{"action":"created","comment":{"url":"https://api.github.com/repos/zendesk/samson/pulls/comments/42759269","id":42759269,"diff_hunk":"@@ -0,0 +1,95 @@\n+module Kubernetes\n+  # Convenience wrapper around the 'Service' object we can get from the K8S API\n+  class Service\n+    attr_reader :deploy_group, :role, :name, :ip_address, :port_info\n+\n+    def initialize(deploy_group: nil, role: nil)\n+      @deploy_group = deploy_group\n+      @role = role\n+      @port_info = []\n+      @name = role.try(:service_name)\n+    end\n+\n+    def namespace\n+      deploy_group.kubernetes_namespace\n+    end\n+\n+    def running?\n+      service_object.present?\n+    end\n+\n+    def proxy_address\n+      \"#{example_node_ip}:#{node_ports.first}\" if running?\n+    end\n+\n+    def example_node_ip\n+      node = client.get_nodes.first\n+      node.spec.externalID if node\n+    end\n+\n+    # The set of ports that are exposed on each Kubernetes minion. Traffic sent\n+    # to this port on any minion will be proxied to the Pods in this service.\n+    def node_ports\n+      fetch_service if @service_object.nil?\n+      @port_info.map(&:nodePort)\n+    end\n+\n+    # Returns an array of OpenStructs containing the list of Pods that this\n+    # service routes traffic to. Each object return has the following attributes:\n+    #   `pod_ip` : IP address of the Pod\n+    #   `pod_name` : name of the Pod\n+    #   `ready?` : true if the Pod is ready and accepting traffic\n+    def endpoints\n+      return [] if endpoint_object.nil?\n+\n+      results = []\n+\n+      # https://htmlpreview.github.io/?https://github.com/kubernetes/kubernetes/HEAD/docs/api-reference/v1/definitions.html#_v1_endpoints\n+      endpoint_object.subsets.each do |subset|\n+        [:addresses, :notReadyAddresses].each do |attr|\n+          next if subset[attr].blank?\n+\n+          subset[attr].each do |address|\n+            if address.targetRef.kind == 'Pod'\n+              results << OpenStruct.new(pod_ip: address.ip,\n+                                        pod_name: address.targetRef.name,\n+                                        ready?: (attr == :addresses))\n+            end\n+          end\n+        end\n+      end\n+\n+      results\n+    end\n+\n+    def service_object\n+      @service_object || fetch_service\n+    end\n+\n+    def endpoint_object\n+      @endpoint_object || fetch_endpoint\n+    end\n+\n+    private\n+\n+    def fetch_service","path":"plugins/kubernetes/app/models/kubernetes/service.rb","position":75,"original_position":75,"commit_id":"db90027911d2e54ff5cc3650e6953aad4adb4f10","original_commit_id":"db90027911d2e54ff5cc3650e6953aad4adb4f10","user":{"login":"henders","id":515143,"avatar_url":"https://avatars.githubusercontent.com/u/515143?v=3","gravatar_id":"","url":"https://api.github.com/users/henders","html_url":"https://github.com/henders","followers_url":"https://api.github.com/users/henders/followers","following_url":"https://api.github.com/users/henders/following{/other_user}","gists_url":"https://api.github.com/users/henders/gists{/gist_id}","starred_url":"https://api.github.com/users/henders/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/henders/subscriptions","organizations_url":"https://api.github.com/users/henders/orgs","repos_url":"https://api.github.com/users/henders/repos","events_url":"https://api.github.com/users/henders/events{/privacy}","received_events_url":"https://api.github.com/users/henders/received_events","type":"User","site_admin":false},"body":"Should probably make this a lazy-loading function properly for @service_object, and make name, ip_address, etc... lazy accesses as well.\r\n\r\nBut I foresee a fair amount of refactoring coming to this code anyway when we start adding tests. So we can possibility ignore this for now.","created_at":"2015-10-22T15:01:35Z","updated_at":"2015-10-22T15:01:35Z","html_url":"https://github.com/zendesk/samson/pull/605#discussion_r42759269","pull_request_url":"https://api.github.com/repos/zendesk/samson/pulls/605","_links":{"self":{"href":"https://api.github.com/repos/zendesk/samson/pulls/comments/42759269"},"html":{"href":"https://github.com/zendesk/samson/pull/605#discussion_r42759269"},"pull_request":{"href":"https://api.github.com/repos/zendesk/samson/pulls/605"}}},"pull_request":{"url":"https://api.github.com/repos/zendesk/samson/pulls/605","id":48267543,"html_url":"https://github.com/zendesk/samson/pull/605","diff_url":"https://github.com/zendesk/samson/pull/605.diff","patch_url":"https://github.com/zendesk/samson/pull/605.patch","issue_url":"https://api.github.com/repos/zendesk/samson/issues/605","number":605,"state":"open","locked":false,"title":"Create Kubernetes Services as part of deploy","user":{"login":"jonmoter","id":1056506,"avatar_url":"https://avatars.githubusercontent.com/u/1056506?v=3","gravatar_id":"","url":"https://api.github.com/users/jonmoter","html_url":"https://github.com/jonmoter","followers_url":"https://api.github.com/users/jonmoter/followers","following_url":"https://api.github.com/users/jonmoter/following{/other_user}","gists_url":"https://api.github.com/users/jonmoter/gists{/gist_id}","starred_url":"https://api.github.com/users/jonmoter/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jonmoter/subscriptions","organizations_url":"https://api.github.com/users/jonmoter/orgs","repos_url":"https://api.github.com/users/jonmoter/repos","events_url":"https://api.github.com/users/jonmoter/events{/privacy}","received_events_url":"https://api.github.com/users/jonmoter/received_events","type":"User","site_admin":false},"body":"When a project is deployed to Kubernetes for the first time, a Service should be created for every `Role` that defines a service.\r\n\r\nThis PR creates a `Kubernetes::Service` object that wraps some functionality of the Service abstraction. Right now it's just a ruby class, but I'm considering adding a table in the DB to keep track of them. I need to give that a little more thought.\r\n\r\nIt also adds logic to `KuberDeployService` to create the Service as part of deployment.\r\n\r\nSadly, this is still lacking in tests. I need to give some thought on how to make all this code more testable. I think we'll need some kind of Kubernetes testing framework, and maybe some integration tests.\r\n\r\n/cc @henders, @msufa, @sbrnunes \r\n\r\n### References\r\n - Jira link: https://zendesk.atlassian.net/browse/PAAS-36\r\n\r\n### Risks\r\n - Only affects Kubernetes plugin code, so minimal risk to primary Samson functionality.","created_at":"2015-10-20T22:40:45Z","updated_at":"2015-10-22T15:01:35Z","closed_at":null,"merged_at":null,"merge_commit_sha":"95049e506e152f4b8d0537f2ea093474daf6cb01","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/zendesk/samson/pulls/605/commits","review_comments_url":"https://api.github.com/repos/zendesk/samson/pulls/605/comments","review_comment_url":"https://api.github.com/repos/zendesk/samson/pulls/comments{/number}","comments_url":"https://api.github.com/repos/zendesk/samson/issues/605/comments","statuses_url":"https://api.github.com/repos/zendesk/samson/statuses/db90027911d2e54ff5cc3650e6953aad4adb4f10","head":{"label":"zendesk:jonmoter/k8s-service-creation","ref":"jonmoter/k8s-service-creation","sha":"db90027911d2e54ff5cc3650e6953aad4adb4f10","user":{"login":"zendesk","id":11525,"avatar_url":"https://avatars.githubusercontent.com/u/11525?v=3","gravatar_id":"","url":"https://api.github.com/users/zendesk","html_url":"https://github.com/zendesk","followers_url":"https://api.github.com/users/zendesk/followers","following_url":"https://api.github.com/users/zendesk/following{/other_user}","gists_url":"https://api.github.com/users/zendesk/gists{/gist_id}","starred_url":"https://api.github.com/users/zendesk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zendesk/subscriptions","organizations_url":"https://api.github.com/users/zendesk/orgs","repos_url":"https://api.github.com/users/zendesk/repos","events_url":"https://api.github.com/users/zendesk/events{/privacy}","received_events_url":"https://api.github.com/users/zendesk/received_events","type":"Organization","site_admin":false},"repo":{"id":20208662,"name":"samson","full_name":"zendesk/samson","owner":{"login":"zendesk","id":11525,"avatar_url":"https://avatars.githubusercontent.com/u/11525?v=3","gravatar_id":"","url":"https://api.github.com/users/zendesk","html_url":"https://github.com/zendesk","followers_url":"https://api.github.com/users/zendesk/followers","following_url":"https://api.github.com/users/zendesk/following{/other_user}","gists_url":"https://api.github.com/users/zendesk/gists{/gist_id}","starred_url":"https://api.github.com/users/zendesk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zendesk/subscriptions","organizations_url":"https://api.github.com/users/zendesk/orgs","repos_url":"https://api.github.com/users/zendesk/repos","events_url":"https://api.github.com/users/zendesk/events{/privacy}","received_events_url":"https://api.github.com/users/zendesk/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/zendesk/samson","description":"Web interface for deployments","fork":false,"url":"https://api.github.com/repos/zendesk/samson","forks_url":"https://api.github.com/repos/zendesk/samson/forks","keys_url":"https://api.github.com/repos/zendesk/samson/keys{/key_id}","collaborators_url":"https://api.github.com/repos/zendesk/samson/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/zendesk/samson/teams","hooks_url":"https://api.github.com/repos/zendesk/samson/hooks","issue_events_url":"https://api.github.com/repos/zendesk/samson/issues/events{/number}","events_url":"https://api.github.com/repos/zendesk/samson/events","assignees_url":"https://api.github.com/repos/zendesk/samson/assignees{/user}","branches_url":"https://api.github.com/repos/zendesk/samson/branches{/branch}","tags_url":"https://api.github.com/repos/zendesk/samson/tags","blobs_url":"https://api.github.com/repos/zendesk/samson/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/zendesk/samson/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/zendesk/samson/git/refs{/sha}","trees_url":"https://api.github.com/repos/zendesk/samson/git/trees{/sha}","statuses_url":"https://api.github.com/repos/zendesk/samson/statuses/{sha}","languages_url":"https://api.github.com/repos/zendesk/samson/languages","stargazers_url":"https://api.github.com/repos/zendesk/samson/stargazers","contributors_url":"https://api.github.com/repos/zendesk/samson/contributors","subscribers_url":"https://api.github.com/repos/zendesk/samson/subscribers","subscription_url":"https://api.github.com/repos/zendesk/samson/subscription","commits_url":"https://api.github.com/repos/zendesk/samson/commits{/sha}","git_commits_url":"https://api.github.com/repos/zendesk/samson/git/commits{/sha}","comments_url":"https://api.github.com/repos/zendesk/samson/comments{/number}","issue_comment_url":"https://api.github.com/repos/zendesk/samson/issues/comments{/number}","contents_url":"https://api.github.com/repos/zendesk/samson/contents/{+path}","compare_url":"https://api.github.com/repos/zendesk/samson/compare/{base}...{head}","merges_url":"https://api.github.com/repos/zendesk/samson/merges","archive_url":"https://api.github.com/repos/zendesk/samson/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/zendesk/samson/downloads","issues_url":"https://api.github.com/repos/zendesk/samson/issues{/number}","pulls_url":"https://api.github.com/repos/zendesk/samson/pulls{/number}","milestones_url":"https://api.github.com/repos/zendesk/samson/milestones{/number}","notifications_url":"https://api.github.com/repos/zendesk/samson/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/zendesk/samson/labels{/name}","releases_url":"https://api.github.com/repos/zendesk/samson/releases{/id}","created_at":"2014-05-27T05:55:57Z","updated_at":"2015-10-22T06:26:09Z","pushed_at":"2015-10-22T14:23:59Z","git_url":"git://github.com/zendesk/samson.git","ssh_url":"git@github.com:zendesk/samson.git","clone_url":"https://github.com/zendesk/samson.git","svn_url":"https://github.com/zendesk/samson","homepage":null,"size":115079,"stargazers_count":515,"watchers_count":515,"language":"Ruby","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":79,"mirror_url":null,"open_issues_count":40,"forks":79,"open_issues":40,"watchers":515,"default_branch":"master"}},"base":{"label":"zendesk:master","ref":"master","sha":"243aa43ea473d8a1734505cbf4fe69029cfe0663","user":{"login":"zendesk","id":11525,"avatar_url":"https://avatars.githubusercontent.com/u/11525?v=3","gravatar_id":"","url":"https://api.github.com/users/zendesk","html_url":"https://github.com/zendesk","followers_url":"https://api.github.com/users/zendesk/followers","following_url":"https://api.github.com/users/zendesk/following{/other_user}","gists_url":"https://api.github.com/users/zendesk/gists{/gist_id}","starred_url":"https://api.github.com/users/zendesk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zendesk/subscriptions","organizations_url":"https://api.github.com/users/zendesk/orgs","repos_url":"https://api.github.com/users/zendesk/repos","events_url":"https://api.github.com/users/zendesk/events{/privacy}","received_events_url":"https://api.github.com/users/zendesk/received_events","type":"Organization","site_admin":false},"repo":{"id":20208662,"name":"samson","full_name":"zendesk/samson","owner":{"login":"zendesk","id":11525,"avatar_url":"https://avatars.githubusercontent.com/u/11525?v=3","gravatar_id":"","url":"https://api.github.com/users/zendesk","html_url":"https://github.com/zendesk","followers_url":"https://api.github.com/users/zendesk/followers","following_url":"https://api.github.com/users/zendesk/following{/other_user}","gists_url":"https://api.github.com/users/zendesk/gists{/gist_id}","starred_url":"https://api.github.com/users/zendesk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zendesk/subscriptions","organizations_url":"https://api.github.com/users/zendesk/orgs","repos_url":"https://api.github.com/users/zendesk/repos","events_url":"https://api.github.com/users/zendesk/events{/privacy}","received_events_url":"https://api.github.com/users/zendesk/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/zendesk/samson","description":"Web interface for deployments","fork":false,"url":"https://api.github.com/repos/zendesk/samson","forks_url":"https://api.github.com/repos/zendesk/samson/forks","keys_url":"https://api.github.com/repos/zendesk/samson/keys{/key_id}","collaborators_url":"https://api.github.com/repos/zendesk/samson/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/zendesk/samson/teams","hooks_url":"https://api.github.com/repos/zendesk/samson/hooks","issue_events_url":"https://api.github.com/repos/zendesk/samson/issues/events{/number}","events_url":"https://api.github.com/repos/zendesk/samson/events","assignees_url":"https://api.github.com/repos/zendesk/samson/assignees{/user}","branches_url":"https://api.github.com/repos/zendesk/samson/branches{/branch}","tags_url":"https://api.github.com/repos/zendesk/samson/tags","blobs_url":"https://api.github.com/repos/zendesk/samson/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/zendesk/samson/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/zendesk/samson/git/refs{/sha}","trees_url":"https://api.github.com/repos/zendesk/samson/git/trees{/sha}","statuses_url":"https://api.github.com/repos/zendesk/samson/statuses/{sha}","languages_url":"https://api.github.com/repos/zendesk/samson/languages","stargazers_url":"https://api.github.com/repos/zendesk/samson/stargazers","contributors_url":"https://api.github.com/repos/zendesk/samson/contributors","subscribers_url":"https://api.github.com/repos/zendesk/samson/subscribers","subscription_url":"https://api.github.com/repos/zendesk/samson/subscription","commits_url":"https://api.github.com/repos/zendesk/samson/commits{/sha}","git_commits_url":"https://api.github.com/repos/zendesk/samson/git/commits{/sha}","comments_url":"https://api.github.com/repos/zendesk/samson/comments{/number}","issue_comment_url":"https://api.github.com/repos/zendesk/samson/issues/comments{/number}","contents_url":"https://api.github.com/repos/zendesk/samson/contents/{+path}","compare_url":"https://api.github.com/repos/zendesk/samson/compare/{base}...{head}","merges_url":"https://api.github.com/repos/zendesk/samson/merges","archive_url":"https://api.github.com/repos/zendesk/samson/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/zendesk/samson/downloads","issues_url":"https://api.github.com/repos/zendesk/samson/issues{/number}","pulls_url":"https://api.github.com/repos/zendesk/samson/pulls{/number}","milestones_url":"https://api.github.com/repos/zendesk/samson/milestones{/number}","notifications_url":"https://api.github.com/repos/zendesk/samson/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/zendesk/samson/labels{/name}","releases_url":"https://api.github.com/repos/zendesk/samson/releases{/id}","created_at":"2014-05-27T05:55:57Z","updated_at":"2015-10-22T06:26:09Z","pushed_at":"2015-10-22T14:23:59Z","git_url":"git://github.com/zendesk/samson.git","ssh_url":"git@github.com:zendesk/samson.git","clone_url":"https://github.com/zendesk/samson.git","svn_url":"https://github.com/zendesk/samson","homepage":null,"size":115079,"stargazers_count":515,"watchers_count":515,"language":"Ruby","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":79,"mirror_url":null,"open_issues_count":40,"forks":79,"open_issues":40,"watchers":515,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/zendesk/samson/pulls/605"},"html":{"href":"https://github.com/zendesk/samson/pull/605"},"issue":{"href":"https://api.github.com/repos/zendesk/samson/issues/605"},"comments":{"href":"https://api.github.com/repos/zendesk/samson/issues/605/comments"},"review_comments":{"href":"https://api.github.com/repos/zendesk/samson/pulls/605/comments"},"review_comment":{"href":"https://api.github.com/repos/zendesk/samson/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/zendesk/samson/pulls/605/commits"},"statuses":{"href":"https://api.github.com/repos/zendesk/samson/statuses/db90027911d2e54ff5cc3650e6953aad4adb4f10"}}}}