{"action":"created","comment":{"url":"https://api.github.com/repos/Shopify/ingress/pulls/comments/226339804","pull_request_review_id":166138838,"id":226339804,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIyNjMzOTgwNA==","diff_hunk":"@@ -48,6 +48,7 @@ var (\n // Configuration holds the definition of all the parts required to describe all\n // ingresses reachable by the ingress controller (using a filter by namespace)\n type Configuration struct {\n+","path":"internal/ingress/types.go","position":4,"original_position":4,"commit_id":"dff2dffd882cecfffacd84bb5918fe8e2f9ad6fd","original_commit_id":"dff2dffd882cecfffacd84bb5918fe8e2f9ad6fd","user":{"login":"clandry94","id":5351125,"node_id":"MDQ6VXNlcjUzNTExMjU=","avatar_url":"https://avatars0.githubusercontent.com/u/5351125?v=4","gravatar_id":"","url":"https://api.github.com/users/clandry94","html_url":"https://github.com/clandry94","followers_url":"https://api.github.com/users/clandry94/followers","following_url":"https://api.github.com/users/clandry94/following{/other_user}","gists_url":"https://api.github.com/users/clandry94/gists{/gist_id}","starred_url":"https://api.github.com/users/clandry94/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/clandry94/subscriptions","organizations_url":"https://api.github.com/users/clandry94/orgs","repos_url":"https://api.github.com/users/clandry94/repos","events_url":"https://api.github.com/users/clandry94/events{/privacy}","received_events_url":"https://api.github.com/users/clandry94/received_events","type":"User","site_admin":false},"body":"I don't remember adding this line, maybe gofmt did? I'll remove it and see if any checks yell at me","created_at":"2018-10-18T14:55:49Z","updated_at":"2018-10-18T14:55:49Z","html_url":"https://github.com/Shopify/ingress/pull/120#discussion_r226339804","pull_request_url":"https://api.github.com/repos/Shopify/ingress/pulls/120","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/Shopify/ingress/pulls/comments/226339804"},"html":{"href":"https://github.com/Shopify/ingress/pull/120#discussion_r226339804"},"pull_request":{"href":"https://api.github.com/repos/Shopify/ingress/pulls/120"}},"in_reply_to_id":226337788},"pull_request":{"url":"https://api.github.com/repos/Shopify/ingress/pulls/120","id":219424275,"node_id":"MDExOlB1bGxSZXF1ZXN0MjE5NDI0Mjc1","html_url":"https://github.com/Shopify/ingress/pull/120","diff_url":"https://github.com/Shopify/ingress/pull/120.diff","patch_url":"https://github.com/Shopify/ingress/pull/120.patch","issue_url":"https://api.github.com/repos/Shopify/ingress/issues/120","number":120,"state":"open","locked":false,"title":"Implement canary ingresses","user":{"login":"clandry94","id":5351125,"node_id":"MDQ6VXNlcjUzNTExMjU=","avatar_url":"https://avatars0.githubusercontent.com/u/5351125?v=4","gravatar_id":"","url":"https://api.github.com/users/clandry94","html_url":"https://github.com/clandry94","followers_url":"https://api.github.com/users/clandry94/followers","following_url":"https://api.github.com/users/clandry94/following{/other_user}","gists_url":"https://api.github.com/users/clandry94/gists{/gist_id}","starred_url":"https://api.github.com/users/clandry94/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/clandry94/subscriptions","organizations_url":"https://api.github.com/users/clandry94/orgs","repos_url":"https://api.github.com/users/clandry94/repos","events_url":"https://api.github.com/users/clandry94/events{/privacy}","received_events_url":"https://api.github.com/users/clandry94/received_events","type":"User","site_admin":false},"body":"Implements the feature described here https://github.com/Shopify/edgescale/issues/664 \r\n\r\nThis PR adds the initial support for multi-service routing per ingress by means of virtual backends. It also implements an interface to create these virtual backends through the form of canary deploys. \r\n\r\n### Some terms\r\n**VirtualBackend** - A virtual backend is a normal ingress-nginx backend with the condition that it is not backed through the typical 1:1 backend-server relationship. Instead, virtual backends share a server with another real backend.\r\n\r\n**Real Backend** - This is the same as a backend. I prefix with the word real to have a clearer distinction between it and a virtual backend\r\n\r\n### How it works\r\n\r\n#### Canary\r\nAs described in the linked issue above, the following annotation\r\n```\r\nnginx.ingress.kubernetes.io/canary: true\r\n```\r\nCombined with a combination of the below annotations, we can define the behaviour of the canary. \r\n\r\nThe canary will define a `canary-weight`. If only weight is specified, then n% of traffic will be shifted to the canary backend. Additionally, if `canary-by-cookie` or `canary-by-header` are set, they will shift all traffic which match the cookie/header set with a value of `always` to the canary backend. If no value is set for the header, it will follow the rules of `canary-weight`. \r\n\r\n```\r\nnginx.ingress.kubernetes.io/canary-by-cookie: <cookie name>\r\nnginx.ingress.kubernetes.io/canary-by-header: <header name>\r\nnginx.ingress.kubernetes.io/canary-weight: <0 to 100>\r\n```\r\n\r\nAfter the spec is applied, the ingress in question has it's backends marked as virtual so that the merging code will know what to do with them.\r\n\r\n#### VirtualBackends\r\n\r\nWhen ingresses are synced, the list of backends and servers is built up. After these lists are finished being built in `getBackendServers()`, but before they are sorted and returned to the sync function, we check if the current ingress has a canary enabled. If so, we pass a reference of the ingress, annotations, upstreams, and servers to the `mergeVirtualBackends` function. It works as such:\r\n1) For each path that matches a virtual backend, find the server that matches its path and is not virtual. \r\n2) If found, embed a virtual backend definition into the real backend. If no matching path is found, then delete the virtual upstream as it is invalid and has no server to back it. \r\n\r\nWhen virtual backends are matched to a real backend, they will have access to metadata that describes the real backend as well as rules to shape traffic. These rules come from the canary ingress configuration. \r\n\r\n","created_at":"2018-10-01T15:44:51Z","updated_at":"2018-10-18T14:55:49Z","closed_at":null,"merged_at":null,"merge_commit_sha":"a6af0325e0a6c99ee99f5691a6334e131f2275f6","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/Shopify/ingress/pulls/120/commits","review_comments_url":"https://api.github.com/repos/Shopify/ingress/pulls/120/comments","review_comment_url":"https://api.github.com/repos/Shopify/ingress/pulls/comments{/number}","comments_url":"https://api.github.com/repos/Shopify/ingress/issues/120/comments","statuses_url":"https://api.github.com/repos/Shopify/ingress/statuses/dff2dffd882cecfffacd84bb5918fe8e2f9ad6fd","head":{"label":"Shopify:canary_ingress","ref":"canary_ingress","sha":"dff2dffd882cecfffacd84bb5918fe8e2f9ad6fd","user":{"login":"Shopify","id":8085,"node_id":"MDEyOk9yZ2FuaXphdGlvbjgwODU=","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,"node_id":"MDEwOlJlcG9zaXRvcnk5OTcwNDY2OA==","name":"ingress","full_name":"Shopify/ingress","private":false,"owner":{"login":"Shopify","id":8085,"node_id":"MDEyOk9yZ2FuaXphdGlvbjgwODU=","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},"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-10-16T01:00:02Z","pushed_at":"2018-10-18T13:44:42Z","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":75211,"stargazers_count":3,"watchers_count":3,"language":"Go","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":5,"mirror_url":null,"archived":false,"open_issues_count":10,"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":5,"open_issues":10,"watchers":3,"default_branch":"master"}},"base":{"label":"Shopify:master","ref":"master","sha":"3019560e28312923600d1e7844e10dd84349b823","user":{"login":"Shopify","id":8085,"node_id":"MDEyOk9yZ2FuaXphdGlvbjgwODU=","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,"node_id":"MDEwOlJlcG9zaXRvcnk5OTcwNDY2OA==","name":"ingress","full_name":"Shopify/ingress","private":false,"owner":{"login":"Shopify","id":8085,"node_id":"MDEyOk9yZ2FuaXphdGlvbjgwODU=","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},"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-10-16T01:00:02Z","pushed_at":"2018-10-18T13:44:42Z","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":75211,"stargazers_count":3,"watchers_count":3,"language":"Go","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":5,"mirror_url":null,"archived":false,"open_issues_count":10,"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":5,"open_issues":10,"watchers":3,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/Shopify/ingress/pulls/120"},"html":{"href":"https://github.com/Shopify/ingress/pull/120"},"issue":{"href":"https://api.github.com/repos/Shopify/ingress/issues/120"},"comments":{"href":"https://api.github.com/repos/Shopify/ingress/issues/120/comments"},"review_comments":{"href":"https://api.github.com/repos/Shopify/ingress/pulls/120/comments"},"review_comment":{"href":"https://api.github.com/repos/Shopify/ingress/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/Shopify/ingress/pulls/120/commits"},"statuses":{"href":"https://api.github.com/repos/Shopify/ingress/statuses/dff2dffd882cecfffacd84bb5918fe8e2f9ad6fd"}},"author_association":"MEMBER"}}
{"actor":{"display_login":"clandry94"}}