{"action":"created","comment":{"url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/pulls/comments/336317114","pull_request_review_id":303637565,"id":336317114,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDMzNjMxNzExNA==","diff_hunk":"@@ -145,109 +215,174 @@ func (r *roleService) getRoleToken(ctx context.Context, domain, role, proxyForPr\n \treturn tok, nil\n }\n \n-// handleExpiredHook is a handler function for gache expired hook\n-func (r *roleService) handleExpiredHook(fctx context.Context, key string) {\n-\tdomain, role := decode(key)\n-\tr.updateRoleToken(fctx, domain, role, \"\", r.expiry, r.expiry)\n-}\n+// refreshRoleTokenCache returns the error channel when it is updated.\n+func (r *roleService) RefreshRoleTokenCache(ctx context.Context) <-chan error {\n+\tglg.Info(\"refreshRoleTokenCache started\")\n \n-// updateRoleToken returns RoleToken struct or error.\n-// This function ask athenz to generate role token and return, or return any error when generating the role token.\n-func (r *roleService) updateRoleToken(ctx context.Context, domain, role, proxyForPrincipal string, minExpiry, maxExpiry time.Duration) (*RoleToken, error) {\n+\techan := make(chan error)\n+\tgo func() {\n+\t\tdefer close(echan)\n \n-\ttok, err, _ := r.group.Do(encode(domain, role), func() (interface{}, error) {\n-\t\t// get the role token\n-\t\ttok, err := r.token()\n-\t\tif err != nil {\n-\t\t\treturn nil, err\n-\t\t}\n+\t\tr.domainRoleCache.Foreach(ctx, func(key string, val interface{}, exp int64) bool {\n+\t\t\tdomain, role, principal := decode(key)\n+\t\t\tfor err := range r.updateRoleTokenWithRetry(ctx, domain, role, principal, r.expiry, r.expiry) {\n+\t\t\t\techan <- err\n+\t\t\t}\n+\t\t\treturn true\n+\t\t})\n+\t}()\n \n-\t\t// concat URL string and url parameters\n-\t\tu := getRoleTokenAthenzURL(r.athenzURL, domain, role, minExpiry, maxExpiry, proxyForPrincipal)\n+\treturn echan\n+}\n \n-\t\treq, err := http.NewRequest(http.MethodGet, u, nil)\n-\t\tif err != nil {\n-\t\t\treturn nil, err\n-\t\t}\n+// handleExpiredHook is a handler function for gache expired hook\n+func (r *roleService) handleExpiredHook(ctx context.Context, key string) {\n+\tglg.Debugf(\"handleExpiredHook(), key: %s\", key)\n+\tdomain, role, principal := decode(key)\n+\tglg.Debugf(\"decoded: %s, %s, %s\", domain, role, principal)\n+\t_, err := r.updateRoleToken(ctx, domain, role, principal, r.expiry, r.expiry)\n+\tglg.Errorf(\"err: %v\", err)\n+}\n \n-\t\treq.Header.Set(r.athenzPrincipleHeader, tok)\n+func (r *roleService) updateRoleTokenWithRetry(ctx context.Context, domain, role, proxyForPrincipal string, minExpiry, maxExpiry time.Duration) <-chan error {\n+\tglg.Debugf(\"updateRoleTokenWithRetry started, domain: %s, role: %s, proxyForPrincipal: %s, minExpiry: %s, maxExpiry: %s\", domain, role, proxyForPrincipal, minExpiry, maxExpiry)\n \n-\t\t// send http request\n-\t\tres, err := r.httpClient.Do(req.WithContext(ctx))\n+\techan := make(chan error, r.errRetryMaxCount)\n+\tgo func() {\n+\t\tdefer close(echan)\n \n-\t\tif err != nil {\n-\t\t\treturn nil, err\n-\t\t}\n-\t\tdefer func() {\n-\t\t\tif res != nil {\n-\t\t\t\tio.Copy(ioutil.Discard, res.Body)\n-\t\t\t\tif res.Body != nil {\n-\t\t\t\t\tres.Body.Close()\n-\t\t\t\t}\n+\t\tfor i := 0; i < r.errRetryMaxCount; i++ {\n+\t\t\tif _, err := r.updateRoleToken(ctx, domain, role, proxyForPrincipal, minExpiry, maxExpiry); err != nil {\n+\t\t\t\techan <- err\n+\t\t\t\ttime.Sleep(r.errRetryInterval)\n+\t\t\t} else {\n+\t\t\t\tbreak\n \t\t\t}\n-\t\t}()\n-\n-\t\tif res.StatusCode != http.StatusOK {\n-\t\t\treturn nil, ErrRoleTokenRequestFailed\n \t\t}\n+\t}()\n \n-\t\t// decode the token as a role token\n-\t\tvar data *RoleToken\n-\t\terr = json.NewDecoder(res.Body).Decode(&data)\n-\t\tif err != nil {\n-\t\t\treturn nil, err\n+\treturn echan\n+}\n+\n+// updateRoleToken returns RoleToken struct or error.\n+// This function ask athenz to generate role token and return, or return any error when generating the role token.\n+func (r *roleService) updateRoleToken(ctx context.Context, domain, role, proxyForPrincipal string, minExpiry, maxExpiry time.Duration) (*RoleToken, error) {\n+\tkey := encode(domain, role, proxyForPrincipal)\n+\n+\trt, err, _ := r.group.Do(key, func() (interface{}, error) {\n+\t\trt, e := r.fetchRoleToken(ctx, domain, role, proxyForPrincipal, minExpiry, maxExpiry)\n+\t\tif e != nil {\n+\t\t\treturn nil, e\n \t\t}\n \n-\t\t// set the token into cache\n-\t\tr.domainRoleCache.SetWithExpire(encode(domain, role), &cacheData{\n-\t\t\ttoken:             data,\n+\t\tr.domainRoleCache.SetWithExpire(key, &cacheData{\n+\t\t\ttoken:             rt,\n \t\t\tdomain:            domain,\n \t\t\trole:              role,\n \t\t\tproxyForPrincipal: proxyForPrincipal,\n \t\t\tminExpiry:         minExpiry,\n \t\t\tmaxExpiry:         maxExpiry,\n-\t\t}, time.Unix(data.ExpiryTime, 0).Sub(fastime.Now())-time.Minute)\n-\t\treturn data, nil\n+\t\t}, time.Unix(rt.ExpiryTime, 0).Sub(fastime.Now()))\n+\n+\t\treturn rt, nil\n \t})\n+\tif err != nil {\n+\t\treturn nil, err\n+\t}\n+\n+\treturn rt.(*RoleToken), err\n+}\n+\n+// fetchRoleToken fetch the role token from Athenz server, and return the decoded role token and any error if occurred.\n+func (r *roleService) fetchRoleToken(ctx context.Context, domain, role, proxyForPrincipal string, minExpiry, maxExpiry time.Duration) (*RoleToken, error) {\n+\tglg.Debugf(\"get role token, domain: %s, role: %s, proxyForPrincipal: %s, minExpiry: %s, maxExpiry: %s\", domain, role, proxyForPrincipal, minExpiry, maxExpiry)\n+\n+\t// get the n-token\n+\ttok, err := r.token()\n+\tif err != nil {\n+\t\treturn nil, err\n+\t}\n+\n+\t// prepare request object\n+\tu := r.getRoleTokenAthenzURL(domain, role, minExpiry, maxExpiry, proxyForPrincipal)\n+\tglg.Debugf(\"url: %v\", u)\n+\treq, err := http.NewRequest(http.MethodGet, u, nil)\n+\tif err != nil {\n+\t\tglg.Debugf(\"fail to create request object, error: %s\", err)\n+\t\treturn nil, err\n+\t}\n+\treq.Header.Set(r.athenzPrincipleHeader, tok)\n \n+\tres, err := r.httpClient.Do(req.WithContext(ctx))\n \tif err != nil {\n \t\treturn nil, err\n \t}\n \n-\treturn tok.(*RoleToken), nil\n+\tdefer func() {\n+\t\tif res != nil {\n+\t\t\tio.Copy(ioutil.Discard, res.Body)\n+\t\t\tif res.Body != nil {\n+\t\t\t\tres.Body.Close()\n+\t\t\t}\n+\t\t}\n+\t}()\n+\n+\tif res.StatusCode != http.StatusOK {\n+\t\tioutil.ReadAll(res.Body)\n+\t\treturn nil, ErrRoleTokenRequestFailed\n+\t}\n+\n+\tvar data *RoleToken\n+\tif err = json.NewDecoder(res.Body).Decode(&data); err != nil {\n+\t\treturn nil, err\n+\t}\n+\n+\treturn data, nil\n }\n \n func (r *roleService) getCache(domain, role, principal string) (*RoleToken, bool) {\n-\tval, ok := r.domainRoleCache.Get(encode(domain, role))\n+\tval, ok := r.domainRoleCache.Get(encode(domain, role, principal))\n \tif !ok {\n \t\treturn nil, false\n \t}\n \treturn val.(*cacheData).token, ok\n }\n \n-func encode(domain, role string) string {\n-\treturn fmt.Sprintf(\"%s-%s\", domain, role)\n+func encode(domain, role, principal string) string {\n+\ts := []string{domain, role, principal}\n+\tif principal == \"\" {\n+\t\treturn strings.Join(s[:2], cacheKeySeparater)\n+\t}\n+\treturn strings.Join(s, cacheKeySeparater)\n }\n \n-func decode(key string) (string, string) {\n-\tkeys := strings.SplitN(key, \"-\", 3)\n-\tif len(keys) < 2 {\n-\t\treturn key, \"\"\n-\t}\n-\treturn keys[0], keys[1]\n+func decode(key string) (string, string, string) {\n+\tkeys := strings.SplitN(key, cacheKeySeparater, 3)\n+\tres := []string{\"\", \"\", \"\"}","path":"service/role.go","position":345,"original_position":345,"commit_id":"4b4afd3c32fc124894effdfb861cdbadb9fbb545","original_commit_id":"4b4afd3c32fc124894effdfb861cdbadb9fbb545","user":{"login":"WindzCUHK","id":6819063,"node_id":"MDQ6VXNlcjY4MTkwNjM=","avatar_url":"https://avatars1.githubusercontent.com/u/6819063?v=4","gravatar_id":"","url":"https://api.github.com/users/WindzCUHK","html_url":"https://github.com/WindzCUHK","followers_url":"https://api.github.com/users/WindzCUHK/followers","following_url":"https://api.github.com/users/WindzCUHK/following{/other_user}","gists_url":"https://api.github.com/users/WindzCUHK/gists{/gist_id}","starred_url":"https://api.github.com/users/WindzCUHK/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/WindzCUHK/subscriptions","organizations_url":"https://api.github.com/users/WindzCUHK/orgs","repos_url":"https://api.github.com/users/WindzCUHK/repos","events_url":"https://api.github.com/users/WindzCUHK/events{/privacy}","received_events_url":"https://api.github.com/users/WindzCUHK/received_events","type":"User","site_admin":false},"body":"```suggestion\r\n\tres := make([]string, 3)\r\n```","created_at":"2019-10-18T04:33:40Z","updated_at":"2019-10-18T04:54:43Z","html_url":"https://github.com/yahoojapan/athenz-client-sidecar/pull/15#discussion_r336317114","pull_request_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/pulls/15","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/pulls/comments/336317114"},"html":{"href":"https://github.com/yahoojapan/athenz-client-sidecar/pull/15#discussion_r336317114"},"pull_request":{"href":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/pulls/15"}}},"pull_request":{"url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/pulls/15","id":324587028,"node_id":"MDExOlB1bGxSZXF1ZXN0MzI0NTg3MDI4","html_url":"https://github.com/yahoojapan/athenz-client-sidecar/pull/15","diff_url":"https://github.com/yahoojapan/athenz-client-sidecar/pull/15.diff","patch_url":"https://github.com/yahoojapan/athenz-client-sidecar/pull/15.patch","issue_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/issues/15","number":15,"state":"open","locked":false,"title":"[patch] Add refresh interval","user":{"login":"kevindiu","id":1985382,"node_id":"MDQ6VXNlcjE5ODUzODI=","avatar_url":"https://avatars1.githubusercontent.com/u/1985382?v=4","gravatar_id":"","url":"https://api.github.com/users/kevindiu","html_url":"https://github.com/kevindiu","followers_url":"https://api.github.com/users/kevindiu/followers","following_url":"https://api.github.com/users/kevindiu/following{/other_user}","gists_url":"https://api.github.com/users/kevindiu/gists{/gist_id}","starred_url":"https://api.github.com/users/kevindiu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kevindiu/subscriptions","organizations_url":"https://api.github.com/users/kevindiu/orgs","repos_url":"https://api.github.com/users/kevindiu/repos","events_url":"https://api.github.com/users/kevindiu/events{/privacy}","received_events_url":"https://api.github.com/users/kevindiu/received_events","type":"User","site_admin":false},"body":"","created_at":"2019-10-04T09:15:12Z","updated_at":"2019-10-18T04:54:42Z","closed_at":null,"merged_at":null,"merge_commit_sha":"5feb41f3402c2a1d3780efccae2bdf771754511d","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/pulls/15/commits","review_comments_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/pulls/15/comments","review_comment_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/pulls/comments{/number}","comments_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/issues/15/comments","statuses_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/statuses/4b4afd3c32fc124894effdfb861cdbadb9fbb545","head":{"label":"yahoojapan:add_refresh_interval","ref":"add_refresh_interval","sha":"4b4afd3c32fc124894effdfb861cdbadb9fbb545","user":{"login":"yahoojapan","id":1642319,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE2NDIzMTk=","avatar_url":"https://avatars0.githubusercontent.com/u/1642319?v=4","gravatar_id":"","url":"https://api.github.com/users/yahoojapan","html_url":"https://github.com/yahoojapan","followers_url":"https://api.github.com/users/yahoojapan/followers","following_url":"https://api.github.com/users/yahoojapan/following{/other_user}","gists_url":"https://api.github.com/users/yahoojapan/gists{/gist_id}","starred_url":"https://api.github.com/users/yahoojapan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/yahoojapan/subscriptions","organizations_url":"https://api.github.com/users/yahoojapan/orgs","repos_url":"https://api.github.com/users/yahoojapan/repos","events_url":"https://api.github.com/users/yahoojapan/events{/privacy}","received_events_url":"https://api.github.com/users/yahoojapan/received_events","type":"Organization","site_admin":false},"repo":{"id":171427713,"node_id":"MDEwOlJlcG9zaXRvcnkxNzE0Mjc3MTM=","name":"athenz-client-sidecar","full_name":"yahoojapan/athenz-client-sidecar","private":false,"owner":{"login":"yahoojapan","id":1642319,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE2NDIzMTk=","avatar_url":"https://avatars0.githubusercontent.com/u/1642319?v=4","gravatar_id":"","url":"https://api.github.com/users/yahoojapan","html_url":"https://github.com/yahoojapan","followers_url":"https://api.github.com/users/yahoojapan/followers","following_url":"https://api.github.com/users/yahoojapan/following{/other_user}","gists_url":"https://api.github.com/users/yahoojapan/gists{/gist_id}","starred_url":"https://api.github.com/users/yahoojapan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/yahoojapan/subscriptions","organizations_url":"https://api.github.com/users/yahoojapan/orgs","repos_url":"https://api.github.com/users/yahoojapan/repos","events_url":"https://api.github.com/users/yahoojapan/events{/privacy}","received_events_url":"https://api.github.com/users/yahoojapan/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/yahoojapan/athenz-client-sidecar","description":null,"fork":false,"url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar","forks_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/forks","keys_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/keys{/key_id}","collaborators_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/teams","hooks_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/hooks","issue_events_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/issues/events{/number}","events_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/events","assignees_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/assignees{/user}","branches_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/branches{/branch}","tags_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/tags","blobs_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/git/refs{/sha}","trees_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/git/trees{/sha}","statuses_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/statuses/{sha}","languages_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/languages","stargazers_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/stargazers","contributors_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/contributors","subscribers_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/subscribers","subscription_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/subscription","commits_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/commits{/sha}","git_commits_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/git/commits{/sha}","comments_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/comments{/number}","issue_comment_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/issues/comments{/number}","contents_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/contents/{+path}","compare_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/compare/{base}...{head}","merges_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/merges","archive_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/downloads","issues_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/issues{/number}","pulls_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/pulls{/number}","milestones_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/milestones{/number}","notifications_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/labels{/name}","releases_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/releases{/id}","deployments_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/deployments","created_at":"2019-02-19T07:36:38Z","updated_at":"2019-10-18T03:18:49Z","pushed_at":"2019-10-18T03:30:02Z","git_url":"git://github.com/yahoojapan/athenz-client-sidecar.git","ssh_url":"git@github.com:yahoojapan/athenz-client-sidecar.git","clone_url":"https://github.com/yahoojapan/athenz-client-sidecar.git","svn_url":"https://github.com/yahoojapan/athenz-client-sidecar","homepage":null,"size":513,"stargazers_count":2,"watchers_count":2,"language":"Go","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":3,"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":1,"open_issues":3,"watchers":2,"default_branch":"master"}},"base":{"label":"yahoojapan:master","ref":"master","sha":"7627b3dd1f9fee936bbb8fb080b94cb9cef7917b","user":{"login":"yahoojapan","id":1642319,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE2NDIzMTk=","avatar_url":"https://avatars0.githubusercontent.com/u/1642319?v=4","gravatar_id":"","url":"https://api.github.com/users/yahoojapan","html_url":"https://github.com/yahoojapan","followers_url":"https://api.github.com/users/yahoojapan/followers","following_url":"https://api.github.com/users/yahoojapan/following{/other_user}","gists_url":"https://api.github.com/users/yahoojapan/gists{/gist_id}","starred_url":"https://api.github.com/users/yahoojapan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/yahoojapan/subscriptions","organizations_url":"https://api.github.com/users/yahoojapan/orgs","repos_url":"https://api.github.com/users/yahoojapan/repos","events_url":"https://api.github.com/users/yahoojapan/events{/privacy}","received_events_url":"https://api.github.com/users/yahoojapan/received_events","type":"Organization","site_admin":false},"repo":{"id":171427713,"node_id":"MDEwOlJlcG9zaXRvcnkxNzE0Mjc3MTM=","name":"athenz-client-sidecar","full_name":"yahoojapan/athenz-client-sidecar","private":false,"owner":{"login":"yahoojapan","id":1642319,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE2NDIzMTk=","avatar_url":"https://avatars0.githubusercontent.com/u/1642319?v=4","gravatar_id":"","url":"https://api.github.com/users/yahoojapan","html_url":"https://github.com/yahoojapan","followers_url":"https://api.github.com/users/yahoojapan/followers","following_url":"https://api.github.com/users/yahoojapan/following{/other_user}","gists_url":"https://api.github.com/users/yahoojapan/gists{/gist_id}","starred_url":"https://api.github.com/users/yahoojapan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/yahoojapan/subscriptions","organizations_url":"https://api.github.com/users/yahoojapan/orgs","repos_url":"https://api.github.com/users/yahoojapan/repos","events_url":"https://api.github.com/users/yahoojapan/events{/privacy}","received_events_url":"https://api.github.com/users/yahoojapan/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/yahoojapan/athenz-client-sidecar","description":null,"fork":false,"url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar","forks_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/forks","keys_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/keys{/key_id}","collaborators_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/teams","hooks_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/hooks","issue_events_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/issues/events{/number}","events_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/events","assignees_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/assignees{/user}","branches_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/branches{/branch}","tags_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/tags","blobs_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/git/refs{/sha}","trees_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/git/trees{/sha}","statuses_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/statuses/{sha}","languages_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/languages","stargazers_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/stargazers","contributors_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/contributors","subscribers_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/subscribers","subscription_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/subscription","commits_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/commits{/sha}","git_commits_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/git/commits{/sha}","comments_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/comments{/number}","issue_comment_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/issues/comments{/number}","contents_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/contents/{+path}","compare_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/compare/{base}...{head}","merges_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/merges","archive_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/downloads","issues_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/issues{/number}","pulls_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/pulls{/number}","milestones_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/milestones{/number}","notifications_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/labels{/name}","releases_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/releases{/id}","deployments_url":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/deployments","created_at":"2019-02-19T07:36:38Z","updated_at":"2019-10-18T03:18:49Z","pushed_at":"2019-10-18T03:30:02Z","git_url":"git://github.com/yahoojapan/athenz-client-sidecar.git","ssh_url":"git@github.com:yahoojapan/athenz-client-sidecar.git","clone_url":"https://github.com/yahoojapan/athenz-client-sidecar.git","svn_url":"https://github.com/yahoojapan/athenz-client-sidecar","homepage":null,"size":513,"stargazers_count":2,"watchers_count":2,"language":"Go","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":3,"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":1,"open_issues":3,"watchers":2,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/pulls/15"},"html":{"href":"https://github.com/yahoojapan/athenz-client-sidecar/pull/15"},"issue":{"href":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/issues/15"},"comments":{"href":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/issues/15/comments"},"review_comments":{"href":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/pulls/15/comments"},"review_comment":{"href":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/pulls/15/commits"},"statuses":{"href":"https://api.github.com/repos/yahoojapan/athenz-client-sidecar/statuses/4b4afd3c32fc124894effdfb861cdbadb9fbb545"}},"author_association":"MEMBER"}}
{"actor":{"display_login":"WindzCUHK"}}