New Helix REST service supported features:
The command line tool comes with helix-core package:
Get the command line tool:
git clone https://git-wip-us.apache.org/repos/asf/helix.git cd helix git checkout tags/helix-0.9.4 ./build cd helix-rest/target/helix-rest-pkg/bin chmod +x *.sh
Get help:
./run-rest-admin.sh --help
Start the REST server
./run-rest-admin.sh --port 1234 --zkSvr localhost:2121
Helix REST 2.0 endpoint will start with /admin/v2 prefix, and the rest will mostly follow the current URL convention. This allows us to support v2.0 endpoint at the same time with the current Helix web interface. Some sample v2.0 endpoints would look like the following:
curl -X GET http://localhost:12345/admin/v2/clusters curl -X POST http://localhost:12345/admin/v2/clusters/myCluster curl -X POST http://localhost:12345/admin/v2/clusters/myCluster?command=activate&supercluster=controler_cluster curl http://localhost:12345/admin/v2/clusters/myCluster/resources/myResource/IdealState
“/clusters”
$curl http://localhost:1234/admin/v2/clusters { "clusters" : [ "cluster1", "cluster2", "cluster3"] }
“/clusters/{clusterName}”
Represents a helix cluster with name {clusterName}
GET -- return the cluster info. Example: curl http://localhost:1234/admin/v2/clusters/myCluster
$curl http://localhost:1234/admin/v2/clusters/myCluster { "id" : "myCluster", "paused" : true, "disabled" : true, "controller" : "helix.apache.org:1234", "instances" : [ "aaa.helix.apache.org:1234", "bbb.helix.apache.org:1234" ], "liveInstances" : ["aaa.helix.apache.org:1234"], "resources" : [ "resource1", "resource2", "resource3" ], "stateModelDefs" : [ "MasterSlave", "LeaderStandby", "OnlineOffline" ] }
PUT – create a new cluster with {clusterName}, it returns 200 if the cluster already exists. Example: curl -X PUT http://localhost:1234/admin/v2/clusters/myCluster
DELETE – delete this cluster. Example: curl -X DELETE http://localhost:1234/admin/v2/clusters/myCluster
activate -- Link this cluster to a Helix super (controller) cluster, i.e, add the cluster as a resource to the super cluster. Example: curl -X POST http://localhost:1234/admin/v2/clusters/myCluster?command=activate&superCluster=myCluster
expand -- In the case that a set of new node is added in the cluster, use this command to balance the resources on the existing instances to new added instances. Example: curl -X POST http://localhost:1234/admin/v2/clusters/myCluster?command=expand
enable – enable/resume the cluster. Example: curl -X POST http://localhost:1234/admin/v2/clusters/myCluster?command=enable
disable – disable/pause the cluster. Example: curl -X POST http://localhost:1234/admin/v2/clusters/myCluster?command=disable
“/clusters/{clusterName}/configs”
$curl http://localhost:1234/admin/v2/clusters/myCluster/configs { "id" : "myCluster", "simpleFields" : { "PERSIST_BEST_POSSIBLE_ASSIGNMENT" : "true" }, "listFields" : { }, "mapFields" : { } }
$curl -X POST -H "Content-Type: application/json" http://localhost:1234/admin/v2/clusters/myCluster/configs?command=update -d ' { "id" : "myCluster", "simpleFields" : { "PERSIST_BEST_POSSIBLE_ASSIGNMENT" : "true" }, "listFields" : { "disabledPartition" : ["p1", "p2", "p3"] }, "mapFields" : { } }'
delete -- Remove the entries included in the input from current config.
$curl -X POST -H "Content-Type: application/json" http://localhost:1234/admin/v2/clusters/myCluster/configs?command=update -d ' { "id" : "myCluster", "simpleFields" : { }, "listFields" : { "disabledPartition" : ["p1", "p3"] }, "mapFields" : { } }'
“/clusters/{clusterName}/controller”
$curl http://localhost:1234/admin/v2/clusters/myCluster/controller { "id" : "myCluster", "controller" : "test.helix.apache.org:1234", "HELIX_VERSION":"0.9.4", "LIVE_INSTANCE":"16261@test.helix.apache.org:1234", "SESSION_ID":"35ab496aba54c99" }
“/clusters/{clusterName}/controller/errors”
“/clusters/{clusterName}/controller/history”
$curl http://localhost:1234/admin/v2/clusters/myCluster/controller/history { "id" : "myCluster", "history" [ "{DATE=2017-03-21-16:57:14, CONTROLLER=test1.helix.apache.org:1234, TIME=1490115434248}", "{DATE=2017-03-27-22:35:16, CONTROLLER=test3.helix.apache.org:1234, TIME=1490654116484}", "{DATE=2017-03-27-22:35:24, CONTROLLER=test2.helix.apache.org:1234, TIME=1490654124926}" ] }
/clusters/{clusterName}/controller/messages"
$curl http://localhost:1234/admin/v2/clusters/myCluster/controller/messages { "id" : "myCluster", "count" : 5, "messages" [ "0b8df4f2-776c-4325-96e7-8fad07bd9048", "13a8c0af-b77e-4f5c-81a9-24fedb62cf58" ] }
“/clusters/{clusterName}/controller/messages/{messageId}”
“/clusters/{clusterName}/statemodeldefs/”
$curl -X POST -H "Content-Type: application/json" http://localhost:1234/admin/v2/clusters/myCluster/statemodeldefs { "id" : "myCluster", "stateModelDefs" : [ "MasterSlave", "LeaderStandby", "OnlineOffline" ] }
“/clusters/{clusterName}/statemodeldefs/{statemodeldef}”
$curl -X POST -H "Content-Type: application/json" http://localhost:1234/admin/v2/clusters/myCluster/statemodeldefs/MasterSlave { "id" : "MasterSlave", "simpleFields" : { "INITIAL_STATE" : "OFFLINE" }, "mapFields" : { "DROPPED.meta" : { "count" : "-1" }, "ERROR.meta" : { "count" : "-1" }, "ERROR.next" : { "DROPPED" : "DROPPED", "OFFLINE" : "OFFLINE" }, "MASTER.meta" : { "count" : "1" }, "MASTER.next" : { "SLAVE" : "SLAVE", "DROPPED" : "SLAVE", "OFFLINE" : "SLAVE" }, "OFFLINE.meta" : { "count" : "-1" }, "OFFLINE.next" : { "SLAVE" : "SLAVE", "MASTER" : "SLAVE", "DROPPED" : "DROPPED" }, "SLAVE.meta" : { "count" : "R" }, "SLAVE.next" : { "MASTER" : "MASTER", "DROPPED" : "OFFLINE", "OFFLINE" : "OFFLINE" } }, "listFields" : { "STATE_PRIORITY_LIST" : [ "MASTER", "SLAVE", "OFFLINE", "DROPPED", "ERROR" ], "STATE_TRANSITION_PRIORITYLIST" : [ "MASTER-SLAVE", "SLAVE-MASTER", "OFFLINE-SLAVE", "SLAVE-OFFLINE", "OFFLINE-DROPPED" ] } }
“/clusters/{clusterName}/resources”
$curl http://localhost:1234/admin/v2/clusters/myCluster/resources { "id" : "myCluster", "idealstates" : [ "idealstate1", "idealstate2", "idealstate3" ], "externalviews" : [ "idealstate1", "idealstate3" ] }
“/clusters/{clusterName}/resources/{resourceName}”
$curl http://localhost:1234/admin/v2/clusters/myCluster/resources/resource1 { "id" : "resource1", "resourceConfig" : {}, "idealState" : {}, "externalView" : {} }
$curl -X PUT -H "Content-Type: application/json" http://localhost:1234/admin/v2/clusters/myCluster/resources/myResource -d ' { "id":"myResource", "simpleFields":{ "STATE_MODEL_FACTORY_NAME":"DEFAULT" ,"EXTERNAL_VIEW_DISABLED":"true" ,"NUM_PARTITIONS":"1" ,"REBALANCE_MODE":"TASK" ,"REPLICAS":"1" ,"IDEAL_STATE_MODE":"AUTO" ,"STATE_MODEL_DEF_REF":"Task" ,"REBALANCER_CLASS_NAME":"org.apache.helix.task.WorkflowRebalancer" } }'
“/clusters/{clusterName}/resources/{resourceName}/idealState”
$curl http://localhost:1234/admin/v2/clusters/myCluster/resources/myResource/idealState { "id":"myResource" ,"simpleFields":{ "IDEAL_STATE_MODE":"AUTO" ,"NUM_PARTITIONS":"2" ,"REBALANCE_MODE":"SEMI_AUTO" ,"REPLICAS":"2" ,"STATE_MODEL_DEF_REF":"MasterSlave" } ,"listFields":{ "myResource_0":["host1", "host2"] ,"myResource_1":["host2", "host1"] } ,"mapFields":{ "myResource_0":{ "host1":"MASTER" ,"host2":"SLAVE" } ,"myResource_1":{ "host1":"SLAVE" ,"host2":"MASTER" } } }
“/clusters/{clusterName}/resources/{resourceName}/externalView”
$curl http://localhost:1234/admin/v2/clusters/myCluster/resources/myResource/externalView { "id":"myResource" ,"simpleFields":{ "IDEAL_STATE_MODE":"AUTO" ,"NUM_PARTITIONS":"2" ,"REBALANCE_MODE":"SEMI_AUTO" ,"REPLICAS":"2" ,"STATE_MODEL_DEF_REF":"MasterSlave" } ,"listFields":{ "myResource_0":["host1", "host2"] ,"myResource_1":["host2", "host1"] } ,"mapFields":{ "myResource_0":{ "host1":"MASTER" ,"host2":"OFFLINE" } ,"myResource_1":{ "host1":"SLAVE" ,"host2":"MASTER" } } }
“/clusters/{clusterName}/resources/{resourceName}/configs”
$curl http://localhost:1234/admin/v2/clusters/myCluster/resources/myResource/configs { "id":"myDB" "UserDefinedProperty" : "property" }
“/clusters/{clusterName}/instances”
$curl http://localhost:1234/admin/v2/clusters/myCluster/instances { "id" : "myCluster", "instances" : [ "host1", "host2", "host3", "host4"], "online" : ["host1", "host4"], "disabled" : ["host2"] }
$curl -X POST -H "Content-Type: application/json" http://localhost:1234/admin/v2/clusters/myCluster/instances/command=enable -d { "instances" : [ "host1", "host3" ] } $curl -X POST -H "Content-Type: application/json" http://localhost:1234/admin/v2/clusters/myCluster/instances/command=disable -d { "instances" : [ "host2", "host4" ] }
“/clusters/{clusterName}/instances/{instanceName}”
$curl http://localhost:1234/admin/v2/clusters/myCluster/instances/host_1234 { "id" : "host_1234", "configs" : { "HELIX_ENABLED" : "true", "HELIX_HOST" : "host", "HELIX_PORT" : "1234", "HELIX_DISABLED_PARTITION" : [ ] } "liveInstance" : { "HELIX_VERSION":"0.6.6.3", "LIVE_INSTANCE":"4526@host", "SESSION_ID":"359619c2d7efc14" } }
$curl -X PUT -H "Content-Type: application/json" http://localhost:1234/admin/v2/clusters/myCluster/instances/host_1234 -d ' { "id" : "host_1234", "simpleFields" : { "HELIX_ENABLED" : "true", "HELIX_HOST" : "host", "HELIX_PORT" : "1234", } }'
There‘s one important restriction for this operation: the {instanceName} should match exactly HELIX_HOST + “_” + HELIX_PORT. For example, if host is localhost, and port is 1234, the instance name should be localhost_1234. Otherwise, the response won’t contain any error but the configurations are not able to be filled in.
DELETE - delete the instance. Example: curl -X DELETE http://localhost:1234/admin/v2/clusters/myCluster/instances/host_1234
enable - enable the instance. Example: curl -X POST http://localhost:1234/admin/v2/clusters/myCluster/instances/host_1234?command=enable
disable - disable the instance. Example: curl -X POST http://localhost:1234/admin/v2/clusters/myCluster/instances/host_1234?command=disable
addInstanceTag - add tags to this instance.
$curl -X POST -H "Content-Type: application/json" http://localhost:1234/admin/v2/clusters/myCluster/instances/host_1234?command=addInstanceTag -d ' { "id" : "host_1234", "instanceTags" : [ "tag_1", "tag_2, "tag_3" ] }'
$curl -X POST -H "Content-Type: application/json" http://localhost:1234/admin/v2/clusters/myCluster/instances/host_1234?command=removeInstanceTag -d ' { "id" : "host_1234", "instanceTags" : [ "tag_1", "tag_2, "tag_3" ] }'
“/clusters/{clusterName}/instances/{instanceName}/resources”
$curl http://localhost:1234/admin/v2/clusters/myCluster/instances/host_1234/resources { "id" : "host_1234", "resources" [ "myResource1", "myResource2", "myResource3"] }
“/clusters/{clusterName}/instances/{instanceName}/resources/{resource}”
$curl http://localhost:1234/admin/v2/clusters/myCluster/instances/localhost_1234/resources/myResource1 { "id":"myResource1" ,"simpleFields":{ "STATE_MODEL_DEF":"MasterSlave" ,"STATE_MODEL_FACTORY_NAME":"DEFAULT" ,"BUCKET_SIZE":"0" ,"SESSION_ID":"359619c2d7f109b" } ,"listFields":{ } ,"mapFields":{ "myResource1_2":{ "CURRENT_STATE":"SLAVE" ,"INFO":"" } ,"myResource1_3":{ "CURRENT_STATE":"MASTER" ,"INFO":"" } ,"myResource1_0":{ "CURRENT_STATE":"MASTER" ,"INFO":"" } ,"myResource1_1":{ "CURRENT_STATE":"SLAVE" ,"INFO":"" } } }
“/clusters/{clusterName}/instances/{instanceName}/configs”
$curl http://localhost:1234/admin/v2/clusters/myCluster/instances/host_1234/configs { "id":"host_1234" "configs" : { "HELIX_ENABLED" : "true", "HELIX_HOST" : "host" "HELIX_PORT" : "1234", "HELIX_DISABLED_PARTITION" : [ ] }
$curl -X PUT -H "Content-Type: application/json" http://localhost:1234/admin/v2/clusters/myCluster/instances/host_1234/configs { "id":"host_1234" "configs" : { "HELIX_ENABLED" : "true", "HELIX_HOST" : "host" "HELIX_PORT" : "1234", "HELIX_DISABLED_PARTITION" : [ ] }
“/clusters/{clusterName}/instances/{instanceName}/errors”
$curl http://localhost:1234/admin/v2/clusters/myCluster/instances/host_1234/errors { "id":"host_1234" "errors":{ "35sfgewngwese":{ "resource1":["p1","p2","p5"], "resource2":["p2","p7"] } } }
“/clusters/{clusterName}/instances/{instanceName}/errors/{sessionId}/{resourceName}/{partitionName}”
$curl http://localhost:1234/admin/v2/clusters/myCluster/instances/host_1234/errors/35sfgewngwese/resource1/p1 { "id":"35sfgewngwese_resource1" ,"simpleFields":{ } ,"listFields":{ } ,"mapFields":{ "HELIX_ERROR 20170521-070822.000561 STATE_TRANSITION b819a34d-41b5-4b42-b497-1577501eeecb":{ "AdditionalInfo":"Exception while executing a state transition task ..." ,"MSG_ID":"4af79e51-5f83-4892-a271-cfadacb0906f" ,"Message state":"READ" } } }
“/clusters/{clusterName}/instances/{instanceName}/history”
$curl http://localhost:1234/admin/v2/clusters/myCluster/instances/host_1234/history { "id": "host_1234", "LAST_OFFLINE_TIME": "183948792", "HISTORY": [ "{DATE=2017-03-02T19:25:18:915, SESSION=459014c82ef3f5b, TIME=1488482718915}", "{DATE=2017-03-10T22:24:53:246, SESSION=15982390e5d5c91, TIME=1489184693246}", "{DATE=2017-03-11T02:03:52:776, SESSION=15982390e5d5d85, TIME=1489197832776}", "{DATE=2017-03-13T18:15:00:778, SESSION=15982390e5d678d, TIME=1489428900778}", "{DATE=2017-03-21T02:47:57:281, SESSION=459014c82effa82, TIME=1490064477281}", "{DATE=2017-03-27T14:51:06:802, SESSION=459014c82f01a07, TIME=1490626266802}", "{DATE=2017-03-30T00:05:08:321, SESSION=5590151804e2c78, TIME=1490832308321}", "{DATE=2017-03-30T01:17:34:339, SESSION=2591d53b0421864, TIME=1490836654339}", "{DATE=2017-03-30T17:31:09:880, SESSION=2591d53b0421b2a, TIME=1490895069880}", "{DATE=2017-03-30T18:05:38:220, SESSION=359619c2d7f109b, TIME=1490.9.438220}" ] }
“/clusters/{clusterName}/instances/{instanceName}/messages”
$curl http://localhost:1234/admin/v2/clusters/myCluster/instances/host_1234/messages { "id": "host_1234", "new_messages": ["0b8df4f2-776c-4325-96e7-8fad07bd9048", "13a8c0af-b77e-4f5c-81a9-24fedb62cf58"], "read_messages": ["19887b07-e9b8-4fa6-8369-64146226c454"] "total_message_count" : 100, "read_message_count" : 50 }
"/clusters/{clusterName}/instances/{instanceName}/messages/{messageId}
$curl http://localhost:1234/admin/v2/clusters/myCluster/instances/localhost_1234/messages/0b8df4f2-776c-4325-96e7-8fad07bd9048 { "id": "0b8df4f2-776c-4325-96e7-8fad07bd9048", "CREATE_TIMESTAMP":"1489997469400", "ClusterEventName":"messageChange", "FROM_STATE":"OFFLINE", "MSG_ID":"0b8df4f2-776c-4325-96e7-8fad07bd9048", "MSG_STATE":"new", "MSG_TYPE":"STATE_TRANSITION", "PARTITION_NAME":"Resource1_243", "RESOURCE_NAME":"Resource1", "SRC_NAME":"controller_1234", "SRC_SESSION_ID":"15982390e5d5a76", "STATE_MODEL_DEF":"LeaderStandby", "STATE_MODEL_FACTORY_NAME":"myFactory", "TGT_NAME":"host_1234", "TGT_SESSION_ID":"459014c82efed9b", "TO_STATE":"DROPPED" }
“/clusters/{clusterName}/instances/{instanceName}/healthreports”
$curl http://localhost:1234/admin/v2/clusters/myCluster/instances/host_1234/healthreports { "id" : "host_1234", "healthreports" [ "report1", "report2", "report3" ] }
“/clusters/{clusterName}/instances/{instanceName}/healthreports/{reportName}”
$curl http://localhost:1234/admin/v2/clusters/myCluster/instances/host_1234/healthreports/ClusterStateStats { "id":"ClusterStateStats" ,"simpleFields":{ "CREATE_TIMESTAMP":"1466753504476" ,"TimeStamp":"1466753504476" } ,"listFields":{ } ,"mapFields":{ "UserDefinedData":{ "Data1":"0" ,"Data2":"0.0" } } }
“/clusters/{clusterName}/workflows”
{ "Workflows" : [ "Workflow1", "Workflow2" ] }
“/clusters/{clusterName}/workflows/{workflowName}”
{ "id" : "Workflow1", "WorkflowConfig" : { "Expiry" : "43200000", "FailureThreshold" : "0", "IsJobQueue" : "true", "LAST_PURGE_TIME" : "1490820801831", "LAST_SCHEDULED_WORKFLOW" : "Workflow1_20170329T000000", "ParallelJobs" : "1", "RecurrenceInterval" : "1", "RecurrenceUnit" : "DAYS", "START_TIME" : "1482176880535", "STATE" : "STOPPED", "StartTime" : "12-19-2016 00:00:00", "TargetState" : "START", "Terminable" : "false", "capacity" : "500" }, "WorkflowContext" : { "JOB_STATES": { "Job1": "COMPLETED", "Job2": "COMPLETED" }, "StartTime": { "Job1": "1490741582339", "Job2": "1490741580204" }, "FINISH_TIME": "1490741659135", "START_TIME": "1490741580196", "STATE": "COMPLETED" }, "Jobs" : ["Job1","Job2","Job3"], "ParentJobs" : { "Job1":["Job2", "Job3"], "Job2":["Job3"] } }
“/clusters/{clusterName}/workflows/{workflowName}/configs”
{ "id": "Workflow1", "Expiry" : "43200000", "FailureThreshold" : "0", "IsJobQueue" : "true", "START_TIME" : "1482176880535", "StartTime" : "12-19-2016 00:00:00", "TargetState" : "START", "Terminable" : "false", "capacity" : "500" }
“/clusters/{clusterName}/workflows/{workflowName}/context”
{ "id": "WorkflowContext", "JOB_STATES": { "Job1": "COMPLETED", "Job2": "COMPLETED" }, "StartTime": { "Job1": "1490741582339", "Job2": "1490741580204" }, "FINISH_TIME": "1490741659135", "START_TIME": "1490741580196", "STATE": "COMPLETED" }
“/clusters/{clusterName}/workflows/{workflowName}/jobs”
{ "id":"Jobs" "Jobs":["Job1","Job2","Job3"] }
“/clusters/{clusterName}/workflows/{workflowName}/jobs/{jobName}”
{ "id":"Job1" "JobConfig":{ "WorkflowID":"Workflow1", "IgnoreDependentJobFailure":"false", "MaxForcedReassignmentsPerTask":"3" }, "JobContext":{ "START_TIME":"1491005863291", "FINISH_TIME":"149101.0.0612", "Tasks":[ { "id":"0", "ASSIGNED_PARTICIPANT":"P1", "FINISH_TIME":"1491005898905" "INFO":"" "NUM_ATTEMPTS":"1" "START_TIME":"1491005863307" "STATE":"COMPLETED" "TARGET":"DB_0" }, { "id":"1", "ASSIGNED_PARTICIPANT":"P5", "FINISH_TIME":"1491005895443" "INFO":"" "NUM_ATTEMPTS":"1" "START_TIME":"1491005863307" "STATE":"COMPLETED" "TARGET":"DB_1" } ] } }
“/clusters/{clusterName}/workflows/{workflowName}/jobs/{jobName}/configs”
{ "id":"JobConfig" "WorkflowID":"Workflow1", "IgnoreDependentJobFailure":"false", "MaxForcedReassignmentsPerTask":"3" }
“/clusters/{clusterName}/workflows/{workflowName}/jobs/{jobName}/context”
{ "id":"JobContext": "START_TIME":"1491005863291", "FINISH_TIME":"149101.0.0612", "Tasks":[ { "id":"0", "ASSIGNED_PARTICIPANT":"P1", "FINISH_TIME":"1491005898905" "INFO":"" "NUM_ATTEMPTS":"1" "START_TIME":"1491005863307" "STATE":"COMPLETED" "TARGET":"DB_0" }, { "id":"1", "ASSIGNED_PARTICIPANT":"P5", "FINISH_TIME":"1491005895443" "INFO":"" "NUM_ATTEMPTS":"1" "START_TIME":"1491005863307" "STATE":"COMPLETED" "TARGET":"DB_1" } ] }