helix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From hu...@apache.org
Subject [helix] 11/14: Dummy check for customized API
Date Wed, 22 May 2019 23:41:36 GMT
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 <jxue@linkedin.com>
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 <hulee@linkedin.com>
---
 .../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));
+  }
 }


Mime
View raw message