{"action":"created","comment":{"url":"https://api.github.com/repos/aws/amazon-ecs-agent/pulls/comments/27155593","id":27155593,"diff_hunk":"@@ -0,0 +1,326 @@\n+// Copyright 2014-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.\n+//\n+// Licensed under the Apache License, Version 2.0 (the \"License\"). You may\n+// not use this file except in compliance with the License. A copy of the\n+// License is located at\n+//\n+//\thttp://aws.amazon.com/apache2.0/\n+//\n+// or in the \"license\" file accompanying this file. This file is distributed\n+// on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either\n+// express or implied. See the License for the specific language governing\n+// permissions and limitations under the License.\n+\n+// Package acsclient wraps the generated aws-sdk-go client to provide marshalling\n+// and unmarshalling of data over a websocket connection in the format expected\n+// by ACS. It allows for bidirectional communication and acts as both a\n+// client-and-server in terms of requests, but only as a client in terms of\n+// connecting.\n+package acsclient\n+\n+import (\n+\t\"bytes\"\n+\t\"crypto/tls\"\n+\t\"encoding/json\"\n+\t\"errors\"\n+\t\"io\"\n+\t\"io/ioutil\"\n+\t\"net\"\n+\t\"net/http\"\n+\t\"net/url\"\n+\t\"reflect\"\n+\t\"strings\"\n+\t\"time\"\n+\n+\t\"github.com/aws/amazon-ecs-agent/agent/ecs_client/authv4\"\n+\t\"github.com/aws/amazon-ecs-agent/agent/ecs_client/authv4/credentials\"\n+\t\"github.com/aws/amazon-ecs-agent/agent/logger\"\n+\t\"github.com/awslabs/aws-sdk-go/internal/protocol/json/jsonutil\"\n+\t\"github.com/gorilla/websocket\"\n+)\n+\n+var log = logger.ForModule(\"acs client\")\n+\n+const acsService = \"ecs\"\n+const acsConnectTimeout = 3 * time.Second\n+\n+// websocketConn specifies the subset of gorilla/websocket's\n+// connection's methods that this client uses.\n+type websocketConn interface {\n+\tWriteMessage(messageType int, data []byte) error\n+\tReadMessage() (messageType int, data []byte, err error)\n+\tClose() error\n+}\n+\n+// More properly this would be func(*ecsacs.T for T in ecsacs.*), but it needs\n+// to be interface{} to properly capture that\n+type requestHandler interface{}\n+\n+// ClientServer is a combined client and server for the ACS websocket connection\n+type ClientServer interface {\n+\tAddRequestHandler(requestHandler)\n+\tMakeRequest(input interface{}) error\n+\tConnect() error\n+\tServe() error\n+\tio.Closer\n+}\n+\n+// default implementation of ClientServer\n+type clientServer struct {\n+\t// url is the full url to ACS, including path, querystring, and so on.\n+\turl                string\n+\tregion             string\n+\tcredentialProvider credentials.AWSCredentialProvider\n+\tacceptInvalidCert  bool\n+\n+\tconn websocketConn\n+\n+\t// requestHandlers is a map from message types to handler functions of the\n+\t// form:\n+\t//     \"FooMessage\": func(message *ecsacs.FooMessage)\n+\trequestHandlers map[string]requestHandler\n+}\n+\n+// receivedMessage is the intermediate message used to unmarshal a message from ACS\n+type receivedMessage struct {\n+\tType    string          `json:\"type\"`\n+\tMessage json.RawMessage `json:\"message\"`\n+}\n+\n+// requestMessage is the intermediate message marshalled to send to ACS.\n+type requestMessage struct {\n+\tType    string          `json:\"type\"`\n+\tMessage json.RawMessage `json:\"message\"`\n+}\n+\n+// New returns a client/server to bidirectionally communicate with ACS\n+// The returned struct should have both 'Connect' and 'Serve' called upon it\n+// before being used.\n+func New(url string, region string, credentialProvider credentials.AWSCredentialProvider, acceptInvalidCert bool) ClientServer {\n+\tcs := &clientServer{url: url, region: region, credentialProvider: credentialProvider, acceptInvalidCert: acceptInvalidCert}\n+\tcs.requestHandlers = make(map[string]requestHandler)\n+\treturn cs\n+}\n+\n+// Connect opens a connection to ACS and upgrades it to a websocket. Calls to\n+// 'MakeRequest' can be made after calling this, but responss will not be\n+// receivable until 'Serve' is also called.\n+func (cs *clientServer) Connect() error {\n+\tparsedAcsURL, err := url.Parse(cs.url)\n+\tif err != nil {\n+\t\treturn err\n+\t}\n+\n+\tsigner := authv4.NewHttpSigner(cs.region, acsService, cs.credentialProvider, nil)\n+\n+\t// NewRequest never returns an error if the url parses and we just verified\n+\t// it did above\n+\trequest, _ := http.NewRequest(\"GET\", cs.url, nil)\n+\tsigner.SignHttpRequest(request)\n+\n+\t// url.Host might not have the port, but tls.Dial needs it\n+\tdialHost := parsedAcsURL.Host\n+\tif !strings.Contains(dialHost, \":\") {\n+\t\tdialHost += \":443\"\n+\t}\n+\n+\ttimeoutDialer := &net.Dialer{Timeout: acsConnectTimeout}\n+\tlog.Info(\"Creating poll dialer\", \"host\", parsedAcsURL.Host)\n+\tacsConn, err := tls.DialWithDialer(timeoutDialer, \"tcp\", dialHost, &tls.Config{InsecureSkipVerify: cs.acceptInvalidCert})\n+\tif err != nil {\n+\t\treturn err\n+\t}\n+\n+\twebsocketConn, httpResponse, err := websocket.NewClient(acsConn, parsedAcsURL, request.Header, 1024, 1024)\n+\tif httpResponse != nil {\n+\t\tdefer httpResponse.Body.Close()\n+\t}\n+\tif err != nil {\n+\t\tvar resp []byte\n+\t\tif httpResponse != nil {\n+\t\t\tresp, _ = ioutil.ReadAll(httpResponse.Body)","path":"agent/acs/client/acs_client.go","position":141,"original_position":141,"commit_id":"77de7582fa7321399f84becb76828206a7d86a06","original_commit_id":"77de7582fa7321399f84becb76828206a7d86a06","user":{"login":"samuelkarp","id":737750,"avatar_url":"https://avatars.githubusercontent.com/u/737750?v=3","gravatar_id":"","url":"https://api.github.com/users/samuelkarp","html_url":"https://github.com/samuelkarp","followers_url":"https://api.github.com/users/samuelkarp/followers","following_url":"https://api.github.com/users/samuelkarp/following{/other_user}","gists_url":"https://api.github.com/users/samuelkarp/gists{/gist_id}","starred_url":"https://api.github.com/users/samuelkarp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/samuelkarp/subscriptions","organizations_url":"https://api.github.com/users/samuelkarp/orgs","repos_url":"https://api.github.com/users/samuelkarp/repos","events_url":"https://api.github.com/users/samuelkarp/events{/privacy}","received_events_url":"https://api.github.com/users/samuelkarp/received_events","type":"User","site_admin":false},"body":"I'd prefer it being handled to make it more obvious for a future maintainer.","created_at":"2015-03-25T19:13:54Z","updated_at":"2015-03-25T19:13:54Z","html_url":"https://github.com/aws/amazon-ecs-agent/pull/35#discussion_r27155593","pull_request_url":"https://api.github.com/repos/aws/amazon-ecs-agent/pulls/35","_links":{"self":{"href":"https://api.github.com/repos/aws/amazon-ecs-agent/pulls/comments/27155593"},"html":{"href":"https://github.com/aws/amazon-ecs-agent/pull/35#discussion_r27155593"},"pull_request":{"href":"https://api.github.com/repos/aws/amazon-ecs-agent/pulls/35"}}},"pull_request":{"url":"https://api.github.com/repos/aws/amazon-ecs-agent/pulls/35","id":31870292,"html_url":"https://github.com/aws/amazon-ecs-agent/pull/35","diff_url":"https://github.com/aws/amazon-ecs-agent/pull/35.diff","patch_url":"https://github.com/aws/amazon-ecs-agent/pull/35.patch","issue_url":"https://api.github.com/repos/aws/amazon-ecs-agent/issues/35","number":35,"state":"open","locked":false,"title":"Refactor ACS communication","user":{"login":"euank","id":2147649,"avatar_url":"https://avatars.githubusercontent.com/u/2147649?v=3","gravatar_id":"","url":"https://api.github.com/users/euank","html_url":"https://github.com/euank","followers_url":"https://api.github.com/users/euank/followers","following_url":"https://api.github.com/users/euank/following{/other_user}","gists_url":"https://api.github.com/users/euank/gists{/gist_id}","starred_url":"https://api.github.com/users/euank/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/euank/subscriptions","organizations_url":"https://api.github.com/users/euank/orgs","repos_url":"https://api.github.com/users/euank/repos","events_url":"https://api.github.com/users/euank/events{/privacy}","received_events_url":"https://api.github.com/users/euank/received_events","type":"User","site_admin":false},"body":"This changes the ACS package to use a .json model + aws-sdk-go to generate the types used for communication with the server.\r\n\r\nImprovements:\r\nEasier to include further changes / message types\r\nBetter handling of errors\r\nBetter test coverage\r\n\r\nConcerns:\r\nThe vendored aws-sdk-go version is an older version of the 'develop' branch and the current develop branch does not cleanly work here.\r\nThis isn't great, but I'd like to just wait for upstream to stabalize a bit more and deal with catching up then, and vendor for now. I think these changes are useful enough that we should still release this with this concern.\r\n\r\nr? @samuelkarp @kiranmeduri ","created_at":"2015-03-24T21:10:02Z","updated_at":"2015-03-25T19:13:54Z","closed_at":null,"merged_at":null,"merge_commit_sha":"830dac17b5f0fdb496387679d1034872db587481","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/aws/amazon-ecs-agent/pulls/35/commits","review_comments_url":"https://api.github.com/repos/aws/amazon-ecs-agent/pulls/35/comments","review_comment_url":"https://api.github.com/repos/aws/amazon-ecs-agent/pulls/comments{/number}","comments_url":"https://api.github.com/repos/aws/amazon-ecs-agent/issues/35/comments","statuses_url":"https://api.github.com/repos/aws/amazon-ecs-agent/statuses/77de7582fa7321399f84becb76828206a7d86a06","head":{"label":"euank:ACSModel","ref":"ACSModel","sha":"77de7582fa7321399f84becb76828206a7d86a06","user":{"login":"euank","id":2147649,"avatar_url":"https://avatars.githubusercontent.com/u/2147649?v=3","gravatar_id":"","url":"https://api.github.com/users/euank","html_url":"https://github.com/euank","followers_url":"https://api.github.com/users/euank/followers","following_url":"https://api.github.com/users/euank/following{/other_user}","gists_url":"https://api.github.com/users/euank/gists{/gist_id}","starred_url":"https://api.github.com/users/euank/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/euank/subscriptions","organizations_url":"https://api.github.com/users/euank/orgs","repos_url":"https://api.github.com/users/euank/repos","events_url":"https://api.github.com/users/euank/events{/privacy}","received_events_url":"https://api.github.com/users/euank/received_events","type":"User","site_admin":false},"repo":{"id":30337468,"name":"amazon-ecs-agent","full_name":"euank/amazon-ecs-agent","owner":{"login":"euank","id":2147649,"avatar_url":"https://avatars.githubusercontent.com/u/2147649?v=3","gravatar_id":"","url":"https://api.github.com/users/euank","html_url":"https://github.com/euank","followers_url":"https://api.github.com/users/euank/followers","following_url":"https://api.github.com/users/euank/following{/other_user}","gists_url":"https://api.github.com/users/euank/gists{/gist_id}","starred_url":"https://api.github.com/users/euank/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/euank/subscriptions","organizations_url":"https://api.github.com/users/euank/orgs","repos_url":"https://api.github.com/users/euank/repos","events_url":"https://api.github.com/users/euank/events{/privacy}","received_events_url":"https://api.github.com/users/euank/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/euank/amazon-ecs-agent","description":"Amazon EC2 Container Service Agent","fork":true,"url":"https://api.github.com/repos/euank/amazon-ecs-agent","forks_url":"https://api.github.com/repos/euank/amazon-ecs-agent/forks","keys_url":"https://api.github.com/repos/euank/amazon-ecs-agent/keys{/key_id}","collaborators_url":"https://api.github.com/repos/euank/amazon-ecs-agent/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/euank/amazon-ecs-agent/teams","hooks_url":"https://api.github.com/repos/euank/amazon-ecs-agent/hooks","issue_events_url":"https://api.github.com/repos/euank/amazon-ecs-agent/issues/events{/number}","events_url":"https://api.github.com/repos/euank/amazon-ecs-agent/events","assignees_url":"https://api.github.com/repos/euank/amazon-ecs-agent/assignees{/user}","branches_url":"https://api.github.com/repos/euank/amazon-ecs-agent/branches{/branch}","tags_url":"https://api.github.com/repos/euank/amazon-ecs-agent/tags","blobs_url":"https://api.github.com/repos/euank/amazon-ecs-agent/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/euank/amazon-ecs-agent/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/euank/amazon-ecs-agent/git/refs{/sha}","trees_url":"https://api.github.com/repos/euank/amazon-ecs-agent/git/trees{/sha}","statuses_url":"https://api.github.com/repos/euank/amazon-ecs-agent/statuses/{sha}","languages_url":"https://api.github.com/repos/euank/amazon-ecs-agent/languages","stargazers_url":"https://api.github.com/repos/euank/amazon-ecs-agent/stargazers","contributors_url":"https://api.github.com/repos/euank/amazon-ecs-agent/contributors","subscribers_url":"https://api.github.com/repos/euank/amazon-ecs-agent/subscribers","subscription_url":"https://api.github.com/repos/euank/amazon-ecs-agent/subscription","commits_url":"https://api.github.com/repos/euank/amazon-ecs-agent/commits{/sha}","git_commits_url":"https://api.github.com/repos/euank/amazon-ecs-agent/git/commits{/sha}","comments_url":"https://api.github.com/repos/euank/amazon-ecs-agent/comments{/number}","issue_comment_url":"https://api.github.com/repos/euank/amazon-ecs-agent/issues/comments{/number}","contents_url":"https://api.github.com/repos/euank/amazon-ecs-agent/contents/{+path}","compare_url":"https://api.github.com/repos/euank/amazon-ecs-agent/compare/{base}...{head}","merges_url":"https://api.github.com/repos/euank/amazon-ecs-agent/merges","archive_url":"https://api.github.com/repos/euank/amazon-ecs-agent/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/euank/amazon-ecs-agent/downloads","issues_url":"https://api.github.com/repos/euank/amazon-ecs-agent/issues{/number}","pulls_url":"https://api.github.com/repos/euank/amazon-ecs-agent/pulls{/number}","milestones_url":"https://api.github.com/repos/euank/amazon-ecs-agent/milestones{/number}","notifications_url":"https://api.github.com/repos/euank/amazon-ecs-agent/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/euank/amazon-ecs-agent/labels{/name}","releases_url":"https://api.github.com/repos/euank/amazon-ecs-agent/releases{/id}","created_at":"2015-02-05T04:21:50Z","updated_at":"2015-03-25T18:30:55Z","pushed_at":"2015-03-25T18:30:55Z","git_url":"git://github.com/euank/amazon-ecs-agent.git","ssh_url":"git@github.com:euank/amazon-ecs-agent.git","clone_url":"https://github.com/euank/amazon-ecs-agent.git","svn_url":"https://github.com/euank/amazon-ecs-agent","homepage":"http://aws.amazon.com/ecs/","size":1049,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"aws:dev","ref":"dev","sha":"0e3fdf617f73112e1c94ce549c6ccd58f7514506","user":{"login":"aws","id":2232217,"avatar_url":"https://avatars.githubusercontent.com/u/2232217?v=3","gravatar_id":"","url":"https://api.github.com/users/aws","html_url":"https://github.com/aws","followers_url":"https://api.github.com/users/aws/followers","following_url":"https://api.github.com/users/aws/following{/other_user}","gists_url":"https://api.github.com/users/aws/gists{/gist_id}","starred_url":"https://api.github.com/users/aws/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aws/subscriptions","organizations_url":"https://api.github.com/users/aws/orgs","repos_url":"https://api.github.com/users/aws/repos","events_url":"https://api.github.com/users/aws/events{/privacy}","received_events_url":"https://api.github.com/users/aws/received_events","type":"Organization","site_admin":false},"repo":{"id":27551774,"name":"amazon-ecs-agent","full_name":"aws/amazon-ecs-agent","owner":{"login":"aws","id":2232217,"avatar_url":"https://avatars.githubusercontent.com/u/2232217?v=3","gravatar_id":"","url":"https://api.github.com/users/aws","html_url":"https://github.com/aws","followers_url":"https://api.github.com/users/aws/followers","following_url":"https://api.github.com/users/aws/following{/other_user}","gists_url":"https://api.github.com/users/aws/gists{/gist_id}","starred_url":"https://api.github.com/users/aws/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aws/subscriptions","organizations_url":"https://api.github.com/users/aws/orgs","repos_url":"https://api.github.com/users/aws/repos","events_url":"https://api.github.com/users/aws/events{/privacy}","received_events_url":"https://api.github.com/users/aws/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/aws/amazon-ecs-agent","description":"Amazon EC2 Container Service Agent","fork":false,"url":"https://api.github.com/repos/aws/amazon-ecs-agent","forks_url":"https://api.github.com/repos/aws/amazon-ecs-agent/forks","keys_url":"https://api.github.com/repos/aws/amazon-ecs-agent/keys{/key_id}","collaborators_url":"https://api.github.com/repos/aws/amazon-ecs-agent/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/aws/amazon-ecs-agent/teams","hooks_url":"https://api.github.com/repos/aws/amazon-ecs-agent/hooks","issue_events_url":"https://api.github.com/repos/aws/amazon-ecs-agent/issues/events{/number}","events_url":"https://api.github.com/repos/aws/amazon-ecs-agent/events","assignees_url":"https://api.github.com/repos/aws/amazon-ecs-agent/assignees{/user}","branches_url":"https://api.github.com/repos/aws/amazon-ecs-agent/branches{/branch}","tags_url":"https://api.github.com/repos/aws/amazon-ecs-agent/tags","blobs_url":"https://api.github.com/repos/aws/amazon-ecs-agent/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/aws/amazon-ecs-agent/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/aws/amazon-ecs-agent/git/refs{/sha}","trees_url":"https://api.github.com/repos/aws/amazon-ecs-agent/git/trees{/sha}","statuses_url":"https://api.github.com/repos/aws/amazon-ecs-agent/statuses/{sha}","languages_url":"https://api.github.com/repos/aws/amazon-ecs-agent/languages","stargazers_url":"https://api.github.com/repos/aws/amazon-ecs-agent/stargazers","contributors_url":"https://api.github.com/repos/aws/amazon-ecs-agent/contributors","subscribers_url":"https://api.github.com/repos/aws/amazon-ecs-agent/subscribers","subscription_url":"https://api.github.com/repos/aws/amazon-ecs-agent/subscription","commits_url":"https://api.github.com/repos/aws/amazon-ecs-agent/commits{/sha}","git_commits_url":"https://api.github.com/repos/aws/amazon-ecs-agent/git/commits{/sha}","comments_url":"https://api.github.com/repos/aws/amazon-ecs-agent/comments{/number}","issue_comment_url":"https://api.github.com/repos/aws/amazon-ecs-agent/issues/comments{/number}","contents_url":"https://api.github.com/repos/aws/amazon-ecs-agent/contents/{+path}","compare_url":"https://api.github.com/repos/aws/amazon-ecs-agent/compare/{base}...{head}","merges_url":"https://api.github.com/repos/aws/amazon-ecs-agent/merges","archive_url":"https://api.github.com/repos/aws/amazon-ecs-agent/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/aws/amazon-ecs-agent/downloads","issues_url":"https://api.github.com/repos/aws/amazon-ecs-agent/issues{/number}","pulls_url":"https://api.github.com/repos/aws/amazon-ecs-agent/pulls{/number}","milestones_url":"https://api.github.com/repos/aws/amazon-ecs-agent/milestones{/number}","notifications_url":"https://api.github.com/repos/aws/amazon-ecs-agent/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/aws/amazon-ecs-agent/labels{/name}","releases_url":"https://api.github.com/repos/aws/amazon-ecs-agent/releases{/id}","created_at":"2014-12-04T17:31:49Z","updated_at":"2015-03-25T18:55:08Z","pushed_at":"2015-03-25T18:55:08Z","git_url":"git://github.com/aws/amazon-ecs-agent.git","ssh_url":"git@github.com:aws/amazon-ecs-agent.git","clone_url":"https://github.com/aws/amazon-ecs-agent.git","svn_url":"https://github.com/aws/amazon-ecs-agent","homepage":"http://aws.amazon.com/ecs/","size":1448,"stargazers_count":108,"watchers_count":108,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":18,"mirror_url":null,"open_issues_count":11,"forks":18,"open_issues":11,"watchers":108,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/aws/amazon-ecs-agent/pulls/35"},"html":{"href":"https://github.com/aws/amazon-ecs-agent/pull/35"},"issue":{"href":"https://api.github.com/repos/aws/amazon-ecs-agent/issues/35"},"comments":{"href":"https://api.github.com/repos/aws/amazon-ecs-agent/issues/35/comments"},"review_comments":{"href":"https://api.github.com/repos/aws/amazon-ecs-agent/pulls/35/comments"},"review_comment":{"href":"https://api.github.com/repos/aws/amazon-ecs-agent/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/aws/amazon-ecs-agent/pulls/35/commits"},"statuses":{"href":"https://api.github.com/repos/aws/amazon-ecs-agent/statuses/77de7582fa7321399f84becb76828206a7d86a06"}}}}