{"action":"created","comment":{"url":"https://api.github.com/repos/cyberark/conjur/pulls/comments/216498092","pull_request_review_id":153993557,"id":216498092,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIxNjQ5ODA5Mg==","diff_hunk":"@@ -1,133 +1,214 @@\n+require 'uri'\n require 'websocket'\n require 'rubygems/package'\n \n+require 'active_support/time'\n+require 'websocket-client-simple'\n+\n+module WebSocket\n+  module Client\n+    module Simple\n+      class Client\n+        alias_method :send_msg, :send\n+      end\n+    end\n+  end\n+end\n+\n module Authentication\n   module AuthnK8s\n-    class KubectlExec\n-      STDIN_CHANNEL = 0\n-      STDOUT_CHANNEL = 1\n-      STDERR_CHANNEL = 2\n-      ERROR_CHANNEL = 3\n-      RESIZE_CHANNEL = 4\n+    CommandTimedOut = ::Util::ErrorClass.new(\n+      \"Command timed out in container '{0}' of pod '{1}'\"\n+    )\n+\n+    class Messages\n+      attr_reader :messages\n+      \n+      def initialize\n+        @messages = Hash.new { |hash,key| hash[key] = [] }\n+      end\n+\n+      def save_message(msg)\n+        strm ||= stream_name(msg)\n+        raise \"Unexpected channel: #{channel(msg)}\" unless strm\n+        @messages[strm.to_sym] << msg_data(msg)\n+      end\n \n-      attr_reader :pod, :container, :timeout, :ws\n+      def save_string(str, stream: nil)\n+        @messages[stream] << str\n+      end\n+\n+      def stream_name(msg)\n+        stream_names[channel_from_message(msg)]\n+      end\n \n-      def initialize pod, container: \"authentication\", timeout: 5.seconds\n-        @pod = pod\n+      def msg_data(msg)\n+        msg.data[1..-1]\n+      end\n+\n+      def channel(stream_name)\n+        stream_names.index(stream_name)\n+      end\n+\n+      private\n+\n+      def channel_from_message(msg)\n+        return channel('error') unless msg.respond_to?(:data)\n+        msg.data[0..0].bytes.first\n+      end\n+\n+      def stream_names\n+        %w[stdin stdout stderr error resize]\n+      end\n+    end\n+\n+    class StreamState\n+      def initialize\n+        @closed = false\n+      end\n+\n+      def close\n+        @closed = true\n+      end\n+\n+      def closed?\n+        @closed\n+      end\n+    end\n+    \n+    class KubectlExec\n+      # logger: an object responding to `debug`\n+      # kubeclient: Kubeclient::Client from \"kubeclient\" gem\n+      #\n+      def initialize(\n+        pod_name:,\n+        pod_namespace:,\n+        logger:,\n+        kubeclient:,\n+        container: 'authentication',\n+        timeout: 5.seconds\n+      )\n+        @pod_name = pod_name\n+        @pod_namespace = pod_namespace\n         @container = container\n         @timeout = timeout\n+        @logger = logger\n+        @kubeclient = kubeclient\n+\n+        @messages = Messages.new\n+        @stream_state = StreamState.new\n       end\n \n-      def exec command, body: \"\", stdin: false\n-        kubectl = K8sObjectLookup.kubectl_client\n+      def execute(cmds, body: \"\", stdin: false)\n+        url = server_url(cmds, stdin)\n+        headers = @kubeclient.headers.clone\n+        ws = WebSocket::Client::Simple.connect(url, headers: headers)\n \n-        base_url = \"wss://#{kubectl.api_endpoint.host}:#{kubectl.api_endpoint.port}\"\n-        path = \"/api/v1/namespaces/#{pod.metadata.namespace}/pods/#{pod.metadata.name}/exec\"\n+        add_websocket_event_handlers(ws, body, stdin)\n \n-        query = [\n-          \"container=#{CGI.escape container}\",\n-          \"stderr=true\",\n-          \"stdout=true\",\n-        ]\n-        query << \"stdin=true\" if stdin\n+        wait_for_close_message(ws)\n \n-        for arg in Array(command)\n-          query << \"command=#{CGI.escape arg}\"\n-        end\n-        query = query.join(\"&\")\n-\n-        url = \"#{base_url}#{path}?#{query}\"\n-        headers = kubectl.headers.clone\n-\n-        ws = @ws = WebSocket::Client::Simple.connect url, headers: headers\n-        ws.instance_variable_set \"@messages\", Hash.new {|hash,key| hash[key] = []}\n-        ws.instance_variable_set \"@pod\", pod\n-        ws.instance_variable_set \"@closed\", false\n-\n-        class << ws\n-          def message_binary msg\n-            channel = msg.data[0..0].bytes.first\n-            stream = case channel\n-                     when STDOUT_CHANNEL\n-                       \"stdout\"\n-                     when STDERR_CHANNEL\n-                       \"stderr\"\n-                     when ERROR_CHANNEL\n-                       \"error\"\n-                     when RESIZE_CHANNEL\n-                       \"resize\"\n-                     else\n-                       raise \"Unexpected channel number : #{channel}\"\n-                     end\n-            @messages[stream.to_sym] << msg.data[1..-1]\n-            Rails.logger.debug \"Pod #{@pod.metadata.name.inspect} message :#{stream} : #{msg.data[1..-1]}\"\n-          end\n+        raise CommandTimedOut.new(@container, @pod_name) unless @stream_state.closed?\n+        \n+        # TODO: raise an `WebsocketServerFailure` here in the case of ws :error\n+\n+        @messages.messages\n+      end\n+      \n+      def copy(path, content, mode)\n+        execute(\n+          [ 'tar', 'xvf', '-', '-C', '/' ],\n+          stdin: true,\n+          body: generate_file_tar_string(path, content, mode)\n+        )\n+      end\n \n-          def message_close msg\n-            Rails.logger.debug \"Pod #{@pod.metadata.name.inspect} message :#{close} : #{msg.data[1..-1]}\"\n+      private\n+\n+      def add_websocket_event_handlers(ws, body, stdin)\n+        # These callbacks have access to local variables, but we can't use the\n+        # instance variables because 'self' is not KubectlExec. Make some local\n+        # vars to pass the instance variables in.\n+        pod_name = @pod_name\n+        logger = @logger\n+        messages = @messages\n+        stream_state = @stream_state\n+        \n+        ws.on(:message) do |msg|\n+          if msg.type == :binary\n+            messages.save_message(msg)\n+            logger.debug(\"Pod #{pod_name}, stream #{messages.stream_name(msg)}: #{messages.msg_data(msg)}\")\n+          elsif msg.type == :close\n+            logger.debug(\"Pod: #{pod_name}, message: close, data: #{messages.msg_data(msg)}\")\n             close\n           end\n         end\n \n-        ws.on :message do |msg|\n-          __send__ \"message_#{msg.type}\", msg\n-        end\n-\n         ws.on :open do\n           hs = ws.handshake\n+\n           if hs.error\n-            emit :error, hs.instance_variable_get(\"@data\")\n+            emit(:error, messages.messages)\n           else\n-            Rails.logger.debug \"Pod #{@pod.metadata.name.inspect} : channel open\"\n+            logger.debug(\"Pod #{pod_name} : channel open\")\n \n             if stdin\n-              ws.send(STDIN_CHANNEL.chr + body)\n-              ws.send nil, :type => :close\n+              data = messages.channel('stdin').chr + body\n+              ws.send_msg(data)\n+              ws.send_msg(nil, type: :close)\n             end\n           end\n         end\n \n-        ws.on :close do |e|\n-          @closed = true\n-          Rails.logger.debug \"Pod #{@pod.metadata.name.inspect} : channel closed\"\n+        ws.on(:close) do |e|\n+          stream_state.close\n+          logger.debug(\"Pod #{pod_name} : channel closed\")\n         end\n \n-        ws.on :error do |e|\n-          @closed = true\n-          Rails.logger.debug \"Pod #{@pod.metadata.name.inspect} error : #{e.inspect}\"\n-          @messages[:error] << e.inspect\n+        ws.on(:error) do |e|\n+          stream_state.close\n+          logger.debug(\"Pod #{pod_name} error : #{e.inspect}\")\n+          \n+          messages.save_string(e.inspect, stream: :error)\n         end\n+      end\n \n-        ws.send \"\\n\"\n-\n+      def wait_for_close_message(ws)","path":"app/domain/authentication/authn_k8s/kubectl_exec.rb","position":245,"original_position":245,"commit_id":"306bccf330e3e1ae77b62e5600c9e8af908a3f34","original_commit_id":"306bccf330e3e1ae77b62e5600c9e8af908a3f34","user":{"login":"jonahx","id":699684,"node_id":"MDQ6VXNlcjY5OTY4NA==","avatar_url":"https://avatars3.githubusercontent.com/u/699684?v=4","gravatar_id":"","url":"https://api.github.com/users/jonahx","html_url":"https://github.com/jonahx","followers_url":"https://api.github.com/users/jonahx/followers","following_url":"https://api.github.com/users/jonahx/following{/other_user}","gists_url":"https://api.github.com/users/jonahx/gists{/gist_id}","starred_url":"https://api.github.com/users/jonahx/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jonahx/subscriptions","organizations_url":"https://api.github.com/users/jonahx/orgs","repos_url":"https://api.github.com/users/jonahx/repos","events_url":"https://api.github.com/users/jonahx/events{/privacy}","received_events_url":"https://api.github.com/users/jonahx/received_events","type":"User","site_admin":false},"body":"Can remove `ws` arg","created_at":"2018-09-10T22:45:01Z","updated_at":"2018-09-10T22:45:01Z","html_url":"https://github.com/cyberark/conjur/pull/731#discussion_r216498092","pull_request_url":"https://api.github.com/repos/cyberark/conjur/pulls/731","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/cyberark/conjur/pulls/comments/216498092"},"html":{"href":"https://github.com/cyberark/conjur/pull/731#discussion_r216498092"},"pull_request":{"href":"https://api.github.com/repos/cyberark/conjur/pulls/731"}}},"pull_request":{"url":"https://api.github.com/repos/cyberark/conjur/pulls/731","id":214426910,"node_id":"MDExOlB1bGxSZXF1ZXN0MjE0NDI2OTEw","html_url":"https://github.com/cyberark/conjur/pull/731","diff_url":"https://github.com/cyberark/conjur/pull/731.diff","patch_url":"https://github.com/cyberark/conjur/pull/731.patch","issue_url":"https://api.github.com/repos/cyberark/conjur/issues/731","number":731,"state":"open","locked":false,"title":"729  refactor kubectl exec class","user":{"login":"jtuttle","id":18331203,"node_id":"MDQ6VXNlcjE4MzMxMjAz","avatar_url":"https://avatars3.githubusercontent.com/u/18331203?v=4","gravatar_id":"","url":"https://api.github.com/users/jtuttle","html_url":"https://github.com/jtuttle","followers_url":"https://api.github.com/users/jtuttle/followers","following_url":"https://api.github.com/users/jtuttle/following{/other_user}","gists_url":"https://api.github.com/users/jtuttle/gists{/gist_id}","starred_url":"https://api.github.com/users/jtuttle/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jtuttle/subscriptions","organizations_url":"https://api.github.com/users/jtuttle/orgs","repos_url":"https://api.github.com/users/jtuttle/repos","events_url":"https://api.github.com/users/jtuttle/events{/privacy}","received_events_url":"https://api.github.com/users/jtuttle/received_events","type":"User","site_admin":false},"body":"#### What does this PR do?\r\n\r\nRefactors the kubectl_exec class in isolation before the full refactor merge.\r\n\r\n#### What ticket does this PR close?\r\n\r\nCloses #729 \r\n\r\n#### How should this be manually tested?\r\n\r\nCukes should suffice\r\n\r\n#### Link to build in Jenkins (if appropriate)\r\n\r\nhttps://jenkins.conjur.net/blue/organizations/jenkins/cyberark--conjur/activity?branch=729--refactor-kubectl-exec-class\r\n\r\n#### Has the Version and Changelog been updated?\r\n\r\nNot yet.","created_at":"2018-09-10T20:01:06Z","updated_at":"2018-09-10T22:45:01Z","closed_at":null,"merged_at":null,"merge_commit_sha":"e16e79869dbe23a0dbf5151ae09dbec8545b8069","assignee":{"login":"jtuttle","id":18331203,"node_id":"MDQ6VXNlcjE4MzMxMjAz","avatar_url":"https://avatars3.githubusercontent.com/u/18331203?v=4","gravatar_id":"","url":"https://api.github.com/users/jtuttle","html_url":"https://github.com/jtuttle","followers_url":"https://api.github.com/users/jtuttle/followers","following_url":"https://api.github.com/users/jtuttle/following{/other_user}","gists_url":"https://api.github.com/users/jtuttle/gists{/gist_id}","starred_url":"https://api.github.com/users/jtuttle/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jtuttle/subscriptions","organizations_url":"https://api.github.com/users/jtuttle/orgs","repos_url":"https://api.github.com/users/jtuttle/repos","events_url":"https://api.github.com/users/jtuttle/events{/privacy}","received_events_url":"https://api.github.com/users/jtuttle/received_events","type":"User","site_admin":false},"assignees":[{"login":"jtuttle","id":18331203,"node_id":"MDQ6VXNlcjE4MzMxMjAz","avatar_url":"https://avatars3.githubusercontent.com/u/18331203?v=4","gravatar_id":"","url":"https://api.github.com/users/jtuttle","html_url":"https://github.com/jtuttle","followers_url":"https://api.github.com/users/jtuttle/followers","following_url":"https://api.github.com/users/jtuttle/following{/other_user}","gists_url":"https://api.github.com/users/jtuttle/gists{/gist_id}","starred_url":"https://api.github.com/users/jtuttle/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jtuttle/subscriptions","organizations_url":"https://api.github.com/users/jtuttle/orgs","repos_url":"https://api.github.com/users/jtuttle/repos","events_url":"https://api.github.com/users/jtuttle/events{/privacy}","received_events_url":"https://api.github.com/users/jtuttle/received_events","type":"User","site_admin":false}],"requested_reviewers":[],"requested_teams":[],"labels":[{"id":631459098,"node_id":"MDU6TGFiZWw2MzE0NTkwOTg=","url":"https://api.github.com/repos/cyberark/conjur/labels/in%20progress","name":"in progress","color":"ededed","default":false},{"id":999180579,"node_id":"MDU6TGFiZWw5OTkxODA1Nzk=","url":"https://api.github.com/repos/cyberark/conjur/labels/review","name":"review","color":"ededed","default":false}],"milestone":null,"commits_url":"https://api.github.com/repos/cyberark/conjur/pulls/731/commits","review_comments_url":"https://api.github.com/repos/cyberark/conjur/pulls/731/comments","review_comment_url":"https://api.github.com/repos/cyberark/conjur/pulls/comments{/number}","comments_url":"https://api.github.com/repos/cyberark/conjur/issues/731/comments","statuses_url":"https://api.github.com/repos/cyberark/conjur/statuses/306bccf330e3e1ae77b62e5600c9e8af908a3f34","head":{"label":"cyberark:729--refactor-kubectl-exec-class","ref":"729--refactor-kubectl-exec-class","sha":"306bccf330e3e1ae77b62e5600c9e8af908a3f34","user":{"login":"cyberark","id":30869256,"node_id":"MDEyOk9yZ2FuaXphdGlvbjMwODY5MjU2","avatar_url":"https://avatars3.githubusercontent.com/u/30869256?v=4","gravatar_id":"","url":"https://api.github.com/users/cyberark","html_url":"https://github.com/cyberark","followers_url":"https://api.github.com/users/cyberark/followers","following_url":"https://api.github.com/users/cyberark/following{/other_user}","gists_url":"https://api.github.com/users/cyberark/gists{/gist_id}","starred_url":"https://api.github.com/users/cyberark/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cyberark/subscriptions","organizations_url":"https://api.github.com/users/cyberark/orgs","repos_url":"https://api.github.com/users/cyberark/repos","events_url":"https://api.github.com/users/cyberark/events{/privacy}","received_events_url":"https://api.github.com/users/cyberark/received_events","type":"Organization","site_admin":false},"repo":{"id":62174977,"node_id":"MDEwOlJlcG9zaXRvcnk2MjE3NDk3Nw==","name":"conjur","full_name":"cyberark/conjur","owner":{"login":"cyberark","id":30869256,"node_id":"MDEyOk9yZ2FuaXphdGlvbjMwODY5MjU2","avatar_url":"https://avatars3.githubusercontent.com/u/30869256?v=4","gravatar_id":"","url":"https://api.github.com/users/cyberark","html_url":"https://github.com/cyberark","followers_url":"https://api.github.com/users/cyberark/followers","following_url":"https://api.github.com/users/cyberark/following{/other_user}","gists_url":"https://api.github.com/users/cyberark/gists{/gist_id}","starred_url":"https://api.github.com/users/cyberark/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cyberark/subscriptions","organizations_url":"https://api.github.com/users/cyberark/orgs","repos_url":"https://api.github.com/users/cyberark/repos","events_url":"https://api.github.com/users/cyberark/events{/privacy}","received_events_url":"https://api.github.com/users/cyberark/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/cyberark/conjur","description":"CyberArk Conjur automatically secures secrets used by privileged users and machine identities","fork":false,"url":"https://api.github.com/repos/cyberark/conjur","forks_url":"https://api.github.com/repos/cyberark/conjur/forks","keys_url":"https://api.github.com/repos/cyberark/conjur/keys{/key_id}","collaborators_url":"https://api.github.com/repos/cyberark/conjur/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/cyberark/conjur/teams","hooks_url":"https://api.github.com/repos/cyberark/conjur/hooks","issue_events_url":"https://api.github.com/repos/cyberark/conjur/issues/events{/number}","events_url":"https://api.github.com/repos/cyberark/conjur/events","assignees_url":"https://api.github.com/repos/cyberark/conjur/assignees{/user}","branches_url":"https://api.github.com/repos/cyberark/conjur/branches{/branch}","tags_url":"https://api.github.com/repos/cyberark/conjur/tags","blobs_url":"https://api.github.com/repos/cyberark/conjur/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/cyberark/conjur/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/cyberark/conjur/git/refs{/sha}","trees_url":"https://api.github.com/repos/cyberark/conjur/git/trees{/sha}","statuses_url":"https://api.github.com/repos/cyberark/conjur/statuses/{sha}","languages_url":"https://api.github.com/repos/cyberark/conjur/languages","stargazers_url":"https://api.github.com/repos/cyberark/conjur/stargazers","contributors_url":"https://api.github.com/repos/cyberark/conjur/contributors","subscribers_url":"https://api.github.com/repos/cyberark/conjur/subscribers","subscription_url":"https://api.github.com/repos/cyberark/conjur/subscription","commits_url":"https://api.github.com/repos/cyberark/conjur/commits{/sha}","git_commits_url":"https://api.github.com/repos/cyberark/conjur/git/commits{/sha}","comments_url":"https://api.github.com/repos/cyberark/conjur/comments{/number}","issue_comment_url":"https://api.github.com/repos/cyberark/conjur/issues/comments{/number}","contents_url":"https://api.github.com/repos/cyberark/conjur/contents/{+path}","compare_url":"https://api.github.com/repos/cyberark/conjur/compare/{base}...{head}","merges_url":"https://api.github.com/repos/cyberark/conjur/merges","archive_url":"https://api.github.com/repos/cyberark/conjur/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/cyberark/conjur/downloads","issues_url":"https://api.github.com/repos/cyberark/conjur/issues{/number}","pulls_url":"https://api.github.com/repos/cyberark/conjur/pulls{/number}","milestones_url":"https://api.github.com/repos/cyberark/conjur/milestones{/number}","notifications_url":"https://api.github.com/repos/cyberark/conjur/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/cyberark/conjur/labels{/name}","releases_url":"https://api.github.com/repos/cyberark/conjur/releases{/id}","deployments_url":"https://api.github.com/repos/cyberark/conjur/deployments","created_at":"2016-06-28T21:18:07Z","updated_at":"2018-09-10T14:43:33Z","pushed_at":"2018-09-10T20:49:10Z","git_url":"git://github.com/cyberark/conjur.git","ssh_url":"git@github.com:cyberark/conjur.git","clone_url":"https://github.com/cyberark/conjur.git","svn_url":"https://github.com/cyberark/conjur","homepage":"https://conjur.org","size":4147,"stargazers_count":165,"watchers_count":165,"language":"Ruby","has_issues":true,"has_projects":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":34,"mirror_url":null,"archived":false,"open_issues_count":84,"license":{"key":"lgpl-3.0","name":"GNU Lesser General Public License v3.0","spdx_id":"LGPL-3.0","url":"https://api.github.com/licenses/lgpl-3.0","node_id":"MDc6TGljZW5zZTEy"},"forks":34,"open_issues":84,"watchers":165,"default_branch":"master"}},"base":{"label":"cyberark:master","ref":"master","sha":"ce68cf7b59792e6069e7d5ce6d96537de384f427","user":{"login":"cyberark","id":30869256,"node_id":"MDEyOk9yZ2FuaXphdGlvbjMwODY5MjU2","avatar_url":"https://avatars3.githubusercontent.com/u/30869256?v=4","gravatar_id":"","url":"https://api.github.com/users/cyberark","html_url":"https://github.com/cyberark","followers_url":"https://api.github.com/users/cyberark/followers","following_url":"https://api.github.com/users/cyberark/following{/other_user}","gists_url":"https://api.github.com/users/cyberark/gists{/gist_id}","starred_url":"https://api.github.com/users/cyberark/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cyberark/subscriptions","organizations_url":"https://api.github.com/users/cyberark/orgs","repos_url":"https://api.github.com/users/cyberark/repos","events_url":"https://api.github.com/users/cyberark/events{/privacy}","received_events_url":"https://api.github.com/users/cyberark/received_events","type":"Organization","site_admin":false},"repo":{"id":62174977,"node_id":"MDEwOlJlcG9zaXRvcnk2MjE3NDk3Nw==","name":"conjur","full_name":"cyberark/conjur","owner":{"login":"cyberark","id":30869256,"node_id":"MDEyOk9yZ2FuaXphdGlvbjMwODY5MjU2","avatar_url":"https://avatars3.githubusercontent.com/u/30869256?v=4","gravatar_id":"","url":"https://api.github.com/users/cyberark","html_url":"https://github.com/cyberark","followers_url":"https://api.github.com/users/cyberark/followers","following_url":"https://api.github.com/users/cyberark/following{/other_user}","gists_url":"https://api.github.com/users/cyberark/gists{/gist_id}","starred_url":"https://api.github.com/users/cyberark/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cyberark/subscriptions","organizations_url":"https://api.github.com/users/cyberark/orgs","repos_url":"https://api.github.com/users/cyberark/repos","events_url":"https://api.github.com/users/cyberark/events{/privacy}","received_events_url":"https://api.github.com/users/cyberark/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/cyberark/conjur","description":"CyberArk Conjur automatically secures secrets used by privileged users and machine identities","fork":false,"url":"https://api.github.com/repos/cyberark/conjur","forks_url":"https://api.github.com/repos/cyberark/conjur/forks","keys_url":"https://api.github.com/repos/cyberark/conjur/keys{/key_id}","collaborators_url":"https://api.github.com/repos/cyberark/conjur/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/cyberark/conjur/teams","hooks_url":"https://api.github.com/repos/cyberark/conjur/hooks","issue_events_url":"https://api.github.com/repos/cyberark/conjur/issues/events{/number}","events_url":"https://api.github.com/repos/cyberark/conjur/events","assignees_url":"https://api.github.com/repos/cyberark/conjur/assignees{/user}","branches_url":"https://api.github.com/repos/cyberark/conjur/branches{/branch}","tags_url":"https://api.github.com/repos/cyberark/conjur/tags","blobs_url":"https://api.github.com/repos/cyberark/conjur/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/cyberark/conjur/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/cyberark/conjur/git/refs{/sha}","trees_url":"https://api.github.com/repos/cyberark/conjur/git/trees{/sha}","statuses_url":"https://api.github.com/repos/cyberark/conjur/statuses/{sha}","languages_url":"https://api.github.com/repos/cyberark/conjur/languages","stargazers_url":"https://api.github.com/repos/cyberark/conjur/stargazers","contributors_url":"https://api.github.com/repos/cyberark/conjur/contributors","subscribers_url":"https://api.github.com/repos/cyberark/conjur/subscribers","subscription_url":"https://api.github.com/repos/cyberark/conjur/subscription","commits_url":"https://api.github.com/repos/cyberark/conjur/commits{/sha}","git_commits_url":"https://api.github.com/repos/cyberark/conjur/git/commits{/sha}","comments_url":"https://api.github.com/repos/cyberark/conjur/comments{/number}","issue_comment_url":"https://api.github.com/repos/cyberark/conjur/issues/comments{/number}","contents_url":"https://api.github.com/repos/cyberark/conjur/contents/{+path}","compare_url":"https://api.github.com/repos/cyberark/conjur/compare/{base}...{head}","merges_url":"https://api.github.com/repos/cyberark/conjur/merges","archive_url":"https://api.github.com/repos/cyberark/conjur/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/cyberark/conjur/downloads","issues_url":"https://api.github.com/repos/cyberark/conjur/issues{/number}","pulls_url":"https://api.github.com/repos/cyberark/conjur/pulls{/number}","milestones_url":"https://api.github.com/repos/cyberark/conjur/milestones{/number}","notifications_url":"https://api.github.com/repos/cyberark/conjur/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/cyberark/conjur/labels{/name}","releases_url":"https://api.github.com/repos/cyberark/conjur/releases{/id}","deployments_url":"https://api.github.com/repos/cyberark/conjur/deployments","created_at":"2016-06-28T21:18:07Z","updated_at":"2018-09-10T14:43:33Z","pushed_at":"2018-09-10T20:49:10Z","git_url":"git://github.com/cyberark/conjur.git","ssh_url":"git@github.com:cyberark/conjur.git","clone_url":"https://github.com/cyberark/conjur.git","svn_url":"https://github.com/cyberark/conjur","homepage":"https://conjur.org","size":4147,"stargazers_count":165,"watchers_count":165,"language":"Ruby","has_issues":true,"has_projects":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":34,"mirror_url":null,"archived":false,"open_issues_count":84,"license":{"key":"lgpl-3.0","name":"GNU Lesser General Public License v3.0","spdx_id":"LGPL-3.0","url":"https://api.github.com/licenses/lgpl-3.0","node_id":"MDc6TGljZW5zZTEy"},"forks":34,"open_issues":84,"watchers":165,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/cyberark/conjur/pulls/731"},"html":{"href":"https://github.com/cyberark/conjur/pull/731"},"issue":{"href":"https://api.github.com/repos/cyberark/conjur/issues/731"},"comments":{"href":"https://api.github.com/repos/cyberark/conjur/issues/731/comments"},"review_comments":{"href":"https://api.github.com/repos/cyberark/conjur/pulls/731/comments"},"review_comment":{"href":"https://api.github.com/repos/cyberark/conjur/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/cyberark/conjur/pulls/731/commits"},"statuses":{"href":"https://api.github.com/repos/cyberark/conjur/statuses/306bccf330e3e1ae77b62e5600c9e8af908a3f34"}},"author_association":"MEMBER"}}
{"actor":{"display_login":"jonahx"}}