{"action":"created","comment":{"url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/pulls/comments/46474644","id":46474644,"diff_hunk":"@@ -0,0 +1,351 @@\n+/*\n+ * Copyright 2014-2015 the original author or authors.\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+ * See the License for the specific language governing permissions and\n+ * limitations under the License.\n+ */\n+\n+package org.springframework.cloud.cluster.etcd.leader;\n+\n+import java.io.IOException;\n+import java.util.concurrent.Callable;\n+import java.util.concurrent.ExecutorService;\n+import java.util.concurrent.Executors;\n+import java.util.concurrent.Future;\n+import java.util.concurrent.ThreadFactory;\n+import java.util.concurrent.TimeUnit;\n+import java.util.concurrent.TimeoutException;\n+\n+import org.slf4j.LoggerFactory;\n+import org.springframework.beans.factory.DisposableBean;\n+import org.springframework.beans.factory.InitializingBean;\n+import org.springframework.cloud.cluster.leader.Candidate;\n+import org.springframework.cloud.cluster.leader.Context;\n+import org.springframework.cloud.cluster.leader.event.LeaderEventPublisher;\n+import org.springframework.context.Lifecycle;\n+\n+import mousio.etcd4j.EtcdClient;\n+import mousio.etcd4j.responses.EtcdException;\n+\n+/**\n+ * Bootstrap leadership {@link org.springframework.cloud.cluster.leader.Candidate candidates}\n+ * with etcd. Upon construction, {@link #start} must be invoked to\n+ * register the candidate for leadership election.\n+ *\n+ * @author Venil Noronha\n+ */\n+public class LeaderInitiator implements Lifecycle, InitializingBean, DisposableBean {\n+\n+\tprivate final static int TTL = 10;\n+\tprivate final static int HEART_BEAT_SLEEP = TTL / 2;\n+\tprivate final static String DEFAULT_NAMESPACE = \"spring-cloud\";\n+\t\n+\t/**\n+\t * {@link EtcdClient} instance.\n+\t */\n+\tprivate final EtcdClient client;\n+\n+\t/**\n+\t * Candidate for leader election.\n+\t */\n+\tprivate final Candidate candidate;\n+\n+\t/**\n+\t * Executor service for running leadership daemon.\n+\t */\n+\tprivate final ExecutorService leaderExecutorService = Executors.newSingleThreadExecutor(new ThreadFactory() {\n+\t\t@Override\n+\t\tpublic Thread newThread(Runnable r) {\n+\t\t\tThread thread = new Thread(r, \"Etcd-Leadership\");\n+\t\t\tthread.setDaemon(true);\n+\t\t\treturn thread;\n+\t\t}\n+\t});\n+\t\n+\t/**\n+\t * Executor service for running leadership worker daemon.\n+\t */\n+\tprivate final ExecutorService workerExecutorService = Executors.newSingleThreadExecutor(new ThreadFactory() {\n+\t\t@Override\n+\t\tpublic Thread newThread(Runnable r) {\n+\t\t\tThread thread = new Thread(r, \"Etcd-Leadership-Worker\");\n+\t\t\tthread.setDaemon(true);\n+\t\t\treturn thread;\n+\t\t}\n+\t});\n+\n+\t/**\n+\t * Flag that indicates whether the current candidate is\n+\t * the leader.\n+\t */\n+\tprivate volatile boolean isLeader = false;\n+\t\n+\t/**\n+\t * Future returned by submitting a {@link Initiator} to {@link #leaderExecutorService}.\n+\t * This is used to cancel leadership.\n+\t */\n+\tprivate volatile Future<Void> initiatorFuture;\n+\t\n+\t/**\n+\t * Future returned by submitting a {@link Worker} to {@link #workerExecutorService}.\n+\t * This is used to notify leadership revocation.\n+\t */\n+\tprivate volatile Future<Void> workerFuture;\n+\n+\t/**\n+\t * Flag that indicates whether the leadership election for\n+\t * this {@link #candidate} is running.\n+\t */\n+\tprivate volatile boolean running;\n+\n+\t/**\n+\t * Leader event publisher if set.\n+\t */\n+\tprivate LeaderEventPublisher leaderEventPublisher;\n+\t\n+\t/**\n+\t * The {@link EtcdContext} instance.\n+\t */\n+\tprivate final EtcdContext context;\n+\n+\t/**\n+\t * The base etcd path where candidate id is to be stored.\n+\t */\n+\tprivate final String baseEtcdPath;\n+\t\n+\t/**\n+\t * Construct a {@link LeaderInitiator}.\n+\t *\n+\t * @param client     {@link EtcdClient} instance\n+\t * @param candidate  leadership election candidate\n+\t * @param namespace\t Etcd namespace\n+\t */\n+\tpublic LeaderInitiator(EtcdClient client, Candidate candidate, String namespace) {\n+\t\tthis.client = client;\n+\t\tthis.candidate = candidate;\n+\t\tthis.context = new EtcdContext();\n+\t\tthis.baseEtcdPath = (namespace == null ? DEFAULT_NAMESPACE : namespace) + \"/\" + candidate.getRole();\n+\t}\n+\n+\t/**\n+\t * Start the registration of the {@link #candidate} for leader election.\n+\t */\n+\t@Override\n+\tpublic synchronized void start() {\n+\t\tif (!running) {\n+\t\t\trunning = true;\n+\t\t\tinitiatorFuture = leaderExecutorService.submit(new Initiator());\n+\t\t}\n+\t}\n+\n+\t/**\n+\t * Stop the registration of the {@link #candidate} for leader election.\n+\t * If the candidate is currently leader, its leadership will be revoked.\n+\t */\n+\t@Override\n+\tpublic synchronized void stop() {\n+\t\tif (running) {\n+\t\t\trunning = false;\n+\t\t\tinitiatorFuture.cancel(true);\n+\t\t}\n+\t}\n+\n+\t/**\n+\t * @return true if leadership election for this {@link #candidate} is running\n+\t */\n+\t@Override\n+\tpublic boolean isRunning() {\n+\t\treturn running;\n+\t}\n+\n+\t@Override\n+\tpublic void afterPropertiesSet() throws Exception {\n+\t\tstart();\n+\t}\n+\n+\t@Override\n+\tpublic void destroy() throws Exception {\n+\t\tstop();\n+\t\tworkerExecutorService.shutdown();\n+\t\tleaderExecutorService.shutdown();\n+\t\tworkerExecutorService.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);\n+\t\tleaderExecutorService.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);\n+\t}\n+\t\n+\t/**\n+\t * Sets the {@link LeaderEventPublisher}.\n+\t * \n+\t * @param leaderEventPublisher the event publisher\n+\t */\n+\tpublic void setLeaderEventPublisher(LeaderEventPublisher leaderEventPublisher) {\n+\t\tthis.leaderEventPublisher = leaderEventPublisher;\n+\t}\n+\n+\t/**\n+\t * Notifies that the candidate has acquired leadership.\n+\t */\n+\tprivate void notifyGranted() {\n+\t\tisLeader = true;\n+\t\tif (leaderEventPublisher != null) {\n+\t\t\tleaderEventPublisher.publishOnGranted(LeaderInitiator.this, context);\n+\t\t}\n+\t\tworkerFuture = workerExecutorService.submit(new Worker());\n+\t}\n+\t\n+\t/**\n+\t * Notifies that the candidate's leadership was revoked.\n+\t */\n+\tprivate void notifyRevoked() {\n+\t\tisLeader = false;\n+\t\tif (leaderEventPublisher != null) {\n+\t\t\tleaderEventPublisher.publishOnRevoked(LeaderInitiator.this, context);\n+\t\t}\n+\t\tworkerFuture.cancel(true);\n+\t}\n+\n+\t/**\n+\t * Tries to delete the candidate's entry from etcd.\n+\t */\n+\tprivate void tryDeleteCandidateEntry() {\n+\t\ttry {\n+\t\t\tclient.delete(baseEtcdPath).prevValue(candidate.getId()).send().get();\n+\t\t}\n+\t\tcatch (EtcdException e) {\n+\t\t\tLoggerFactory.getLogger(getClass()).warn(\"Exception occurred while trying to delete candidate key from etcd\", e); \n+\t\t}\n+\t\tcatch (IOException | TimeoutException e) {\n+\t\t\tLoggerFactory.getLogger(getClass()).warn(\"Exception occurred while trying to access etcd\", e);\n+\t\t}\n+\t}\n+\n+\t/**\n+\t * Callable that invokes {@link Candidate#onGranted(Context)}\n+\t * when the candidate is granted leadership.\n+\t */\n+\tclass Worker implements Callable<Void> {\n+\n+\t\t@Override\n+\t\tpublic Void call() {\n+\t\t\ttry {\n+\t\t\t\tcandidate.onGranted(context);\n+\t\t\t\tThread.sleep(Long.MAX_VALUE);\n+\t\t\t}\n+\t\t\tcatch (InterruptedException e) {\n+\t\t\t\t// If the candidate's leadership was revoked\n+\t\t\t}\n+\t\t\tfinally {\n+\t\t\t\tcandidate.onRevoked(context);","path":"spring-cloud-cluster-etcd/src/main/java/org/springframework/cloud/cluster/etcd/leader/LeaderInitiator.java","position":263,"original_position":246,"commit_id":"1fbca474df3bb63e912563dc5c7bca0453744d9c","original_commit_id":"b62e00d4b92040ea7b8bb5bd961a2797115b2c12","user":{"login":"venilnoronha","id":1722758,"avatar_url":"https://avatars.githubusercontent.com/u/1722758?v=3","gravatar_id":"","url":"https://api.github.com/users/venilnoronha","html_url":"https://github.com/venilnoronha","followers_url":"https://api.github.com/users/venilnoronha/followers","following_url":"https://api.github.com/users/venilnoronha/following{/other_user}","gists_url":"https://api.github.com/users/venilnoronha/gists{/gist_id}","starred_url":"https://api.github.com/users/venilnoronha/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/venilnoronha/subscriptions","organizations_url":"https://api.github.com/users/venilnoronha/orgs","repos_url":"https://api.github.com/users/venilnoronha/repos","events_url":"https://api.github.com/users/venilnoronha/events{/privacy}","received_events_url":"https://api.github.com/users/venilnoronha/received_events","type":"User","site_admin":false},"body":"I've fixed this issue with commit 05aca24b037d89f31921e0c4c4e6f9c193a8f442. I've added a test for it too.","created_at":"2015-12-02T21:02:06Z","updated_at":"2015-12-02T21:02:06Z","html_url":"https://github.com/spring-cloud/spring-cloud-cluster/pull/20#discussion_r46474644","pull_request_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/pulls/20","_links":{"self":{"href":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/pulls/comments/46474644"},"html":{"href":"https://github.com/spring-cloud/spring-cloud-cluster/pull/20#discussion_r46474644"},"pull_request":{"href":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/pulls/20"}}},"pull_request":{"url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/pulls/20","id":51137136,"html_url":"https://github.com/spring-cloud/spring-cloud-cluster/pull/20","diff_url":"https://github.com/spring-cloud/spring-cloud-cluster/pull/20.diff","patch_url":"https://github.com/spring-cloud/spring-cloud-cluster/pull/20.patch","issue_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/issues/20","number":20,"state":"open","locked":false,"title":"Initial etcd leader-election implementation.","user":{"login":"venilnoronha","id":1722758,"avatar_url":"https://avatars.githubusercontent.com/u/1722758?v=3","gravatar_id":"","url":"https://api.github.com/users/venilnoronha","html_url":"https://github.com/venilnoronha","followers_url":"https://api.github.com/users/venilnoronha/followers","following_url":"https://api.github.com/users/venilnoronha/following{/other_user}","gists_url":"https://api.github.com/users/venilnoronha/gists{/gist_id}","starred_url":"https://api.github.com/users/venilnoronha/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/venilnoronha/subscriptions","organizations_url":"https://api.github.com/users/venilnoronha/orgs","repos_url":"https://api.github.com/users/venilnoronha/repos","events_url":"https://api.github.com/users/venilnoronha/events{/privacy}","received_events_url":"https://api.github.com/users/venilnoronha/received_events","type":"User","site_admin":false},"body":"Hi,\r\n\r\nI've created a etcd implementation for spring-cloud-cluster leader-election along with autoconfiguration. I've also updated the tests and the leaderelection doc. Please pull.","created_at":"2015-11-18T20:26:06Z","updated_at":"2015-12-02T21:02:06Z","closed_at":null,"merged_at":null,"merge_commit_sha":"e6dae2537fd1dfbf1b8b5aa547651dcede35ba24","assignee":{"login":"pperalta","id":394956,"avatar_url":"https://avatars.githubusercontent.com/u/394956?v=3","gravatar_id":"","url":"https://api.github.com/users/pperalta","html_url":"https://github.com/pperalta","followers_url":"https://api.github.com/users/pperalta/followers","following_url":"https://api.github.com/users/pperalta/following{/other_user}","gists_url":"https://api.github.com/users/pperalta/gists{/gist_id}","starred_url":"https://api.github.com/users/pperalta/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pperalta/subscriptions","organizations_url":"https://api.github.com/users/pperalta/orgs","repos_url":"https://api.github.com/users/pperalta/repos","events_url":"https://api.github.com/users/pperalta/events{/privacy}","received_events_url":"https://api.github.com/users/pperalta/received_events","type":"User","site_admin":false},"milestone":null,"commits_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/pulls/20/commits","review_comments_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/pulls/20/comments","review_comment_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/pulls/comments{/number}","comments_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/issues/20/comments","statuses_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/statuses/1fbca474df3bb63e912563dc5c7bca0453744d9c","head":{"label":"venilnoronha:etcd","ref":"etcd","sha":"1fbca474df3bb63e912563dc5c7bca0453744d9c","user":{"login":"venilnoronha","id":1722758,"avatar_url":"https://avatars.githubusercontent.com/u/1722758?v=3","gravatar_id":"","url":"https://api.github.com/users/venilnoronha","html_url":"https://github.com/venilnoronha","followers_url":"https://api.github.com/users/venilnoronha/followers","following_url":"https://api.github.com/users/venilnoronha/following{/other_user}","gists_url":"https://api.github.com/users/venilnoronha/gists{/gist_id}","starred_url":"https://api.github.com/users/venilnoronha/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/venilnoronha/subscriptions","organizations_url":"https://api.github.com/users/venilnoronha/orgs","repos_url":"https://api.github.com/users/venilnoronha/repos","events_url":"https://api.github.com/users/venilnoronha/events{/privacy}","received_events_url":"https://api.github.com/users/venilnoronha/received_events","type":"User","site_admin":false},"repo":{"id":46432631,"name":"spring-cloud-cluster","full_name":"venilnoronha/spring-cloud-cluster","owner":{"login":"venilnoronha","id":1722758,"avatar_url":"https://avatars.githubusercontent.com/u/1722758?v=3","gravatar_id":"","url":"https://api.github.com/users/venilnoronha","html_url":"https://github.com/venilnoronha","followers_url":"https://api.github.com/users/venilnoronha/followers","following_url":"https://api.github.com/users/venilnoronha/following{/other_user}","gists_url":"https://api.github.com/users/venilnoronha/gists{/gist_id}","starred_url":"https://api.github.com/users/venilnoronha/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/venilnoronha/subscriptions","organizations_url":"https://api.github.com/users/venilnoronha/orgs","repos_url":"https://api.github.com/users/venilnoronha/repos","events_url":"https://api.github.com/users/venilnoronha/events{/privacy}","received_events_url":"https://api.github.com/users/venilnoronha/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/venilnoronha/spring-cloud-cluster","description":"Integration with Zookeeper and Spring Cloud: clustering concerns, like leadership election and consistent key value store","fork":true,"url":"https://api.github.com/repos/venilnoronha/spring-cloud-cluster","forks_url":"https://api.github.com/repos/venilnoronha/spring-cloud-cluster/forks","keys_url":"https://api.github.com/repos/venilnoronha/spring-cloud-cluster/keys{/key_id}","collaborators_url":"https://api.github.com/repos/venilnoronha/spring-cloud-cluster/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/venilnoronha/spring-cloud-cluster/teams","hooks_url":"https://api.github.com/repos/venilnoronha/spring-cloud-cluster/hooks","issue_events_url":"https://api.github.com/repos/venilnoronha/spring-cloud-cluster/issues/events{/number}","events_url":"https://api.github.com/repos/venilnoronha/spring-cloud-cluster/events","assignees_url":"https://api.github.com/repos/venilnoronha/spring-cloud-cluster/assignees{/user}","branches_url":"https://api.github.com/repos/venilnoronha/spring-cloud-cluster/branches{/branch}","tags_url":"https://api.github.com/repos/venilnoronha/spring-cloud-cluster/tags","blobs_url":"https://api.github.com/repos/venilnoronha/spring-cloud-cluster/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/venilnoronha/spring-cloud-cluster/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/venilnoronha/spring-cloud-cluster/git/refs{/sha}","trees_url":"https://api.github.com/repos/venilnoronha/spring-cloud-cluster/git/trees{/sha}","statuses_url":"https://api.github.com/repos/venilnoronha/spring-cloud-cluster/statuses/{sha}","languages_url":"https://api.github.com/repos/venilnoronha/spring-cloud-cluster/languages","stargazers_url":"https://api.github.com/repos/venilnoronha/spring-cloud-cluster/stargazers","contributors_url":"https://api.github.com/repos/venilnoronha/spring-cloud-cluster/contributors","subscribers_url":"https://api.github.com/repos/venilnoronha/spring-cloud-cluster/subscribers","subscription_url":"https://api.github.com/repos/venilnoronha/spring-cloud-cluster/subscription","commits_url":"https://api.github.com/repos/venilnoronha/spring-cloud-cluster/commits{/sha}","git_commits_url":"https://api.github.com/repos/venilnoronha/spring-cloud-cluster/git/commits{/sha}","comments_url":"https://api.github.com/repos/venilnoronha/spring-cloud-cluster/comments{/number}","issue_comment_url":"https://api.github.com/repos/venilnoronha/spring-cloud-cluster/issues/comments{/number}","contents_url":"https://api.github.com/repos/venilnoronha/spring-cloud-cluster/contents/{+path}","compare_url":"https://api.github.com/repos/venilnoronha/spring-cloud-cluster/compare/{base}...{head}","merges_url":"https://api.github.com/repos/venilnoronha/spring-cloud-cluster/merges","archive_url":"https://api.github.com/repos/venilnoronha/spring-cloud-cluster/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/venilnoronha/spring-cloud-cluster/downloads","issues_url":"https://api.github.com/repos/venilnoronha/spring-cloud-cluster/issues{/number}","pulls_url":"https://api.github.com/repos/venilnoronha/spring-cloud-cluster/pulls{/number}","milestones_url":"https://api.github.com/repos/venilnoronha/spring-cloud-cluster/milestones{/number}","notifications_url":"https://api.github.com/repos/venilnoronha/spring-cloud-cluster/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/venilnoronha/spring-cloud-cluster/labels{/name}","releases_url":"https://api.github.com/repos/venilnoronha/spring-cloud-cluster/releases{/id}","created_at":"2015-11-18T16:42:52Z","updated_at":"2015-11-18T16:42:53Z","pushed_at":"2015-12-02T21:00:09Z","git_url":"git://github.com/venilnoronha/spring-cloud-cluster.git","ssh_url":"git@github.com:venilnoronha/spring-cloud-cluster.git","clone_url":"https://github.com/venilnoronha/spring-cloud-cluster.git","svn_url":"https://github.com/venilnoronha/spring-cloud-cluster","homepage":null,"size":221,"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":"spring-cloud:master","ref":"master","sha":"9499db27bd33ed8a626eaf068bf66b264735931c","user":{"login":"spring-cloud","id":7815877,"avatar_url":"https://avatars.githubusercontent.com/u/7815877?v=3","gravatar_id":"","url":"https://api.github.com/users/spring-cloud","html_url":"https://github.com/spring-cloud","followers_url":"https://api.github.com/users/spring-cloud/followers","following_url":"https://api.github.com/users/spring-cloud/following{/other_user}","gists_url":"https://api.github.com/users/spring-cloud/gists{/gist_id}","starred_url":"https://api.github.com/users/spring-cloud/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/spring-cloud/subscriptions","organizations_url":"https://api.github.com/users/spring-cloud/orgs","repos_url":"https://api.github.com/users/spring-cloud/repos","events_url":"https://api.github.com/users/spring-cloud/events{/privacy}","received_events_url":"https://api.github.com/users/spring-cloud/received_events","type":"Organization","site_admin":false},"repo":{"id":24367501,"name":"spring-cloud-cluster","full_name":"spring-cloud/spring-cloud-cluster","owner":{"login":"spring-cloud","id":7815877,"avatar_url":"https://avatars.githubusercontent.com/u/7815877?v=3","gravatar_id":"","url":"https://api.github.com/users/spring-cloud","html_url":"https://github.com/spring-cloud","followers_url":"https://api.github.com/users/spring-cloud/followers","following_url":"https://api.github.com/users/spring-cloud/following{/other_user}","gists_url":"https://api.github.com/users/spring-cloud/gists{/gist_id}","starred_url":"https://api.github.com/users/spring-cloud/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/spring-cloud/subscriptions","organizations_url":"https://api.github.com/users/spring-cloud/orgs","repos_url":"https://api.github.com/users/spring-cloud/repos","events_url":"https://api.github.com/users/spring-cloud/events{/privacy}","received_events_url":"https://api.github.com/users/spring-cloud/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/spring-cloud/spring-cloud-cluster","description":"Integration with Zookeeper and Spring Cloud: clustering concerns, like leadership election and consistent key value store","fork":false,"url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster","forks_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/forks","keys_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/keys{/key_id}","collaborators_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/teams","hooks_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/hooks","issue_events_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/issues/events{/number}","events_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/events","assignees_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/assignees{/user}","branches_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/branches{/branch}","tags_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/tags","blobs_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/git/refs{/sha}","trees_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/git/trees{/sha}","statuses_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/statuses/{sha}","languages_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/languages","stargazers_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/stargazers","contributors_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/contributors","subscribers_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/subscribers","subscription_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/subscription","commits_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/commits{/sha}","git_commits_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/git/commits{/sha}","comments_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/comments{/number}","issue_comment_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/issues/comments{/number}","contents_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/contents/{+path}","compare_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/compare/{base}...{head}","merges_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/merges","archive_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/downloads","issues_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/issues{/number}","pulls_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/pulls{/number}","milestones_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/milestones{/number}","notifications_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/labels{/name}","releases_url":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/releases{/id}","created_at":"2014-09-23T10:49:34Z","updated_at":"2015-11-18T20:27:07Z","pushed_at":"2015-12-02T21:00:10Z","git_url":"git://github.com/spring-cloud/spring-cloud-cluster.git","ssh_url":"git@github.com:spring-cloud/spring-cloud-cluster.git","clone_url":"https://github.com/spring-cloud/spring-cloud-cluster.git","svn_url":"https://github.com/spring-cloud/spring-cloud-cluster","homepage":null,"size":607,"stargazers_count":28,"watchers_count":28,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":19,"mirror_url":null,"open_issues_count":11,"forks":19,"open_issues":11,"watchers":28,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/pulls/20"},"html":{"href":"https://github.com/spring-cloud/spring-cloud-cluster/pull/20"},"issue":{"href":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/issues/20"},"comments":{"href":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/issues/20/comments"},"review_comments":{"href":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/pulls/20/comments"},"review_comment":{"href":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/pulls/20/commits"},"statuses":{"href":"https://api.github.com/repos/spring-cloud/spring-cloud-cluster/statuses/1fbca474df3bb63e912563dc5c7bca0453744d9c"}}}}