{"action":"created","comment":{"url":"https://api.github.com/repos/apache/ambari/pulls/comments/209491402","pull_request_review_id":145514388,"id":209491402,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIwOTQ5MTQwMg==","diff_hunk":"@@ -0,0 +1,265 @@\n+/*\n+ * Licensed to the Apache Software Foundation (ASF) under one\n+ * or more contributor license agreements.  See the NOTICE file\n+ * distributed with this work for additional information\n+ * regarding copyright ownership.  The ASF licenses this file\n+ * to you under the Apache License, Version 2.0 (the\n+ * \"License\"); you may not use this file except in compliance\n+ * with the License.  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,\n+ * software distributed under the License is distributed on an\n+ * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n+ * KIND, either express or implied.  See the License for the\n+ * specific language governing permissions and limitations\n+ * under the License.\n+ */\n+package org.apache.ambari.logsearch.config.zookeeper;\n+\n+import com.google.common.base.Splitter;\n+import com.google.common.collect.ImmutableSet;\n+import com.google.gson.Gson;\n+import com.google.gson.GsonBuilder;\n+import org.apache.ambari.logsearch.config.api.LogLevelFilterMonitor;\n+import org.apache.ambari.logsearch.config.api.LogSearchPropertyDescription;\n+import org.apache.ambari.logsearch.config.api.model.loglevelfilter.LogLevelFilter;\n+import org.apache.commons.collections.MapUtils;\n+import org.apache.commons.lang3.StringUtils;\n+import org.apache.curator.RetryPolicy;\n+import org.apache.curator.framework.CuratorFramework;\n+import org.apache.curator.framework.CuratorFrameworkFactory;\n+import org.apache.curator.framework.recipes.cache.TreeCache;\n+import org.apache.curator.framework.recipes.cache.TreeCacheEvent;\n+import org.apache.curator.framework.recipes.cache.TreeCacheListener;\n+import org.apache.curator.retry.RetryForever;\n+import org.apache.curator.retry.RetryUntilElapsed;\n+import org.apache.curator.utils.ZKPaths;\n+import org.apache.zookeeper.ZooDefs;\n+import org.apache.zookeeper.data.ACL;\n+import org.apache.zookeeper.data.Id;\n+import org.slf4j.Logger;\n+import org.slf4j.LoggerFactory;\n+\n+import java.util.ArrayList;\n+import java.util.List;\n+import java.util.Map;\n+import java.util.Set;\n+\n+/**\n+ * Utility functions for handling ZK operation and monitor ZK data for Log Search configuration\n+ */\n+public class LogSearchConfigZKHelper {\n+\n+  private static final Logger LOG = LoggerFactory.getLogger(LogSearchConfigZKHelper.class);\n+\n+  private static final int DEFAULT_SESSION_TIMEOUT = 60000;\n+  private static final int DEFAULT_CONNECTION_TIMEOUT = 30000;\n+  private static final int RETRY_INTERVAL_MS = 10000;\n+  private static final String DEFAULT_ZK_ROOT = \"/logsearch\";\n+  private static final String DATE_FORMAT = \"yyyy-MM-dd'T'HH:mm:ss.SSS\";\n+\n+  @LogSearchPropertyDescription(\n+    name = \"logsearch.config.zk_connect_string\",\n+    description = \"ZooKeeper connection string.\",\n+    examples = {\"localhost1:2181,localhost2:2181/znode\"},\n+    sources = {\"logsearch.properties\", \"logfeeder.properties\"}\n+  )\n+  private static final String ZK_CONNECT_STRING_PROPERTY = \"logsearch.config.zk_connect_string\";\n+\n+  @LogSearchPropertyDescription(\n+    name = \"logsearch.config.zk_acls\",\n+    description = \"ZooKeeper ACLs for handling configs. (read & write)\",\n+    examples = {\"world:anyone:r,sasl:solr:cdrwa,sasl:logsearch:cdrwa\"},\n+    sources = {\"logsearch.properties\", \"logfeeder.properties\"},\n+    defaultValue = \"world:anyone:cdrwa\"\n+  )\n+  private static final String ZK_ACLS_PROPERTY = \"logsearch.config.zk_acls\";\n+\n+  @LogSearchPropertyDescription(\n+    name = \"logsearch.config.zk_root\",\n+    description = \"ZooKeeper root node where the shippers are stored. (added to the connection string)\",\n+    examples = {\"/logsearch\"},\n+    sources = {\"logsearch.properties\", \"logfeeder.properties\"}\n+  )\n+  private static final String ZK_ROOT_NODE_PROPERTY = \"logsearch.config.zk_root\";\n+\n+  @LogSearchPropertyDescription(\n+    name = \"logsearch.config.zk_session_time_out_ms\",\n+    description = \"ZooKeeper session timeout in milliseconds\",\n+    examples = {\"60000\"},\n+    sources = {\"logsearch.properties\", \"logfeeder.properties\"}\n+  )\n+  private static final String ZK_SESSION_TIMEOUT_PROPERTY = \"logsearch.config.zk_session_time_out_ms\";\n+\n+  @LogSearchPropertyDescription(\n+    name = \"logsearch.config.zk_connection_time_out_ms\",\n+    description = \"ZooKeeper connection timeout in milliseconds\",\n+    examples = {\"30000\"},\n+    sources = {\"logsearch.properties\", \"logfeeder.properties\"}\n+  )\n+  private static final String ZK_CONNECTION_TIMEOUT_PROPERTY = \"logsearch.config.zk_connection_time_out_ms\";\n+\n+  @LogSearchPropertyDescription(\n+    name = \"logsearch.config.zk_connection_retry_time_out_ms\",\n+    description = \"The maximum elapsed time for connecting to ZooKeeper in milliseconds. 0 means retrying forever.\",\n+    examples = {\"1200000\"},\n+    sources = {\"logsearch.properties\", \"logfeeder.properties\"}\n+  )\n+  private static final String ZK_CONNECTION_RETRY_TIMEOUT_PROPERTY = \"logsearch.config.zk_connection_retry_time_out_ms\";\n+\n+  private static final long WAIT_FOR_ROOT_SLEEP_SECONDS = 10;\n+\n+  private LogSearchConfigZKHelper() {\n+  }\n+\n+  /**\n+   * Create ZK curator client from a configuration (map holds the configs for that)\n+   */\n+  public static CuratorFramework createZKClient(Map<String, String> properties) {\n+    String root = MapUtils.getString(properties, ZK_ROOT_NODE_PROPERTY, DEFAULT_ZK_ROOT);\n+    LOG.info(\"Connecting to ZooKeeper at \" + properties.get(ZK_CONNECT_STRING_PROPERTY) + root);\n+    return CuratorFrameworkFactory.builder()\n+      .connectString(properties.get(ZK_CONNECT_STRING_PROPERTY) + root)\n+      .retryPolicy(getRetryPolicy(properties.get(ZK_CONNECTION_RETRY_TIMEOUT_PROPERTY)))\n+      .connectionTimeoutMs(getIntProperty(properties, ZK_CONNECTION_TIMEOUT_PROPERTY, DEFAULT_CONNECTION_TIMEOUT))\n+      .sessionTimeoutMs(getIntProperty(properties, ZK_SESSION_TIMEOUT_PROPERTY, DEFAULT_SESSION_TIMEOUT))\n+      .build();\n+  }\n+\n+  /**\n+   * Get ACLs from a property (get the value then parse and transform it as ACL objects)\n+   */\n+  public static List<ACL> getAcls(Map<String, String> properties) {\n+    String aclStr = properties.get(ZK_ACLS_PROPERTY);\n+    if (StringUtils.isBlank(aclStr)) {\n+      return ZooDefs.Ids.OPEN_ACL_UNSAFE;\n+    }\n+\n+    List<ACL> acls = new ArrayList<>();\n+    List<String> aclStrList = Splitter.on(\",\").omitEmptyStrings().trimResults().splitToList(aclStr);\n+    for (String unparcedAcl : aclStrList) {\n+      String[] parts = unparcedAcl.split(\":\");\n+      if (parts.length == 3) {\n+        acls.add(new ACL(parsePermission(parts[2]), new Id(parts[0], parts[1])));\n+      }\n+    }\n+    return acls;\n+  }\n+\n+  private static int getIntProperty(Map<String, String> properties, String propertyKey, int defaultValue) {\n+    if (properties.get(propertyKey) == null)\n+      return defaultValue;\n+    return Integer.parseInt(properties.get(propertyKey));\n+  }\n+\n+  private static RetryPolicy getRetryPolicy(String zkConnectionRetryTimeoutValue) {\n+    if (zkConnectionRetryTimeoutValue == null)\n+      return new RetryForever(RETRY_INTERVAL_MS);\n+    int maxElapsedTimeMs = Integer.parseInt(zkConnectionRetryTimeoutValue);\n+    if (maxElapsedTimeMs == 0)\n+      return new RetryForever(RETRY_INTERVAL_MS);\n+    return new RetryUntilElapsed(maxElapsedTimeMs, RETRY_INTERVAL_MS);\n+  }\n+\n+  /**\n+   * Create listener for znode of log level filters - can be used for Log Feeder as it can be useful if it's monitoring the log level changes\n+   */\n+  public static TreeCacheListener createTreeCacheListener(String clusterName, Gson gson, LogLevelFilterMonitor logLevelFilterMonitor) {\n+    return new TreeCacheListener() {\n+      private final Set<TreeCacheEvent.Type> nodeEvents = ImmutableSet.of(TreeCacheEvent.Type.NODE_ADDED, TreeCacheEvent.Type.NODE_UPDATED, TreeCacheEvent.Type.NODE_REMOVED);\n+      public void childEvent(CuratorFramework client, TreeCacheEvent event) throws Exception {\n+        if (!nodeEvents.contains(event.getType())) {\n+          return;\n+        }\n+        String nodeName = ZKPaths.getNodeFromPath(event.getData().getPath());\n+        String nodeData = new String(event.getData().getData());\n+        TreeCacheEvent.Type eventType = event.getType();\n+\n+        String configPathStab = String.format(\"/%s/\", clusterName);","path":"ambari-logsearch/ambari-logsearch-config-zookeeper/src/main/java/org/apache/ambari/logsearch/config/zookeeper/LogSearchConfigZKHelper.java","position":180,"original_position":180,"commit_id":"0eea32edb37e1ab182eff9b781ff78bf9120865b","original_commit_id":"0eea32edb37e1ab182eff9b781ff78bf9120865b","user":{"login":"swagle","id":3011545,"node_id":"MDQ6VXNlcjMwMTE1NDU=","avatar_url":"https://avatars2.githubusercontent.com/u/3011545?v=4","gravatar_id":"","url":"https://api.github.com/users/swagle","html_url":"https://github.com/swagle","followers_url":"https://api.github.com/users/swagle/followers","following_url":"https://api.github.com/users/swagle/following{/other_user}","gists_url":"https://api.github.com/users/swagle/gists{/gist_id}","starred_url":"https://api.github.com/users/swagle/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/swagle/subscriptions","organizations_url":"https://api.github.com/users/swagle/orgs","repos_url":"https://api.github.com/users/swagle/repos","events_url":"https://api.github.com/users/swagle/events{/privacy}","received_events_url":"https://api.github.com/users/swagle/received_events","type":"User","site_admin":false},"body":"Minor nit: configPathStub","created_at":"2018-08-13T04:52:48Z","updated_at":"2018-08-13T04:52:48Z","html_url":"https://github.com/apache/ambari/pull/2040#discussion_r209491402","pull_request_url":"https://api.github.com/repos/apache/ambari/pulls/2040","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/apache/ambari/pulls/comments/209491402"},"html":{"href":"https://github.com/apache/ambari/pull/2040#discussion_r209491402"},"pull_request":{"href":"https://api.github.com/repos/apache/ambari/pulls/2040"}}},"pull_request":{"url":"https://api.github.com/repos/apache/ambari/pulls/2040","id":207766866,"node_id":"MDExOlB1bGxSZXF1ZXN0MjA3NzY2ODY2","html_url":"https://github.com/apache/ambari/pull/2040","diff_url":"https://github.com/apache/ambari/pull/2040.diff","patch_url":"https://github.com/apache/ambari/pull/2040.patch","issue_url":"https://api.github.com/repos/apache/ambari/issues/2040","number":2040,"state":"open","locked":false,"title":"AMBARI-24459. Log Search / Log Feeder - support to use ZK only for st…","user":{"login":"oleewere","id":1231814,"node_id":"MDQ6VXNlcjEyMzE4MTQ=","avatar_url":"https://avatars3.githubusercontent.com/u/1231814?v=4","gravatar_id":"","url":"https://api.github.com/users/oleewere","html_url":"https://github.com/oleewere","followers_url":"https://api.github.com/users/oleewere/followers","following_url":"https://api.github.com/users/oleewere/following{/other_user}","gists_url":"https://api.github.com/users/oleewere/gists{/gist_id}","starred_url":"https://api.github.com/users/oleewere/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/oleewere/subscriptions","organizations_url":"https://api.github.com/users/oleewere/orgs","repos_url":"https://api.github.com/users/oleewere/repos","events_url":"https://api.github.com/users/oleewere/events{/privacy}","received_events_url":"https://api.github.com/users/oleewere/received_events","type":"User","site_admin":false},"body":"…oring filters (without manage input configs)\r\n\r\n## What changes were proposed in this pull request?\r\nbe able to use zookeeper just only to store log level filters (and for example use local filesystem to store input configurations)\r\n\r\n- some common operations was moved to LogSearchConfigZKHelper\r\n- SolrLogLevelFilterConfigurer renamed to LogLevelFilterConfigurer in logsearch server code\r\n- it wont be the default use case for configuration api (but probably it should be later)\r\n\r\n## How was this patch tested?\r\nmanually with the new configs\r\n\r\nplease review @zeroflag @g-boros @swagle ","created_at":"2018-08-11T09:31:00Z","updated_at":"2018-08-13T04:52:48Z","closed_at":null,"merged_at":null,"merge_commit_sha":"982ac20c88d9f5a64f188449ba0bd13b726d63c6","assignee":{"login":"oleewere","id":1231814,"node_id":"MDQ6VXNlcjEyMzE4MTQ=","avatar_url":"https://avatars3.githubusercontent.com/u/1231814?v=4","gravatar_id":"","url":"https://api.github.com/users/oleewere","html_url":"https://github.com/oleewere","followers_url":"https://api.github.com/users/oleewere/followers","following_url":"https://api.github.com/users/oleewere/following{/other_user}","gists_url":"https://api.github.com/users/oleewere/gists{/gist_id}","starred_url":"https://api.github.com/users/oleewere/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/oleewere/subscriptions","organizations_url":"https://api.github.com/users/oleewere/orgs","repos_url":"https://api.github.com/users/oleewere/repos","events_url":"https://api.github.com/users/oleewere/events{/privacy}","received_events_url":"https://api.github.com/users/oleewere/received_events","type":"User","site_admin":false},"assignees":[{"login":"oleewere","id":1231814,"node_id":"MDQ6VXNlcjEyMzE4MTQ=","avatar_url":"https://avatars3.githubusercontent.com/u/1231814?v=4","gravatar_id":"","url":"https://api.github.com/users/oleewere","html_url":"https://github.com/oleewere","followers_url":"https://api.github.com/users/oleewere/followers","following_url":"https://api.github.com/users/oleewere/following{/other_user}","gists_url":"https://api.github.com/users/oleewere/gists{/gist_id}","starred_url":"https://api.github.com/users/oleewere/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/oleewere/subscriptions","organizations_url":"https://api.github.com/users/oleewere/orgs","repos_url":"https://api.github.com/users/oleewere/repos","events_url":"https://api.github.com/users/oleewere/events{/privacy}","received_events_url":"https://api.github.com/users/oleewere/received_events","type":"User","site_admin":false}],"requested_reviewers":[{"login":"zeroflag","id":641365,"node_id":"MDQ6VXNlcjY0MTM2NQ==","avatar_url":"https://avatars2.githubusercontent.com/u/641365?v=4","gravatar_id":"","url":"https://api.github.com/users/zeroflag","html_url":"https://github.com/zeroflag","followers_url":"https://api.github.com/users/zeroflag/followers","following_url":"https://api.github.com/users/zeroflag/following{/other_user}","gists_url":"https://api.github.com/users/zeroflag/gists{/gist_id}","starred_url":"https://api.github.com/users/zeroflag/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zeroflag/subscriptions","organizations_url":"https://api.github.com/users/zeroflag/orgs","repos_url":"https://api.github.com/users/zeroflag/repos","events_url":"https://api.github.com/users/zeroflag/events{/privacy}","received_events_url":"https://api.github.com/users/zeroflag/received_events","type":"User","site_admin":false}],"requested_teams":[],"labels":[{"id":799557193,"node_id":"MDU6TGFiZWw3OTk1NTcxOTM=","url":"https://api.github.com/repos/apache/ambari/labels/logsearch","name":"logsearch","color":"d7ffaf","default":false}],"milestone":null,"commits_url":"https://api.github.com/repos/apache/ambari/pulls/2040/commits","review_comments_url":"https://api.github.com/repos/apache/ambari/pulls/2040/comments","review_comment_url":"https://api.github.com/repos/apache/ambari/pulls/comments{/number}","comments_url":"https://api.github.com/repos/apache/ambari/issues/2040/comments","statuses_url":"https://api.github.com/repos/apache/ambari/statuses/0eea32edb37e1ab182eff9b781ff78bf9120865b","head":{"label":"oleewere:AMBARI-24459-trunk","ref":"AMBARI-24459-trunk","sha":"0eea32edb37e1ab182eff9b781ff78bf9120865b","user":{"login":"oleewere","id":1231814,"node_id":"MDQ6VXNlcjEyMzE4MTQ=","avatar_url":"https://avatars3.githubusercontent.com/u/1231814?v=4","gravatar_id":"","url":"https://api.github.com/users/oleewere","html_url":"https://github.com/oleewere","followers_url":"https://api.github.com/users/oleewere/followers","following_url":"https://api.github.com/users/oleewere/following{/other_user}","gists_url":"https://api.github.com/users/oleewere/gists{/gist_id}","starred_url":"https://api.github.com/users/oleewere/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/oleewere/subscriptions","organizations_url":"https://api.github.com/users/oleewere/orgs","repos_url":"https://api.github.com/users/oleewere/repos","events_url":"https://api.github.com/users/oleewere/events{/privacy}","received_events_url":"https://api.github.com/users/oleewere/received_events","type":"User","site_admin":false},"repo":{"id":41387030,"node_id":"MDEwOlJlcG9zaXRvcnk0MTM4NzAzMA==","name":"ambari","full_name":"oleewere/ambari","owner":{"login":"oleewere","id":1231814,"node_id":"MDQ6VXNlcjEyMzE4MTQ=","avatar_url":"https://avatars3.githubusercontent.com/u/1231814?v=4","gravatar_id":"","url":"https://api.github.com/users/oleewere","html_url":"https://github.com/oleewere","followers_url":"https://api.github.com/users/oleewere/followers","following_url":"https://api.github.com/users/oleewere/following{/other_user}","gists_url":"https://api.github.com/users/oleewere/gists{/gist_id}","starred_url":"https://api.github.com/users/oleewere/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/oleewere/subscriptions","organizations_url":"https://api.github.com/users/oleewere/orgs","repos_url":"https://api.github.com/users/oleewere/repos","events_url":"https://api.github.com/users/oleewere/events{/privacy}","received_events_url":"https://api.github.com/users/oleewere/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/oleewere/ambari","description":"Mirror of Apache Ambari","fork":true,"url":"https://api.github.com/repos/oleewere/ambari","forks_url":"https://api.github.com/repos/oleewere/ambari/forks","keys_url":"https://api.github.com/repos/oleewere/ambari/keys{/key_id}","collaborators_url":"https://api.github.com/repos/oleewere/ambari/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/oleewere/ambari/teams","hooks_url":"https://api.github.com/repos/oleewere/ambari/hooks","issue_events_url":"https://api.github.com/repos/oleewere/ambari/issues/events{/number}","events_url":"https://api.github.com/repos/oleewere/ambari/events","assignees_url":"https://api.github.com/repos/oleewere/ambari/assignees{/user}","branches_url":"https://api.github.com/repos/oleewere/ambari/branches{/branch}","tags_url":"https://api.github.com/repos/oleewere/ambari/tags","blobs_url":"https://api.github.com/repos/oleewere/ambari/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/oleewere/ambari/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/oleewere/ambari/git/refs{/sha}","trees_url":"https://api.github.com/repos/oleewere/ambari/git/trees{/sha}","statuses_url":"https://api.github.com/repos/oleewere/ambari/statuses/{sha}","languages_url":"https://api.github.com/repos/oleewere/ambari/languages","stargazers_url":"https://api.github.com/repos/oleewere/ambari/stargazers","contributors_url":"https://api.github.com/repos/oleewere/ambari/contributors","subscribers_url":"https://api.github.com/repos/oleewere/ambari/subscribers","subscription_url":"https://api.github.com/repos/oleewere/ambari/subscription","commits_url":"https://api.github.com/repos/oleewere/ambari/commits{/sha}","git_commits_url":"https://api.github.com/repos/oleewere/ambari/git/commits{/sha}","comments_url":"https://api.github.com/repos/oleewere/ambari/comments{/number}","issue_comment_url":"https://api.github.com/repos/oleewere/ambari/issues/comments{/number}","contents_url":"https://api.github.com/repos/oleewere/ambari/contents/{+path}","compare_url":"https://api.github.com/repos/oleewere/ambari/compare/{base}...{head}","merges_url":"https://api.github.com/repos/oleewere/ambari/merges","archive_url":"https://api.github.com/repos/oleewere/ambari/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/oleewere/ambari/downloads","issues_url":"https://api.github.com/repos/oleewere/ambari/issues{/number}","pulls_url":"https://api.github.com/repos/oleewere/ambari/pulls{/number}","milestones_url":"https://api.github.com/repos/oleewere/ambari/milestones{/number}","notifications_url":"https://api.github.com/repos/oleewere/ambari/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/oleewere/ambari/labels{/name}","releases_url":"https://api.github.com/repos/oleewere/ambari/releases{/id}","deployments_url":"https://api.github.com/repos/oleewere/ambari/deployments","created_at":"2015-08-25T20:45:42Z","updated_at":"2018-06-22T11:09:23Z","pushed_at":"2018-08-11T09:38:47Z","git_url":"git://github.com/oleewere/ambari.git","ssh_url":"git@github.com:oleewere/ambari.git","clone_url":"https://github.com/oleewere/ambari.git","svn_url":"https://github.com/oleewere/ambari","homepage":null,"size":313297,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":0,"open_issues":0,"watchers":0,"default_branch":"trunk"}},"base":{"label":"apache:trunk","ref":"trunk","sha":"c37b7ff02798e49fad2eba51d51450b9da704193","user":{"login":"apache","id":47359,"node_id":"MDEyOk9yZ2FuaXphdGlvbjQ3MzU5","avatar_url":"https://avatars0.githubusercontent.com/u/47359?v=4","gravatar_id":"","url":"https://api.github.com/users/apache","html_url":"https://github.com/apache","followers_url":"https://api.github.com/users/apache/followers","following_url":"https://api.github.com/users/apache/following{/other_user}","gists_url":"https://api.github.com/users/apache/gists{/gist_id}","starred_url":"https://api.github.com/users/apache/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apache/subscriptions","organizations_url":"https://api.github.com/users/apache/orgs","repos_url":"https://api.github.com/users/apache/repos","events_url":"https://api.github.com/users/apache/events{/privacy}","received_events_url":"https://api.github.com/users/apache/received_events","type":"Organization","site_admin":false},"repo":{"id":2442457,"node_id":"MDEwOlJlcG9zaXRvcnkyNDQyNDU3","name":"ambari","full_name":"apache/ambari","owner":{"login":"apache","id":47359,"node_id":"MDEyOk9yZ2FuaXphdGlvbjQ3MzU5","avatar_url":"https://avatars0.githubusercontent.com/u/47359?v=4","gravatar_id":"","url":"https://api.github.com/users/apache","html_url":"https://github.com/apache","followers_url":"https://api.github.com/users/apache/followers","following_url":"https://api.github.com/users/apache/following{/other_user}","gists_url":"https://api.github.com/users/apache/gists{/gist_id}","starred_url":"https://api.github.com/users/apache/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apache/subscriptions","organizations_url":"https://api.github.com/users/apache/orgs","repos_url":"https://api.github.com/users/apache/repos","events_url":"https://api.github.com/users/apache/events{/privacy}","received_events_url":"https://api.github.com/users/apache/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/apache/ambari","description":"Mirror of Apache Ambari","fork":false,"url":"https://api.github.com/repos/apache/ambari","forks_url":"https://api.github.com/repos/apache/ambari/forks","keys_url":"https://api.github.com/repos/apache/ambari/keys{/key_id}","collaborators_url":"https://api.github.com/repos/apache/ambari/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/apache/ambari/teams","hooks_url":"https://api.github.com/repos/apache/ambari/hooks","issue_events_url":"https://api.github.com/repos/apache/ambari/issues/events{/number}","events_url":"https://api.github.com/repos/apache/ambari/events","assignees_url":"https://api.github.com/repos/apache/ambari/assignees{/user}","branches_url":"https://api.github.com/repos/apache/ambari/branches{/branch}","tags_url":"https://api.github.com/repos/apache/ambari/tags","blobs_url":"https://api.github.com/repos/apache/ambari/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/apache/ambari/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/apache/ambari/git/refs{/sha}","trees_url":"https://api.github.com/repos/apache/ambari/git/trees{/sha}","statuses_url":"https://api.github.com/repos/apache/ambari/statuses/{sha}","languages_url":"https://api.github.com/repos/apache/ambari/languages","stargazers_url":"https://api.github.com/repos/apache/ambari/stargazers","contributors_url":"https://api.github.com/repos/apache/ambari/contributors","subscribers_url":"https://api.github.com/repos/apache/ambari/subscribers","subscription_url":"https://api.github.com/repos/apache/ambari/subscription","commits_url":"https://api.github.com/repos/apache/ambari/commits{/sha}","git_commits_url":"https://api.github.com/repos/apache/ambari/git/commits{/sha}","comments_url":"https://api.github.com/repos/apache/ambari/comments{/number}","issue_comment_url":"https://api.github.com/repos/apache/ambari/issues/comments{/number}","contents_url":"https://api.github.com/repos/apache/ambari/contents/{+path}","compare_url":"https://api.github.com/repos/apache/ambari/compare/{base}...{head}","merges_url":"https://api.github.com/repos/apache/ambari/merges","archive_url":"https://api.github.com/repos/apache/ambari/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/apache/ambari/downloads","issues_url":"https://api.github.com/repos/apache/ambari/issues{/number}","pulls_url":"https://api.github.com/repos/apache/ambari/pulls{/number}","milestones_url":"https://api.github.com/repos/apache/ambari/milestones{/number}","notifications_url":"https://api.github.com/repos/apache/ambari/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/apache/ambari/labels{/name}","releases_url":"https://api.github.com/repos/apache/ambari/releases{/id}","deployments_url":"https://api.github.com/repos/apache/ambari/deployments","created_at":"2011-09-23T07:00:08Z","updated_at":"2018-08-11T22:25:55Z","pushed_at":"2018-08-12T22:45:41Z","git_url":"git://github.com/apache/ambari.git","ssh_url":"git@github.com:apache/ambari.git","clone_url":"https://github.com/apache/ambari.git","svn_url":"https://github.com/apache/ambari","homepage":null,"size":332297,"stargazers_count":899,"watchers_count":899,"language":"Java","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":914,"mirror_url":null,"archived":false,"open_issues_count":65,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":914,"open_issues":65,"watchers":899,"default_branch":"trunk"}},"_links":{"self":{"href":"https://api.github.com/repos/apache/ambari/pulls/2040"},"html":{"href":"https://github.com/apache/ambari/pull/2040"},"issue":{"href":"https://api.github.com/repos/apache/ambari/issues/2040"},"comments":{"href":"https://api.github.com/repos/apache/ambari/issues/2040/comments"},"review_comments":{"href":"https://api.github.com/repos/apache/ambari/pulls/2040/comments"},"review_comment":{"href":"https://api.github.com/repos/apache/ambari/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/apache/ambari/pulls/2040/commits"},"statuses":{"href":"https://api.github.com/repos/apache/ambari/statuses/0eea32edb37e1ab182eff9b781ff78bf9120865b"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"swagle"}}