This is an automated email from the ASF dual-hosted git repository.

hulee pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/helix.git

commit 2d712e14f35d379af717b7e213853e0c98ae73c3
Author: Junkai Xue <[email protected]>
AuthorDate: Tue Mar 12 12:40:41 2019 -0700

    Dummy check for customized API
    
    For this change, it build the dummy check for customized API. It contains 
following changes:
    1. RESTConfig can setup the customized URL
    2. Define the end point of per participant and per partition.
    3. Add dummy logic that return true for all the check status of customized 
checks.
    
    RB=1596427
    BUG=HELIX-1678
    G=helix-reviewers
    A=jjwang
    
    Signed-off-by: Hunter Lee <[email protected]>
---
 .../main/java/org/apache/helix/ConfigAccessor.java | 21 ++++++++
 .../main/java/org/apache/helix/PropertyKey.java    |  9 ++++
 .../main/java/org/apache/helix/PropertyType.java   |  9 +++-
 .../org/apache/helix/model/HelixConfigScope.java   |  4 +-
 .../java/org/apache/helix/model/RESTConfig.java    | 51 ++++++++++++++++++
 .../apache/helix/util/InstanceValidationUtil.java  | 60 +++++++++++++++++++++-
 .../helix/rest/server/TestInstanceAccessor.java    | 14 +++++
 7 files changed, 164 insertions(+), 4 deletions(-)

diff --git a/helix-core/src/main/java/org/apache/helix/ConfigAccessor.java 
b/helix-core/src/main/java/org/apache/helix/ConfigAccessor.java
index 53f42fb..1d4c5e8 100644
--- a/helix-core/src/main/java/org/apache/helix/ConfigAccessor.java
+++ b/helix-core/src/main/java/org/apache/helix/ConfigAccessor.java
@@ -34,6 +34,7 @@ import org.apache.helix.model.HelixConfigScope;
 import org.apache.helix.model.HelixConfigScope.ConfigScopeProperty;
 import org.apache.helix.manager.zk.ZKUtil;
 import org.apache.helix.model.InstanceConfig;
+import org.apache.helix.model.RESTConfig;
 import org.apache.helix.model.ResourceConfig;
 import org.apache.helix.model.builder.HelixConfigScopeBuilder;
 import org.apache.helix.util.StringTemplate;
@@ -562,6 +563,26 @@ public class ConfigAccessor {
   }
 
   /**
+   * Get ClusterConfig of the given cluster.
+   *
+   * @param clusterName
+   *
+   * @return
+   */
+  public RESTConfig getRESTConfig(String clusterName) {
+    HelixConfigScope scope =
+        new 
HelixConfigScopeBuilder(ConfigScopeProperty.REST).forCluster(clusterName).build();
+    ZNRecord record = getConfigZnRecord(scope);
+
+    if (record == null) {
+      LOG.warn("No config found at " + scope.getZkPath());
+      return null;
+    }
+
+    return new RESTConfig(record);
+  }
+
+  /**
    * Set ClusterConfig of the given cluster.
    * The current Cluster config will be replaced with the given clusterConfig.
    * WARNING: This is not thread-safe or concurrent updates safe.
diff --git a/helix-core/src/main/java/org/apache/helix/PropertyKey.java 
b/helix-core/src/main/java/org/apache/helix/PropertyKey.java
index 03d369b..6350b3c 100644
--- a/helix-core/src/main/java/org/apache/helix/PropertyKey.java
+++ b/helix-core/src/main/java/org/apache/helix/PropertyKey.java
@@ -39,6 +39,7 @@ import org.apache.helix.model.MaintenanceSignal;
 import org.apache.helix.model.Message;
 import org.apache.helix.model.ParticipantHistory;
 import org.apache.helix.model.PauseSignal;
+import org.apache.helix.model.RESTConfig;
 import org.apache.helix.model.ResourceConfig;
 import org.apache.helix.model.StateModelDefinition;
 import org.apache.helix.model.StatusUpdate;
@@ -779,6 +780,14 @@ public class PropertyKey {
       return new PropertyKey(PropertyType.WORKFLOWCONTEXT, 
WorkflowContext.class, _clusterName,
           workflowName);
     }
+
+    /**
+     * Get a property key associated with {@link ResourceConfig}
+     * @return {@link PropertyKey}
+     */
+    public PropertyKey restConfig() {
+      return new PropertyKey(RESTCONFIGS, RESTConfig.class, _clusterName);
+    }
   }
 
   /**
diff --git a/helix-core/src/main/java/org/apache/helix/PropertyType.java 
b/helix-core/src/main/java/org/apache/helix/PropertyType.java
index 2381acc..e234a3b 100644
--- a/helix-core/src/main/java/org/apache/helix/PropertyType.java
+++ b/helix-core/src/main/java/org/apache/helix/PropertyType.java
@@ -27,7 +27,8 @@ enum Type {
   INSTANCE,
   CONTROLLER,
   RESOURCE,
-  TASK
+  TASK,
+  REST
 }
 
 /**
@@ -73,7 +74,11 @@ public enum PropertyType {
   WORKFLOW_CONFIG(Type.TASK, true, false, false, false, false),
   WORKFLOW_CONTEXT(Type.TASK, true, false, false, false, false),
   JOB_CONFIG(Type.TASK, true, false, false, false, false),
-  JOB_CONTEXT(Type.TASK, true, false, false, false, false);
+  JOB_CONTEXT(Type.TASK, true, false, false, false, false),
+
+  // REST PROPERTIES
+  RESTCONFIGS(Type.REST, true, false, false, false, true);
+
 
   // @formatter:on
 
diff --git 
a/helix-core/src/main/java/org/apache/helix/model/HelixConfigScope.java 
b/helix-core/src/main/java/org/apache/helix/model/HelixConfigScope.java
index 9d3b41a..7c5c91d 100644
--- a/helix-core/src/main/java/org/apache/helix/model/HelixConfigScope.java
+++ b/helix-core/src/main/java/org/apache/helix/model/HelixConfigScope.java
@@ -35,7 +35,8 @@ public class HelixConfigScope {
     PARTICIPANT(2, 0),
     RESOURCE(2, 0),
     PARTITION(2, 1),
-    CONSTRAINT(2, 0);
+    CONSTRAINT(2, 0),
+    REST(2, 0);
 
     final int _zkPathArgNum;
     final int _mapKeyArgNum;
@@ -82,6 +83,7 @@ public class HelixConfigScope {
     template.addEntry(ConfigScopeProperty.CLUSTER, 1, 
"/{clusterName}/CONFIGS/CLUSTER");
     template.addEntry(ConfigScopeProperty.PARTICIPANT, 1, 
"/{clusterName}/CONFIGS/PARTICIPANT");
     template.addEntry(ConfigScopeProperty.RESOURCE, 1, 
"/{clusterName}/CONFIGS/RESOURCE");
+    template.addEntry(ConfigScopeProperty.REST, 2, 
"/{clusterName}/CONFIGS/REST/{clusterName}");
   }
 
   final ConfigScopeProperty _type;
diff --git a/helix-core/src/main/java/org/apache/helix/model/RESTConfig.java 
b/helix-core/src/main/java/org/apache/helix/model/RESTConfig.java
new file mode 100644
index 0000000..a47226c
--- /dev/null
+++ b/helix-core/src/main/java/org/apache/helix/model/RESTConfig.java
@@ -0,0 +1,51 @@
+package org.apache.helix.model;
+
+import org.apache.helix.HelixProperty;
+import org.apache.helix.ZNRecord;
+
+public class RESTConfig extends HelixProperty {
+  public enum RESTConfigProperty {
+    CUSTOMIZED_HEALTH_URL // User customized URL for getting participant 
health status or partition
+                          // health status.
+  }
+
+  /**
+   * Instantiate REST config for a specific cluster
+   * @param cluster the cluster identifier
+   */
+  public RESTConfig(String cluster) {
+    super(cluster);
+  }
+
+  /**
+   * Instantiate REST config with a pre-populated record
+   *
+   * @param record a ZNRecord corresponding to a cluster configuration
+   */
+  public RESTConfig(ZNRecord record) {
+    super(record);
+  }
+
+  /**
+   * Set up the user defined URL for check per participant health / per 
partition health by combine
+   * URL and final endpoint. It must ended without "/"
+   *
+   * eg: http://*:12345/customized/path/check
+   *
+   * @param customizedHealthURL
+   */
+  public void setCustomizedHealthURL(String customizedHealthURL) {
+    _record.setSimpleField(RESTConfigProperty.CUSTOMIZED_HEALTH_URL.name(), 
customizedHealthURL);
+  }
+
+  /**
+   * Get user defined URL to construct per participant health / partition 
health
+   * Return null if it does not exist.
+   *
+   * @return
+   */
+  public String getCustomizedHealthURL() {
+    return 
_record.getSimpleField(RESTConfigProperty.CUSTOMIZED_HEALTH_URL.name());
+  }
+
+}
diff --git 
a/helix-core/src/main/java/org/apache/helix/util/InstanceValidationUtil.java 
b/helix-core/src/main/java/org/apache/helix/util/InstanceValidationUtil.java
index b701864..81266c2 100644
--- a/helix-core/src/main/java/org/apache/helix/util/InstanceValidationUtil.java
+++ b/helix-core/src/main/java/org/apache/helix/util/InstanceValidationUtil.java
@@ -21,7 +21,6 @@ package org.apache.helix.util;
 
 import java.util.List;
 import java.util.Map;
-
 import org.apache.helix.AccessOption;
 import org.apache.helix.ConfigAccessor;
 import org.apache.helix.HelixDataAccessor;
@@ -32,6 +31,7 @@ import org.apache.helix.model.ClusterConfig;
 import org.apache.helix.model.CurrentState;
 import org.apache.helix.model.InstanceConfig;
 import org.apache.helix.model.LiveInstance;
+import org.apache.helix.model.RESTConfig;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -44,6 +44,11 @@ import org.slf4j.LoggerFactory;
 public class InstanceValidationUtil {
   private static final Logger _logger = 
LoggerFactory.getLogger(InstanceValidationUtil.class);
 
+  public enum HealthStatusType {
+    instanceHealthStatus,
+    partitionHealthStatus
+  }
+  
   private InstanceValidationUtil() {
   }
 
@@ -188,4 +193,57 @@ public class InstanceValidationUtil {
     _logger.warn(String.format("The instance %s is not active", instanceName));
     return false;
   }
+
+  /**
+   * Check the overall health status for instance including:
+   *  1. Per instance health status with application customized key-value 
entries
+   *  2. Sibling partitions (replicas for same partition holding on different 
node
+   *     health status for the entire cluster.
+   *
+   * @param configAccessor
+   * @param clustername
+   * @param hostName
+   * @param customizedInputs
+   * @param partitionHealthMap
+   * @return
+   */
+  public static boolean checkCustomizedHealthStatusForInstance(ConfigAccessor 
configAccessor,
+      String clustername, String hostName, Map<String, String> 
customizedInputs,
+      Map<String, Map<String, String>> partitionHealthMap, Map<String, String> 
instanceHealthMap) {
+    boolean isHealthy = true;
+    RESTConfig restConfig = configAccessor.getRESTConfig(clustername);
+    // If user customized URL is not ready, return true as the check
+    if (restConfig == null || restConfig.getCustomizedHealthURL() == null) {
+      return isHealthy;
+    }
+    // TODO : 1. Call REST with customized URL
+    //        2. Parse mapping result with string -> boolean value and return 
out for per instance
+    //        3. Check sibling nodes for partition health
+    isHealthy =
+        perInstanceHealthCheck(instanceHealthMap) || 
perPartitionHealthCheck(partitionHealthMap);
+
+    return isHealthy;
+  }
+
+  /**
+   * Fetch the health map based on health type: per instance or per partition
+   * Accessor can used for fetching data from ZK for per partition level.
+   * @param URL
+   * @param accessor
+   * @param healthStatusType
+   * @return
+   */
+  public static Map<String, Map<String, String>> 
getHealthMapBasedOnType(String URL,
+      HelixDataAccessor accessor, HealthStatusType healthStatusType) {
+    return null;
+  }
+
+  protected static boolean perInstanceHealthCheck(Map<String, String> 
statusMap) {
+    return true;
+  }
+
+  protected static boolean perPartitionHealthCheck(
+      Map<String, Map<String, String>> partitionHealthMap) {
+    return true;
+  }
 }
diff --git 
a/helix-rest/src/test/java/org/apache/helix/rest/server/TestInstanceAccessor.java
 
b/helix-rest/src/test/java/org/apache/helix/rest/server/TestInstanceAccessor.java
index 858ea89..be47cab 100644
--- 
a/helix-rest/src/test/java/org/apache/helix/rest/server/TestInstanceAccessor.java
+++ 
b/helix-rest/src/test/java/org/apache/helix/rest/server/TestInstanceAccessor.java
@@ -22,6 +22,7 @@ package org.apache.helix.rest.server;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -40,6 +41,7 @@ import org.apache.helix.model.Message;
 import org.apache.helix.rest.server.resources.AbstractResource;
 import org.apache.helix.rest.server.resources.helix.InstanceAccessor;
 import org.apache.helix.rest.server.util.JerseyUriRequestBuilder;
+import org.apache.helix.util.InstanceValidationUtil;
 import org.codehaus.jackson.JsonNode;
 import org.testng.Assert;
 import org.testng.annotations.Test;
@@ -400,4 +402,16 @@ public class TestInstanceAccessor extends 
AbstractTestClass {
         .expectedReturnStatusCode(Response.Status.NOT_FOUND.getStatusCode())
         .format(CLUSTER_NAME, instanceName).post(this, entity);
   }
+
+  public void testCustomizedChecks() {
+    // TODO: This is fake testing. Only validate it returns true value of this 
function.
+    // For future, we need test: 1. mock the input of per participant API 
result to test validate logic
+    //                           2. mock the input of per partition API result 
to test the sibling
+    //                              check logic
+    System.out.println("Start test :" + TestHelper.getTestMethodName());
+    String instanceName = "TestInstance";
+    Assert.assertTrue(InstanceValidationUtil
+        .checkCustomizedHealthStatusForInstance(_configAccessor, CLUSTER_NAME, 
instanceName,
+            Collections.EMPTY_MAP, Collections.EMPTY_MAP, 
Collections.EMPTY_MAP));
+  }
 }

Reply via email to