{"action":"created","comment":{"url":"https://api.github.com/repos/Shopify/ingress/pulls/comments/180968059","pull_request_review_id":111483206,"id":180968059,"diff_hunk":"@@ -184,6 +185,98 @@ var _ = framework.IngressNginxDescribe(\"Dynamic Configuration\", func() {\n \t\t\t})\n \t\tExpect(err).ToNot(HaveOccurred())\n \t})\n+\n+\tContext(\"when session affinity annotation is present\", func() {\n+\t\tIt(\"should use sticky sessions when ingress rules are configured\", func() {\n+\t\t\tcookieName := \"STICKYSESSION\"\n+\n+\t\t\tBy(\"Updating affinity annotation on ingress\")\n+\t\t\tingress, err := f.KubeClientSet.ExtensionsV1beta1().Ingresses(f.Namespace.Name).Get(\"foo.com\", metav1.GetOptions{})\n+\t\t\tExpect(err).ToNot(HaveOccurred())\n+\t\t\tingress.ObjectMeta.Annotations = map[string]string{\n+\t\t\t\t\"nginx.ingress.kubernetes.io/affinity\":            \"cookie\",\n+\t\t\t\t\"nginx.ingress.kubernetes.io/session-cookie-name\": cookieName,\n+\t\t\t}\n+\t\t\t_, err = f.KubeClientSet.ExtensionsV1beta1().Ingresses(f.Namespace.Name).Update(ingress)\n+\t\t\tExpect(err).ToNot(HaveOccurred())\n+\t\t\ttime.Sleep(5 * time.Second)\n+\n+\t\t\tBy(\"Making a first request\")\n+\t\t\thost := \"foo.com\"\n+\t\t\tresp, _, errs := gorequest.New().\n+\t\t\t\tGet(f.NginxHTTPURL).\n+\t\t\t\tSet(\"Host\", host).\n+\t\t\t\tEnd()\n+\t\t\tExpect(len(errs)).Should(BeNumerically(\"==\", 0))\n+\t\t\tExpect(resp.StatusCode).Should(Equal(http.StatusOK))\n+\n+\t\t\tcookies := (*http.Response)(resp).Cookies()\n+\t\t\tsessionCookie, err := getCookie(cookieName, cookies)\n+\t\t\tExpect(err).ToNot(HaveOccurred())\n+\n+\t\t\tBy(\"Making a second request with the previous session cookie\")\n+\t\t\tresp, _, errs = gorequest.New().\n+\t\t\t\tGet(f.NginxHTTPURL).\n+\t\t\t\tAddCookie(sessionCookie).\n+\t\t\t\tSet(\"Host\", host).\n+\t\t\t\tEnd()\n+\t\t\tExpect(len(errs)).Should(BeNumerically(\"==\", 0))\n+\t\t\tExpect(resp.StatusCode).Should(Equal(http.StatusOK))\n+\n+\t\t\tBy(\"Making a third request with no cookie\")\n+\t\t\tresp, _, errs = gorequest.New().\n+\t\t\t\tGet(f.NginxHTTPURL).\n+\t\t\t\tSet(\"Host\", host).\n+\t\t\t\tEnd()\n+\n+\t\t\tExpect(len(errs)).Should(BeNumerically(\"==\", 0))\n+\t\t\tExpect(resp.StatusCode).Should(Equal(http.StatusOK))\n+\n+\t\t\tlog, err := f.NginxLogs()\n+\t\t\tExpect(err).ToNot(HaveOccurred())\n+\t\t\tExpect(log).ToNot(BeEmpty())\n+\n+\t\t\tBy(\"Checking that upstreams are sticky when session cookie is used\")\n+\t\t\tindex := strings.Index(log, fmt.Sprintf(\"reason: 'UPDATE' Ingress %s/foo.com\", f.Namespace.Name))\n+\t\t\treqLogs := log[index:]\n+\t\t\tre := regexp.MustCompile(`\\d{1,3}(?:\\.\\d{1,3}){3}(?::\\d{1,5})`)\n+\t\t\tupstreams := re.FindAllString(reqLogs, -1)\n+\t\t\tExpect(len(upstreams)).Should(BeNumerically(\"==\", 3))\n+\t\t\tExpect(upstreams[0]).To(Equal(upstreams[1]))\n+\t\t\tExpect(upstreams[1]).ToNot(Equal(upstreams[2]))","path":"test/e2e/lua/dynamic_configuration.go","position":79,"original_position":79,"commit_id":"062170df865239d3e5e6e3a62da62901262b249b","original_commit_id":"062170df865239d3e5e6e3a62da62901262b249b","user":{"login":"ElvinEfendi","id":1150042,"avatar_url":"https://avatars0.githubusercontent.com/u/1150042?v=4","gravatar_id":"","url":"https://api.github.com/users/ElvinEfendi","html_url":"https://github.com/ElvinEfendi","followers_url":"https://api.github.com/users/ElvinEfendi/followers","following_url":"https://api.github.com/users/ElvinEfendi/following{/other_user}","gists_url":"https://api.github.com/users/ElvinEfendi/gists{/gist_id}","starred_url":"https://api.github.com/users/ElvinEfendi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ElvinEfendi/subscriptions","organizations_url":"https://api.github.com/users/ElvinEfendi/orgs","repos_url":"https://api.github.com/users/ElvinEfendi/repos","events_url":"https://api.github.com/users/ElvinEfendi/events{/privacy}","received_events_url":"https://api.github.com/users/ElvinEfendi/received_events","type":"User","site_admin":false},"body":"💯 ","created_at":"2018-04-12T05:26:06Z","updated_at":"2018-04-12T05:26:07Z","html_url":"https://github.com/Shopify/ingress/pull/34#discussion_r180968059","pull_request_url":"https://api.github.com/repos/Shopify/ingress/pulls/34","author_association":"NONE","_links":{"self":{"href":"https://api.github.com/repos/Shopify/ingress/pulls/comments/180968059"},"html":{"href":"https://github.com/Shopify/ingress/pull/34#discussion_r180968059"},"pull_request":{"href":"https://api.github.com/repos/Shopify/ingress/pulls/34"}}},"pull_request":{"url":"https://api.github.com/repos/Shopify/ingress/pulls/34","id":177544925,"html_url":"https://github.com/Shopify/ingress/pull/34","diff_url":"https://github.com/Shopify/ingress/pull/34.diff","patch_url":"https://github.com/Shopify/ingress/pull/34.patch","issue_url":"https://api.github.com/repos/Shopify/ingress/issues/34","number":34,"state":"open","locked":false,"title":"Add session affinity to custom load balancing","user":{"login":"zrdaley","id":17059671,"avatar_url":"https://avatars2.githubusercontent.com/u/17059671?v=4","gravatar_id":"","url":"https://api.github.com/users/zrdaley","html_url":"https://github.com/zrdaley","followers_url":"https://api.github.com/users/zrdaley/followers","following_url":"https://api.github.com/users/zrdaley/following{/other_user}","gists_url":"https://api.github.com/users/zrdaley/gists{/gist_id}","starred_url":"https://api.github.com/users/zrdaley/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zrdaley/subscriptions","organizations_url":"https://api.github.com/users/zrdaley/orgs","repos_url":"https://api.github.com/users/zrdaley/repos","events_url":"https://api.github.com/users/zrdaley/events{/privacy}","received_events_url":"https://api.github.com/users/zrdaley/received_events","type":"User","site_admin":false},"body":"### What this PR does / why we need it\r\n\r\nThis PR adds **session affinity through cookies** to the lua custom load balancing module when dynamic configuration is enabled. \r\n\r\nThis implementation mimics the current implementation used for sticky sessions in `kubernetes/ingress-nginx` when dynamic configuration is **not** enabled ([k8 documentation on sticky sessions](https://github.com/kubernetes/ingress-nginx/blob/master/docs/examples/affinity/cookie/README.md))\r\n\r\nRelated issue: https://github.com/Shopify/edgescale/issues/373\r\n\r\n@Shopify/edgescale \r\n\r\n\r\n### **`kubernetes/ingress-nginx` implementation**\r\n1. If the [affinity annotation](https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/annotations.md#session-affinity) is set to \"cookie\" on an ingress then a `sticky-{{ $upstream.name }}` upstream is defined in the nginx template (see [code](https://github.com/kubernetes/ingress-nginx/blob/385368990cd678d08fe0b30fd8f087cfaad91a19/rootfs/etc/nginx/template/nginx.tmpl#L350-L352))\r\n2. The [nginx-sticky-module-ng](https://bitbucket.org/nginx-goodies/nginx-sticky-module-ng) is used to handle sticky upstreams \r\n>A nginx module to add a sticky cookie to be always forwarded to the same upstream server...\r\n>When the sticky module can't apply, it switchs back to the classic Round Robin Upstream or returns a \"Bad Gateway\" (depending on the no_fallback flag).\r\n3. The [nginx template proxy_pass](https://github.com/kubernetes/ingress-nginx/blob/385368990cd678d08fe0b30fd8f087cfaad91a19/rootfs/etc/nginx/template/nginx.tmpl#L986) is built in [template.go](https://github.com/kubernetes/ingress-nginx/blob/adf12fced1d9db98c767554adff1c7895e50ee24/internal/ingress/controller/template/template.go#L348-L349); if the backend is sticky then it will return `sticky-{{ $upstream.name }}` and use the upstream defined in step i.\r\n\r\n### **New custom Lua implementation**\r\n1. In the lua [balancer module](https://github.com/Shopify/ingress/blob/c1937876ed35406748ae996bd59dc5a7b40017d3/rootfs/etc/nginx/lua/balancer.lua#L44-L50) the session [affinity annotation](https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/annotations.md#session-affinity) with the value \"cookie\" is checked for\r\n2. If it exists, then a cookie named by the [session-cookie-name annotation](https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/annotations.md#cookie-affinity) value (default is \"route\") is checked for\r\n3. If the cookie:\r\n    - **Does NOT exist:** \r\n        1. The round robin algorithm is used to determine the upstream to forward to *\r\n        2. The upstream is converted to an `<IP>:<Port>` string and hashed using the [session-cookie-hash annotation](https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/annotations.md#cookie-affinity) value (default is \"md5\") \r\n        3. A new cookie is set with [session-cookie-name annotation](https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/annotations.md#cookie-affinity) as the name and the hash as the value\r\n        4. The upstream is stored in the shared lua dictionary named `sticky-sessions`\r\n            - `sticky-sessions` stores the following key value pairs: **\r\n                - _key_: The hash of the cookie\r\n                - _value_: The raw `<IP>:<Port>` string of the upstream to be forwarded to\r\n        5. The IP and port of the upstream are set as the current peer\r\n    - **DOES exist**\r\n        1. The stored cookie is looked up in the shared lua dictionary, `sticky-sessions`**\r\n        2. The IP and port returned from the dictionary lookup are checked to determine if they're still routable\r\n        3. If the IP and port:\r\n            - **ARE routable**\r\n                - The IP and port of the upstream are set as the current peer\r\n            - **Are NOT routable**\r\n                - Follow procedure in Step 3: Does NOT exist\r\n\r\n\r\n*Any of custom load balancing algorithms can be to balance with session affinity. Defaulting to round robin is just to be consistent with nginx-sticky-module-ng used for session affinity when dynamic configuration is not enabled. \r\n\r\n\r\n","created_at":"2018-03-26T19:31:49Z","updated_at":"2018-04-12T05:26:07Z","closed_at":null,"merged_at":null,"merge_commit_sha":"03f89d039d3711e55831b1f3a3b6c3faafecfc77","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/Shopify/ingress/pulls/34/commits","review_comments_url":"https://api.github.com/repos/Shopify/ingress/pulls/34/comments","review_comment_url":"https://api.github.com/repos/Shopify/ingress/pulls/comments{/number}","comments_url":"https://api.github.com/repos/Shopify/ingress/issues/34/comments","statuses_url":"https://api.github.com/repos/Shopify/ingress/statuses/062170df865239d3e5e6e3a62da62901262b249b","head":{"label":"Shopify:sticky","ref":"sticky","sha":"062170df865239d3e5e6e3a62da62901262b249b","user":{"login":"Shopify","id":8085,"avatar_url":"https://avatars1.githubusercontent.com/u/8085?v=4","gravatar_id":"","url":"https://api.github.com/users/Shopify","html_url":"https://github.com/Shopify","followers_url":"https://api.github.com/users/Shopify/followers","following_url":"https://api.github.com/users/Shopify/following{/other_user}","gists_url":"https://api.github.com/users/Shopify/gists{/gist_id}","starred_url":"https://api.github.com/users/Shopify/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Shopify/subscriptions","organizations_url":"https://api.github.com/users/Shopify/orgs","repos_url":"https://api.github.com/users/Shopify/repos","events_url":"https://api.github.com/users/Shopify/events{/privacy}","received_events_url":"https://api.github.com/users/Shopify/received_events","type":"Organization","site_admin":false},"repo":{"id":99704668,"name":"ingress","full_name":"Shopify/ingress","owner":{"login":"Shopify","id":8085,"avatar_url":"https://avatars1.githubusercontent.com/u/8085?v=4","gravatar_id":"","url":"https://api.github.com/users/Shopify","html_url":"https://github.com/Shopify","followers_url":"https://api.github.com/users/Shopify/followers","following_url":"https://api.github.com/users/Shopify/following{/other_user}","gists_url":"https://api.github.com/users/Shopify/gists{/gist_id}","starred_url":"https://api.github.com/users/Shopify/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Shopify/subscriptions","organizations_url":"https://api.github.com/users/Shopify/orgs","repos_url":"https://api.github.com/users/Shopify/repos","events_url":"https://api.github.com/users/Shopify/events{/privacy}","received_events_url":"https://api.github.com/users/Shopify/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Shopify/ingress","description":"Ingress controllers","fork":true,"url":"https://api.github.com/repos/Shopify/ingress","forks_url":"https://api.github.com/repos/Shopify/ingress/forks","keys_url":"https://api.github.com/repos/Shopify/ingress/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Shopify/ingress/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Shopify/ingress/teams","hooks_url":"https://api.github.com/repos/Shopify/ingress/hooks","issue_events_url":"https://api.github.com/repos/Shopify/ingress/issues/events{/number}","events_url":"https://api.github.com/repos/Shopify/ingress/events","assignees_url":"https://api.github.com/repos/Shopify/ingress/assignees{/user}","branches_url":"https://api.github.com/repos/Shopify/ingress/branches{/branch}","tags_url":"https://api.github.com/repos/Shopify/ingress/tags","blobs_url":"https://api.github.com/repos/Shopify/ingress/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Shopify/ingress/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Shopify/ingress/git/refs{/sha}","trees_url":"https://api.github.com/repos/Shopify/ingress/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Shopify/ingress/statuses/{sha}","languages_url":"https://api.github.com/repos/Shopify/ingress/languages","stargazers_url":"https://api.github.com/repos/Shopify/ingress/stargazers","contributors_url":"https://api.github.com/repos/Shopify/ingress/contributors","subscribers_url":"https://api.github.com/repos/Shopify/ingress/subscribers","subscription_url":"https://api.github.com/repos/Shopify/ingress/subscription","commits_url":"https://api.github.com/repos/Shopify/ingress/commits{/sha}","git_commits_url":"https://api.github.com/repos/Shopify/ingress/git/commits{/sha}","comments_url":"https://api.github.com/repos/Shopify/ingress/comments{/number}","issue_comment_url":"https://api.github.com/repos/Shopify/ingress/issues/comments{/number}","contents_url":"https://api.github.com/repos/Shopify/ingress/contents/{+path}","compare_url":"https://api.github.com/repos/Shopify/ingress/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Shopify/ingress/merges","archive_url":"https://api.github.com/repos/Shopify/ingress/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Shopify/ingress/downloads","issues_url":"https://api.github.com/repos/Shopify/ingress/issues{/number}","pulls_url":"https://api.github.com/repos/Shopify/ingress/pulls{/number}","milestones_url":"https://api.github.com/repos/Shopify/ingress/milestones{/number}","notifications_url":"https://api.github.com/repos/Shopify/ingress/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Shopify/ingress/labels{/name}","releases_url":"https://api.github.com/repos/Shopify/ingress/releases{/id}","deployments_url":"https://api.github.com/repos/Shopify/ingress/deployments","created_at":"2017-08-08T14:55:27Z","updated_at":"2018-04-11T16:41:03Z","pushed_at":"2018-04-11T20:29:13Z","git_url":"git://github.com/Shopify/ingress.git","ssh_url":"git@github.com:Shopify/ingress.git","clone_url":"https://github.com/Shopify/ingress.git","svn_url":"https://github.com/Shopify/ingress","homepage":null,"size":66265,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":3,"mirror_url":null,"archived":false,"open_issues_count":8,"license":null,"forks":3,"open_issues":8,"watchers":0,"default_branch":"master"}},"base":{"label":"Shopify:master","ref":"master","sha":"a609d78e9c20222259baef08d16ed30db4902b77","user":{"login":"Shopify","id":8085,"avatar_url":"https://avatars1.githubusercontent.com/u/8085?v=4","gravatar_id":"","url":"https://api.github.com/users/Shopify","html_url":"https://github.com/Shopify","followers_url":"https://api.github.com/users/Shopify/followers","following_url":"https://api.github.com/users/Shopify/following{/other_user}","gists_url":"https://api.github.com/users/Shopify/gists{/gist_id}","starred_url":"https://api.github.com/users/Shopify/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Shopify/subscriptions","organizations_url":"https://api.github.com/users/Shopify/orgs","repos_url":"https://api.github.com/users/Shopify/repos","events_url":"https://api.github.com/users/Shopify/events{/privacy}","received_events_url":"https://api.github.com/users/Shopify/received_events","type":"Organization","site_admin":false},"repo":{"id":99704668,"name":"ingress","full_name":"Shopify/ingress","owner":{"login":"Shopify","id":8085,"avatar_url":"https://avatars1.githubusercontent.com/u/8085?v=4","gravatar_id":"","url":"https://api.github.com/users/Shopify","html_url":"https://github.com/Shopify","followers_url":"https://api.github.com/users/Shopify/followers","following_url":"https://api.github.com/users/Shopify/following{/other_user}","gists_url":"https://api.github.com/users/Shopify/gists{/gist_id}","starred_url":"https://api.github.com/users/Shopify/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Shopify/subscriptions","organizations_url":"https://api.github.com/users/Shopify/orgs","repos_url":"https://api.github.com/users/Shopify/repos","events_url":"https://api.github.com/users/Shopify/events{/privacy}","received_events_url":"https://api.github.com/users/Shopify/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Shopify/ingress","description":"Ingress controllers","fork":true,"url":"https://api.github.com/repos/Shopify/ingress","forks_url":"https://api.github.com/repos/Shopify/ingress/forks","keys_url":"https://api.github.com/repos/Shopify/ingress/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Shopify/ingress/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Shopify/ingress/teams","hooks_url":"https://api.github.com/repos/Shopify/ingress/hooks","issue_events_url":"https://api.github.com/repos/Shopify/ingress/issues/events{/number}","events_url":"https://api.github.com/repos/Shopify/ingress/events","assignees_url":"https://api.github.com/repos/Shopify/ingress/assignees{/user}","branches_url":"https://api.github.com/repos/Shopify/ingress/branches{/branch}","tags_url":"https://api.github.com/repos/Shopify/ingress/tags","blobs_url":"https://api.github.com/repos/Shopify/ingress/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Shopify/ingress/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Shopify/ingress/git/refs{/sha}","trees_url":"https://api.github.com/repos/Shopify/ingress/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Shopify/ingress/statuses/{sha}","languages_url":"https://api.github.com/repos/Shopify/ingress/languages","stargazers_url":"https://api.github.com/repos/Shopify/ingress/stargazers","contributors_url":"https://api.github.com/repos/Shopify/ingress/contributors","subscribers_url":"https://api.github.com/repos/Shopify/ingress/subscribers","subscription_url":"https://api.github.com/repos/Shopify/ingress/subscription","commits_url":"https://api.github.com/repos/Shopify/ingress/commits{/sha}","git_commits_url":"https://api.github.com/repos/Shopify/ingress/git/commits{/sha}","comments_url":"https://api.github.com/repos/Shopify/ingress/comments{/number}","issue_comment_url":"https://api.github.com/repos/Shopify/ingress/issues/comments{/number}","contents_url":"https://api.github.com/repos/Shopify/ingress/contents/{+path}","compare_url":"https://api.github.com/repos/Shopify/ingress/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Shopify/ingress/merges","archive_url":"https://api.github.com/repos/Shopify/ingress/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Shopify/ingress/downloads","issues_url":"https://api.github.com/repos/Shopify/ingress/issues{/number}","pulls_url":"https://api.github.com/repos/Shopify/ingress/pulls{/number}","milestones_url":"https://api.github.com/repos/Shopify/ingress/milestones{/number}","notifications_url":"https://api.github.com/repos/Shopify/ingress/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Shopify/ingress/labels{/name}","releases_url":"https://api.github.com/repos/Shopify/ingress/releases{/id}","deployments_url":"https://api.github.com/repos/Shopify/ingress/deployments","created_at":"2017-08-08T14:55:27Z","updated_at":"2018-04-11T16:41:03Z","pushed_at":"2018-04-11T20:29:13Z","git_url":"git://github.com/Shopify/ingress.git","ssh_url":"git@github.com:Shopify/ingress.git","clone_url":"https://github.com/Shopify/ingress.git","svn_url":"https://github.com/Shopify/ingress","homepage":null,"size":66265,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":3,"mirror_url":null,"archived":false,"open_issues_count":8,"license":null,"forks":3,"open_issues":8,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/Shopify/ingress/pulls/34"},"html":{"href":"https://github.com/Shopify/ingress/pull/34"},"issue":{"href":"https://api.github.com/repos/Shopify/ingress/issues/34"},"comments":{"href":"https://api.github.com/repos/Shopify/ingress/issues/34/comments"},"review_comments":{"href":"https://api.github.com/repos/Shopify/ingress/pulls/34/comments"},"review_comment":{"href":"https://api.github.com/repos/Shopify/ingress/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/Shopify/ingress/pulls/34/commits"},"statuses":{"href":"https://api.github.com/repos/Shopify/ingress/statuses/062170df865239d3e5e6e3a62da62901262b249b"}},"author_association":"NONE"}}
{"actor":{"display_login":"ElvinEfendi"}}