{"action":"created","comment":{"url":"https://api.github.com/repos/linkedin/ambry/pulls/comments/97672802","pull_request_review_id":18289978,"id":97672802,"diff_hunk":"@@ -0,0 +1,470 @@\n+/**\n+ * Copyright 2016 LinkedIn Corp. All rights reserved.\n+ *\n+ * Licensed under the Apache License, Version 2.0 (the \"License\");\n+ * you may not use this file except in compliance with the License.\n+ * You may obtain a copy of the License at\n+ *\n+ * http://www.apache.org/licenses/LICENSE-2.0\n+ *\n+ * Unless required by applicable law or agreed to in writing, software\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+ */\n+package com.github.ambry.clustermap;\n+\n+import com.github.ambry.config.ClusterMapConfig;\n+import com.github.ambry.config.VerifiableProperties;\n+import com.github.ambry.tools.util.ToolUtils;\n+import com.github.ambry.utils.Utils;\n+import java.io.File;\n+import java.io.IOException;\n+import java.util.ArrayList;\n+import java.util.Arrays;\n+import java.util.Collections;\n+import java.util.HashMap;\n+import java.util.List;\n+import java.util.ListIterator;\n+import java.util.Map;\n+import java.util.Properties;\n+import java.util.TreeMap;\n+import java.util.TreeSet;\n+import joptsimple.ArgumentAcceptingOptionSpec;\n+import joptsimple.OptionParser;\n+import joptsimple.OptionSet;\n+import joptsimple.OptionSpec;\n+import org.apache.helix.HelixAdmin;\n+import org.apache.helix.manager.zk.ZKHelixAdmin;\n+import org.apache.helix.model.IdealState;\n+import org.apache.helix.model.InstanceConfig;\n+import org.apache.helix.model.LeaderStandbySMD;\n+import org.apache.helix.model.builder.AutoModeISBuilder;\n+import org.json.JSONArray;\n+import org.json.JSONException;\n+import org.json.JSONObject;\n+\n+\n+/**\n+ * This tool takes the hardware layout, partition layout and the Zk hosts information json files as input,\n+ * and updates the ZK hosts with the contents of the layout files. It adds all partitions and hosts that have not\n+ * previously been added (so, initially this will bootstrap the cluster information and on an ongoing basis, this can\n+ * add new nodes and partitions).\n+ *\n+ * The existing hardware and partition layout json files will be read in as is.\n+ *\n+ * The ZkLayoutPath argument containing the Zk hosts information in each datacenter should be a json of the\n+ * following example form:\n+ *\n+ * {\n+ *   \"zkHosts\" : [\n+ *     {\n+ *       \"datacenter\":\"dc1\",\n+ *       \"hostname\":\"abc.example.com\",\n+ *       \"port\":\"2199\",\n+ *     },\n+ *     {\n+ *       \"datacenter\":\"dc2\",\n+ *       \"hostname\":\"def.example.com\",\n+ *       \"port\":\"2300\",\n+ *     }\n+ *   ]\n+ * }\n+ *\n+ * This tool should be run from an admin node that has access to the nodes in the hardware layout. The access is\n+ * required because the static {@link ClusterMapManager} that we use to parse the static layout files validates\n+ * these nodes.\n+ *\n+ * The tool does the following:\n+ * 1. Bootstraps a static cluster map by adding nodes and partitions to Helix.\n+ * 2. Upgrades the information with changes in the static clustermap that involve new nodes and new partitions.\n+ *    To avoid over-complicating things, it assumes that the existing partition assignment does not change during an\n+ *    upgrade. Newly added partitions can be distributed in any way (new partitions can have replicas even in\n+ *    previously added nodes).\n+ * 3. Upgrades will also update the partition states if required (READ_WRITE to SEALED or vice versa) for existing\n+ *    partitions.\n+ *\n+ */\n+public class HelixBootstrapUpgradeTool {\n+  private final ClusterMapManager staticClusterMap;\n+  private final Map<String, String> dataCenterToZkAddress = new HashMap<>();\n+  private final Map<String, HelixAdmin> adminForDc = new HashMap<>();\n+  // A mapping from partitions to Helix resource, populated at the start with what is present in Helix.\n+  private final TreeMap<Long, Long> existingPartitions = new TreeMap<>();\n+  // A set of resources in Helix, populated at the start with what is present in Helix.\n+  private final TreeSet<Long> existingResources = new TreeSet<>();\n+  private final String localDc;\n+  private final String clusterName;\n+\n+  static final int MAX_PARTITIONS_PER_RESOURCE = 100;\n+  static final String CAPACITY_STR = \"capacityInBytes\";\n+  static final String REPLICAS_STR = \"Replicas\";\n+  static final String REPLICAS_DELIM_STR = \",\";\n+  static final String PORT_STR = \"port\";\n+  static final String SSLPORT_STR = \"sslPort\";\n+  static final String HOSTNAME_STR = \"hostname\";\n+  static final String DATACENTER_STR = \"datacenter\";\n+  static final String RACKID_STR = \"rackId\";\n+  static final String SEALED_STR = \"SEALED\";\n+  static final String ZKHOSTS_STR = \"zkHosts\";\n+\n+  /**\n+   * @param args takes in three mandatory arguments: the hardware layout path, the partition layout path and the zk\n+   *             layout path.\n+   *             The Zk layout has to be of the following form:\n+   *             {\n+   *               \"zkHosts\" : [\n+   *                 {\n+   *                   \"datacenter\":\"dc1\",\n+   *                   \"hostname\":\"abc.example.com\",\n+   *                   \"port\":\"2199\",\n+   *                 },\n+   *                 {\n+   *                   \"datacenter\":\"dc2\",\n+   *                   \"hostname\":\"def.example.com\",\n+   *                   \"port\":\"2300\",\n+   *                 }\n+   *               ]\n+   *             }\n+   *\n+   *             Also takes in an optional argument that specifies the local datacenter name, so that can be used as\n+   *             the \"reference\" datacenter. If none provided, the tool simply chooses one of the datacenters in the\n+   *             layout as the reference datacenter.\n+   */\n+  public static void main(String args[]) throws Exception {\n+    OptionParser parser = new OptionParser();\n+\n+    ArgumentAcceptingOptionSpec<String> hardwareLayoutPathOpt =\n+        parser.accepts(\"hardwareLayoutPath\", \"The path to the hardware layout json file\")\n+            .withRequiredArg()\n+            .describedAs(\"hardware_layout_path\")\n+            .ofType(String.class);\n+\n+    ArgumentAcceptingOptionSpec<String> partitionLayoutPathOpt =\n+        parser.accepts(\"partitionLayoutPath\", \"The path to the partition layout json file\")\n+            .withRequiredArg()\n+            .describedAs(\"partition_layout_path\")\n+            .ofType(String.class);\n+\n+    ArgumentAcceptingOptionSpec<String> zkLayoutPathOpt = parser.accepts(\"zkLayoutPath\",\n+        \"The path to the json file containing zookeeper connect info. This should\" + \" be of the following form: \\n{\\n\"\n+            + \"  \\\"zkHosts\\\" : [\\n\" + \"     {\\n\" + \"       \\\"datacenter\\\":\\\"dc1\\\",\\n\"\n+            + \"       \\\"hostname\\\":\\\"abc.example.com\\\",\\n\" + \"       \\\"port\\\":\\\"2199\\\",\\n\" + \"     },\\n\" + \"     {\\n\"\n+            + \"       \\\"datacenter\\\":\\\"dc2\\\",\\n\" + \"       \\\"hostname\\\":\\\"def.example.com\\\",\\n\"\n+            + \"       \\\"port\\\":\\\"2300\\\",\\n\" + \"     }\\n\" + \"  ]\\n\" + \"}\").\n+        withRequiredArg().\n+        describedAs(\"zk_connect_info_path\").\n+        ofType(String.class);\n+\n+    ArgumentAcceptingOptionSpec<String> localDcOpt = parser.accepts(\"localDc\", \"The local datacenter name\")\n+        .withRequiredArg()\n+        .describedAs(\"local_dc\")\n+        .ofType(String.class);\n+\n+    OptionSet options = parser.parse(args);\n+    String hardwareLayoutPath = options.valueOf(hardwareLayoutPathOpt);\n+    String partitionLayoutPath = options.valueOf(partitionLayoutPathOpt);\n+    String zkLayoutPath = options.valueOf(zkLayoutPathOpt);\n+    ArrayList<OptionSpec> listOpt = new ArrayList<>();\n+    listOpt.add(hardwareLayoutPathOpt);\n+    listOpt.add(partitionLayoutPathOpt);\n+    listOpt.add(zkLayoutPathOpt);\n+    ToolUtils.ensureOrExit(listOpt, options, parser);\n+    bootstrapOrUpgrade(hardwareLayoutPath, partitionLayoutPath, zkLayoutPath, options.valueOf(localDcOpt));\n+  }\n+\n+  /**\n+   * Takes in the path to the files that make up the static cluster map and adds or updates the cluster map information\n+   * in Helix to make the two consistent.\n+   * @param hardwareLayoutPath the path to the hardware layout file.\n+   * @param partitionLayoutPath the path to the partition layout file.\n+   * @param zkLayoutPath the path to the zookeeper layout file.\n+   * @param localDc the name of the local datacenter. This can be null.\n+   * @throws IOException if there is an error reading a file.\n+   * @throws JSONException if there is an error parsing the JSON content in any of the files.\n+   */\n+  static void bootstrapOrUpgrade(String hardwareLayoutPath, String partitionLayoutPath, String zkLayoutPath,\n+      String localDc) throws IOException, JSONException {\n+    HelixBootstrapUpgradeTool clusterMapToHelixMapper =\n+        new HelixBootstrapUpgradeTool(hardwareLayoutPath, partitionLayoutPath, zkLayoutPath, localDc);\n+    clusterMapToHelixMapper.updateClusterMapInHelix();\n+  }","path":"ambry-tools/src/main/java/com.github.ambry/clustermap/HelixBootstrapUpgradeTool.java","position":190,"original_position":190,"commit_id":"1fdb745be3f07f58418e3645444386edd5f354e2","original_commit_id":"1fdb745be3f07f58418e3645444386edd5f354e2","user":{"login":"nsivabalan","id":513218,"avatar_url":"https://avatars.githubusercontent.com/u/513218?v=3","gravatar_id":"","url":"https://api.github.com/users/nsivabalan","html_url":"https://github.com/nsivabalan","followers_url":"https://api.github.com/users/nsivabalan/followers","following_url":"https://api.github.com/users/nsivabalan/following{/other_user}","gists_url":"https://api.github.com/users/nsivabalan/gists{/gist_id}","starred_url":"https://api.github.com/users/nsivabalan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nsivabalan/subscriptions","organizations_url":"https://api.github.com/users/nsivabalan/orgs","repos_url":"https://api.github.com/users/nsivabalan/repos","events_url":"https://api.github.com/users/nsivabalan/events{/privacy}","received_events_url":"https://api.github.com/users/nsivabalan/received_events","type":"User","site_admin":false},"body":"after upgrade, can we close all the HelixAdmins that are currently open","created_at":"2017-01-24T22:58:51Z","updated_at":"2017-01-24T22:58:51Z","html_url":"https://github.com/linkedin/ambry/pull/523#discussion_r97672802","pull_request_url":"https://api.github.com/repos/linkedin/ambry/pulls/523","_links":{"self":{"href":"https://api.github.com/repos/linkedin/ambry/pulls/comments/97672802"},"html":{"href":"https://github.com/linkedin/ambry/pull/523#discussion_r97672802"},"pull_request":{"href":"https://api.github.com/repos/linkedin/ambry/pulls/523"}}},"pull_request":{"url":"https://api.github.com/repos/linkedin/ambry/pulls/523","id":101504056,"html_url":"https://github.com/linkedin/ambry/pull/523","diff_url":"https://github.com/linkedin/ambry/pull/523.diff","patch_url":"https://github.com/linkedin/ambry/pull/523.patch","issue_url":"https://api.github.com/repos/linkedin/ambry/issues/523","number":523,"state":"open","locked":false,"title":"Add a tool to map static cluster map information into Helix","user":{"login":"pnarayanan","id":1454915,"avatar_url":"https://avatars.githubusercontent.com/u/1454915?v=3","gravatar_id":"","url":"https://api.github.com/users/pnarayanan","html_url":"https://github.com/pnarayanan","followers_url":"https://api.github.com/users/pnarayanan/followers","following_url":"https://api.github.com/users/pnarayanan/following{/other_user}","gists_url":"https://api.github.com/users/pnarayanan/gists{/gist_id}","starred_url":"https://api.github.com/users/pnarayanan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pnarayanan/subscriptions","organizations_url":"https://api.github.com/users/pnarayanan/orgs","repos_url":"https://api.github.com/users/pnarayanan/repos","events_url":"https://api.github.com/users/pnarayanan/events{/privacy}","received_events_url":"https://api.github.com/users/pnarayanan/received_events","type":"User","site_admin":false},"body":"- Add a tool to bootstrap and, from time to time, upgrade\r\n  cluster map information in Helix from the static clustermap files.\r\n- Adds tests to verify the tool's claims.\r\n- Adds certain functionalities in the test classes of the static\r\n  cluster map to help test the tool.\r\n\r\nPart of #524 \r\n\r\n--\r\nNotes:\r\n* Main changes to be reviewed are in `HelixBootstrapUpgradeTool.java` and `HelixBootstrapUpgradeToolTest.java`.\r\n* Tests cover all of the core functionalities.\r\n* We make use of a recently added [method](https://github.com/apache/helix/commit/0737d7accbf70c78bab72be02a39ad8300266fe1) in Helix. This is available in Helix 0.6.7","created_at":"2017-01-13T19:37:25Z","updated_at":"2017-01-24T22:58:51Z","closed_at":null,"merged_at":null,"merge_commit_sha":"b3d11f43da7347d8e9e3a51d37a6beb6a2a85763","assignee":null,"assignees":[],"milestone":{"url":"https://api.github.com/repos/linkedin/ambry/milestones/4","html_url":"https://github.com/linkedin/ambry/milestone/4","labels_url":"https://api.github.com/repos/linkedin/ambry/milestones/4/labels","id":2251031,"number":4,"title":"Dynamic Cluster Management","description":null,"creator":{"login":"pnarayanan","id":1454915,"avatar_url":"https://avatars.githubusercontent.com/u/1454915?v=3","gravatar_id":"","url":"https://api.github.com/users/pnarayanan","html_url":"https://github.com/pnarayanan","followers_url":"https://api.github.com/users/pnarayanan/followers","following_url":"https://api.github.com/users/pnarayanan/following{/other_user}","gists_url":"https://api.github.com/users/pnarayanan/gists{/gist_id}","starred_url":"https://api.github.com/users/pnarayanan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pnarayanan/subscriptions","organizations_url":"https://api.github.com/users/pnarayanan/orgs","repos_url":"https://api.github.com/users/pnarayanan/repos","events_url":"https://api.github.com/users/pnarayanan/events{/privacy}","received_events_url":"https://api.github.com/users/pnarayanan/received_events","type":"User","site_admin":false},"open_issues":2,"closed_issues":0,"state":"open","created_at":"2017-01-13T19:36:55Z","updated_at":"2017-01-16T04:30:47Z","due_on":null,"closed_at":null},"commits_url":"https://api.github.com/repos/linkedin/ambry/pulls/523/commits","review_comments_url":"https://api.github.com/repos/linkedin/ambry/pulls/523/comments","review_comment_url":"https://api.github.com/repos/linkedin/ambry/pulls/comments{/number}","comments_url":"https://api.github.com/repos/linkedin/ambry/issues/523/comments","statuses_url":"https://api.github.com/repos/linkedin/ambry/statuses/1fdb745be3f07f58418e3645444386edd5f354e2","head":{"label":"pnarayanan:helixTool","ref":"helixTool","sha":"1fdb745be3f07f58418e3645444386edd5f354e2","user":{"login":"pnarayanan","id":1454915,"avatar_url":"https://avatars.githubusercontent.com/u/1454915?v=3","gravatar_id":"","url":"https://api.github.com/users/pnarayanan","html_url":"https://github.com/pnarayanan","followers_url":"https://api.github.com/users/pnarayanan/followers","following_url":"https://api.github.com/users/pnarayanan/following{/other_user}","gists_url":"https://api.github.com/users/pnarayanan/gists{/gist_id}","starred_url":"https://api.github.com/users/pnarayanan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pnarayanan/subscriptions","organizations_url":"https://api.github.com/users/pnarayanan/orgs","repos_url":"https://api.github.com/users/pnarayanan/repos","events_url":"https://api.github.com/users/pnarayanan/events{/privacy}","received_events_url":"https://api.github.com/users/pnarayanan/received_events","type":"User","site_admin":false},"repo":{"id":25383889,"name":"ambry","full_name":"pnarayanan/ambry","owner":{"login":"pnarayanan","id":1454915,"avatar_url":"https://avatars.githubusercontent.com/u/1454915?v=3","gravatar_id":"","url":"https://api.github.com/users/pnarayanan","html_url":"https://github.com/pnarayanan","followers_url":"https://api.github.com/users/pnarayanan/followers","following_url":"https://api.github.com/users/pnarayanan/following{/other_user}","gists_url":"https://api.github.com/users/pnarayanan/gists{/gist_id}","starred_url":"https://api.github.com/users/pnarayanan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pnarayanan/subscriptions","organizations_url":"https://api.github.com/users/pnarayanan/orgs","repos_url":"https://api.github.com/users/pnarayanan/repos","events_url":"https://api.github.com/users/pnarayanan/events{/privacy}","received_events_url":"https://api.github.com/users/pnarayanan/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/pnarayanan/ambry","description":"Immutable blob store","fork":true,"url":"https://api.github.com/repos/pnarayanan/ambry","forks_url":"https://api.github.com/repos/pnarayanan/ambry/forks","keys_url":"https://api.github.com/repos/pnarayanan/ambry/keys{/key_id}","collaborators_url":"https://api.github.com/repos/pnarayanan/ambry/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/pnarayanan/ambry/teams","hooks_url":"https://api.github.com/repos/pnarayanan/ambry/hooks","issue_events_url":"https://api.github.com/repos/pnarayanan/ambry/issues/events{/number}","events_url":"https://api.github.com/repos/pnarayanan/ambry/events","assignees_url":"https://api.github.com/repos/pnarayanan/ambry/assignees{/user}","branches_url":"https://api.github.com/repos/pnarayanan/ambry/branches{/branch}","tags_url":"https://api.github.com/repos/pnarayanan/ambry/tags","blobs_url":"https://api.github.com/repos/pnarayanan/ambry/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/pnarayanan/ambry/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/pnarayanan/ambry/git/refs{/sha}","trees_url":"https://api.github.com/repos/pnarayanan/ambry/git/trees{/sha}","statuses_url":"https://api.github.com/repos/pnarayanan/ambry/statuses/{sha}","languages_url":"https://api.github.com/repos/pnarayanan/ambry/languages","stargazers_url":"https://api.github.com/repos/pnarayanan/ambry/stargazers","contributors_url":"https://api.github.com/repos/pnarayanan/ambry/contributors","subscribers_url":"https://api.github.com/repos/pnarayanan/ambry/subscribers","subscription_url":"https://api.github.com/repos/pnarayanan/ambry/subscription","commits_url":"https://api.github.com/repos/pnarayanan/ambry/commits{/sha}","git_commits_url":"https://api.github.com/repos/pnarayanan/ambry/git/commits{/sha}","comments_url":"https://api.github.com/repos/pnarayanan/ambry/comments{/number}","issue_comment_url":"https://api.github.com/repos/pnarayanan/ambry/issues/comments{/number}","contents_url":"https://api.github.com/repos/pnarayanan/ambry/contents/{+path}","compare_url":"https://api.github.com/repos/pnarayanan/ambry/compare/{base}...{head}","merges_url":"https://api.github.com/repos/pnarayanan/ambry/merges","archive_url":"https://api.github.com/repos/pnarayanan/ambry/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/pnarayanan/ambry/downloads","issues_url":"https://api.github.com/repos/pnarayanan/ambry/issues{/number}","pulls_url":"https://api.github.com/repos/pnarayanan/ambry/pulls{/number}","milestones_url":"https://api.github.com/repos/pnarayanan/ambry/milestones{/number}","notifications_url":"https://api.github.com/repos/pnarayanan/ambry/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/pnarayanan/ambry/labels{/name}","releases_url":"https://api.github.com/repos/pnarayanan/ambry/releases{/id}","deployments_url":"https://api.github.com/repos/pnarayanan/ambry/deployments","created_at":"2014-10-18T01:44:12Z","updated_at":"2016-11-04T00:08:34Z","pushed_at":"2017-01-23T23:06:05Z","git_url":"git://github.com/pnarayanan/ambry.git","ssh_url":"git@github.com:pnarayanan/ambry.git","clone_url":"https://github.com/pnarayanan/ambry.git","svn_url":"https://github.com/pnarayanan/ambry","homepage":null,"size":8429,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"linkedin:master","ref":"master","sha":"1881ac5051d7e2602b2895f636c46f13fdcfc9ae","user":{"login":"linkedin","id":357098,"avatar_url":"https://avatars.githubusercontent.com/u/357098?v=3","gravatar_id":"","url":"https://api.github.com/users/linkedin","html_url":"https://github.com/linkedin","followers_url":"https://api.github.com/users/linkedin/followers","following_url":"https://api.github.com/users/linkedin/following{/other_user}","gists_url":"https://api.github.com/users/linkedin/gists{/gist_id}","starred_url":"https://api.github.com/users/linkedin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/linkedin/subscriptions","organizations_url":"https://api.github.com/users/linkedin/orgs","repos_url":"https://api.github.com/users/linkedin/repos","events_url":"https://api.github.com/users/linkedin/events{/privacy}","received_events_url":"https://api.github.com/users/linkedin/received_events","type":"Organization","site_admin":false},"repo":{"id":13870893,"name":"ambry","full_name":"linkedin/ambry","owner":{"login":"linkedin","id":357098,"avatar_url":"https://avatars.githubusercontent.com/u/357098?v=3","gravatar_id":"","url":"https://api.github.com/users/linkedin","html_url":"https://github.com/linkedin","followers_url":"https://api.github.com/users/linkedin/followers","following_url":"https://api.github.com/users/linkedin/following{/other_user}","gists_url":"https://api.github.com/users/linkedin/gists{/gist_id}","starred_url":"https://api.github.com/users/linkedin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/linkedin/subscriptions","organizations_url":"https://api.github.com/users/linkedin/orgs","repos_url":"https://api.github.com/users/linkedin/repos","events_url":"https://api.github.com/users/linkedin/events{/privacy}","received_events_url":"https://api.github.com/users/linkedin/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/linkedin/ambry","description":"Distributed object store","fork":false,"url":"https://api.github.com/repos/linkedin/ambry","forks_url":"https://api.github.com/repos/linkedin/ambry/forks","keys_url":"https://api.github.com/repos/linkedin/ambry/keys{/key_id}","collaborators_url":"https://api.github.com/repos/linkedin/ambry/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/linkedin/ambry/teams","hooks_url":"https://api.github.com/repos/linkedin/ambry/hooks","issue_events_url":"https://api.github.com/repos/linkedin/ambry/issues/events{/number}","events_url":"https://api.github.com/repos/linkedin/ambry/events","assignees_url":"https://api.github.com/repos/linkedin/ambry/assignees{/user}","branches_url":"https://api.github.com/repos/linkedin/ambry/branches{/branch}","tags_url":"https://api.github.com/repos/linkedin/ambry/tags","blobs_url":"https://api.github.com/repos/linkedin/ambry/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/linkedin/ambry/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/linkedin/ambry/git/refs{/sha}","trees_url":"https://api.github.com/repos/linkedin/ambry/git/trees{/sha}","statuses_url":"https://api.github.com/repos/linkedin/ambry/statuses/{sha}","languages_url":"https://api.github.com/repos/linkedin/ambry/languages","stargazers_url":"https://api.github.com/repos/linkedin/ambry/stargazers","contributors_url":"https://api.github.com/repos/linkedin/ambry/contributors","subscribers_url":"https://api.github.com/repos/linkedin/ambry/subscribers","subscription_url":"https://api.github.com/repos/linkedin/ambry/subscription","commits_url":"https://api.github.com/repos/linkedin/ambry/commits{/sha}","git_commits_url":"https://api.github.com/repos/linkedin/ambry/git/commits{/sha}","comments_url":"https://api.github.com/repos/linkedin/ambry/comments{/number}","issue_comment_url":"https://api.github.com/repos/linkedin/ambry/issues/comments{/number}","contents_url":"https://api.github.com/repos/linkedin/ambry/contents/{+path}","compare_url":"https://api.github.com/repos/linkedin/ambry/compare/{base}...{head}","merges_url":"https://api.github.com/repos/linkedin/ambry/merges","archive_url":"https://api.github.com/repos/linkedin/ambry/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/linkedin/ambry/downloads","issues_url":"https://api.github.com/repos/linkedin/ambry/issues{/number}","pulls_url":"https://api.github.com/repos/linkedin/ambry/pulls{/number}","milestones_url":"https://api.github.com/repos/linkedin/ambry/milestones{/number}","notifications_url":"https://api.github.com/repos/linkedin/ambry/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/linkedin/ambry/labels{/name}","releases_url":"https://api.github.com/repos/linkedin/ambry/releases{/id}","deployments_url":"https://api.github.com/repos/linkedin/ambry/deployments","created_at":"2013-10-25T20:04:54Z","updated_at":"2017-01-24T02:13:58Z","pushed_at":"2017-01-24T22:48:32Z","git_url":"git://github.com/linkedin/ambry.git","ssh_url":"git@github.com:linkedin/ambry.git","clone_url":"https://github.com/linkedin/ambry.git","svn_url":"https://github.com/linkedin/ambry","homepage":"https://github.com/linkedin/ambry/wiki","size":8440,"stargazers_count":800,"watchers_count":800,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":129,"mirror_url":null,"open_issues_count":59,"forks":129,"open_issues":59,"watchers":800,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/linkedin/ambry/pulls/523"},"html":{"href":"https://github.com/linkedin/ambry/pull/523"},"issue":{"href":"https://api.github.com/repos/linkedin/ambry/issues/523"},"comments":{"href":"https://api.github.com/repos/linkedin/ambry/issues/523/comments"},"review_comments":{"href":"https://api.github.com/repos/linkedin/ambry/pulls/523/comments"},"review_comment":{"href":"https://api.github.com/repos/linkedin/ambry/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/linkedin/ambry/pulls/523/commits"},"statuses":{"href":"https://api.github.com/repos/linkedin/ambry/statuses/1fdb745be3f07f58418e3645444386edd5f354e2"}}}}
{"actor":{"display_login":"nsivabalan"}}