{"action":"created","comment":{"url":"https://api.github.com/repos/docker/swarmkit/pulls/comments/75244658","id":75244658,"diff_hunk":"@@ -0,0 +1,123 @@\n+package resourceapi\n+\n+import (\n+\t\"errors\"\n+\t\"time\"\n+\n+\t\"github.com/docker/swarmkit/api\"\n+\t\"github.com/docker/swarmkit/ca\"\n+\t\"github.com/docker/swarmkit/identity\"\n+\t\"github.com/docker/swarmkit/manager/state/store\"\n+\t\"github.com/docker/swarmkit/protobuf/ptypes\"\n+\t\"golang.org/x/net/context\"\n+\t\"google.golang.org/grpc\"\n+\t\"google.golang.org/grpc/codes\"\n+)\n+\n+var (\n+\terrInvalidArgument = errors.New(\"invalid argument\")\n+)\n+\n+// ResourceAllocator handles resource allocation of cluster entities.\n+type ResourceAllocator struct {\n+\tstore *store.MemoryStore\n+}\n+\n+// New returns an instance of the allocator\n+func New(store *store.MemoryStore) *ResourceAllocator {\n+\treturn &ResourceAllocator{store: store}\n+}\n+\n+// AttachNetwork allows the node to request the resources\n+// allocation needed for a network attachment on the specific node.\n+// - Returns `InvalidArgument` if the Spec is malformed.\n+// - Returns `NotFound` if the Network is not found.\n+// - Returns an error if the creation fails.\n+func (ra *ResourceAllocator) AttachNetwork(ctx context.Context, request *api.AttachNetworkRequest) (*api.AttachNetworkResponse, error) {\n+\tnodeInfo, err := ca.RemoteNode(ctx)\n+\tif err != nil {\n+\t\treturn nil, err\n+\t}\n+\n+\tvar network *api.Network\n+\tra.store.View(func(tx store.ReadTx) {\n+\t\tnetwork = store.GetNetwork(tx, request.Config.Target)\n+\t\tif network == nil {\n+\t\t\tif networks, err := store.FindNetworks(tx, store.ByName(request.Config.Target)); err == nil && len(networks) == 1 {\n+\t\t\t\tnetwork = networks[0]\n+\t\t\t}\n+\t\t}\n+\t})\n+\tif network == nil {\n+\t\treturn nil, grpc.Errorf(codes.NotFound, \"network %s not found\", request.Config.Target)\n+\t}\n+\n+\tif !network.Spec.ManuallyAttachable {\n+\t\treturn nil, grpc.Errorf(codes.PermissionDenied, \"cannot attach to network %s (permission denied)\", request.Config.Target)\n+\t}\n+\n+\tt := &api.Task{\n+\t\tID:     identity.NewID(),\n+\t\tNodeID: nodeInfo.NodeID,\n+\t\tSpec: api.TaskSpec{\n+\t\t\tRuntime: &api.TaskSpec_Attachment{\n+\t\t\t\tAttachment: &api.NetworkAttachmentSpec{\n+\t\t\t\t\tID: request.ID,\n+\t\t\t\t},\n+\t\t\t},\n+\t\t\tNetworks: []*api.NetworkAttachmentConfig{\n+\t\t\t\t{\n+\t\t\t\t\tTarget:    network.ID,\n+\t\t\t\t\tAddresses: request.Config.Addresses,\n+\t\t\t\t},\n+\t\t\t},\n+\t\t},\n+\t\tStatus: api.TaskStatus{\n+\t\t\tState:     api.TaskStateNew,\n+\t\t\tTimestamp: ptypes.MustTimestampProto(time.Now()),\n+\t\t\tMessage:   \"created\",\n+\t\t},\n+\t\tDesiredState: api.TaskStateRunning,\n+\t\t// TODO: Add Network attachment.\n+\t}\n+\n+\tif err := ra.store.Update(func(tx store.Tx) error {\n+\t\treturn store.CreateTask(tx, t)\n+\t}); err != nil {\n+\t\treturn nil, err\n+\t}\n+\n+\treturn &api.AttachNetworkResponse{AttachmentID: t.ID}, nil\n+}\n+\n+// DetachNetwork allows the node to request the release of\n+// the resources associated to the network attachment.\n+// - Returns `InvalidArgument` if attachment ID is not provided.\n+// - Returns `NotFound` if the attachment is not found.\n+// - Returns an error if the deletion fails.\n+func (ra *ResourceAllocator) DetachNetwork(ctx context.Context, request *api.DetachNetworkRequest) (*api.DetachNetworkResponse, error) {\n+\tif request.AttachmentID == \"\" {\n+\t\treturn nil, grpc.Errorf(codes.InvalidArgument, errInvalidArgument.Error())\n+\t}\n+\n+\tnodeInfo, err := ca.RemoteNode(ctx)\n+\tif err != nil {\n+\t\treturn nil, err\n+\t}\n+\n+\tif err := ra.store.Update(func(tx store.Tx) error {\n+\t\tt := store.GetTask(tx, request.AttachmentID)\n+\t\tif t == nil {\n+\t\t\treturn grpc.Errorf(codes.NotFound, \"attachment %s not found\", request.AttachmentID)\n+\t\t}\n+\t\tif t.NodeID != nodeInfo.NodeID {\n+\t\t\treturn grpc.Errorf(codes.PermissionDenied, \"attachment %s doesn't belong to this node\", request.AttachmentID)","path":"manager/resourceapi/allocator.go","position":114,"original_position":114,"commit_id":"3f997b1cc48dfc3092d18ed516bf1621b2a89fe9","original_commit_id":"3f997b1cc48dfc3092d18ed516bf1621b2a89fe9","user":{"login":"mrjana","id":1693482,"avatar_url":"https://avatars.githubusercontent.com/u/1693482?v=3","gravatar_id":"","url":"https://api.github.com/users/mrjana","html_url":"https://github.com/mrjana","followers_url":"https://api.github.com/users/mrjana/followers","following_url":"https://api.github.com/users/mrjana/following{/other_user}","gists_url":"https://api.github.com/users/mrjana/gists{/gist_id}","starred_url":"https://api.github.com/users/mrjana/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mrjana/subscriptions","organizations_url":"https://api.github.com/users/mrjana/orgs","repos_url":"https://api.github.com/users/mrjana/repos","events_url":"https://api.github.com/users/mrjana/events{/privacy}","received_events_url":"https://api.github.com/users/mrjana/received_events","type":"User","site_admin":false},"body":"Because the node is not authorized to delete this attachment because it did create the attachment in the first place.","created_at":"2016-08-18T03:40:26Z","updated_at":"2016-08-18T03:40:26Z","html_url":"https://github.com/docker/swarmkit/pull/1373#discussion_r75244658","pull_request_url":"https://api.github.com/repos/docker/swarmkit/pulls/1373","_links":{"self":{"href":"https://api.github.com/repos/docker/swarmkit/pulls/comments/75244658"},"html":{"href":"https://github.com/docker/swarmkit/pull/1373#discussion_r75244658"},"pull_request":{"href":"https://api.github.com/repos/docker/swarmkit/pulls/1373"}}},"pull_request":{"url":"https://api.github.com/repos/docker/swarmkit/pulls/1373","id":81349049,"html_url":"https://github.com/docker/swarmkit/pull/1373","diff_url":"https://github.com/docker/swarmkit/pull/1373.diff","patch_url":"https://github.com/docker/swarmkit/pull/1373.patch","issue_url":"https://api.github.com/repos/docker/swarmkit/issues/1373","number":1373,"state":"open","locked":false,"title":"Add resource allocator api","user":{"login":"mrjana","id":1693482,"avatar_url":"https://avatars.githubusercontent.com/u/1693482?v=3","gravatar_id":"","url":"https://api.github.com/users/mrjana","html_url":"https://github.com/mrjana","followers_url":"https://api.github.com/users/mrjana/followers","following_url":"https://api.github.com/users/mrjana/following{/other_user}","gists_url":"https://api.github.com/users/mrjana/gists{/gist_id}","starred_url":"https://api.github.com/users/mrjana/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mrjana/subscriptions","organizations_url":"https://api.github.com/users/mrjana/orgs","repos_url":"https://api.github.com/users/mrjana/repos","events_url":"https://api.github.com/users/mrjana/events{/privacy}","received_events_url":"https://api.github.com/users/mrjana/received_events","type":"User","site_admin":false},"body":"Added resource allocator api to help worker nodes to attach and detach\r\nto a swarm created network so that individual containers can be\r\nindependently attached to a swarm network and discover/access swarm\r\nservices directly.\r\n\r\nSigned-off-by: Jana Radhakrishnan <mrjana@docker.com>","created_at":"2016-08-15T17:59:32Z","updated_at":"2016-08-18T03:40:26Z","closed_at":null,"merged_at":null,"merge_commit_sha":"724bb5c9ae0ab1b750a068310e1c6386debe9ea5","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/docker/swarmkit/pulls/1373/commits","review_comments_url":"https://api.github.com/repos/docker/swarmkit/pulls/1373/comments","review_comment_url":"https://api.github.com/repos/docker/swarmkit/pulls/comments{/number}","comments_url":"https://api.github.com/repos/docker/swarmkit/issues/1373/comments","statuses_url":"https://api.github.com/repos/docker/swarmkit/statuses/3f997b1cc48dfc3092d18ed516bf1621b2a89fe9","head":{"label":"mrjana:drun","ref":"drun","sha":"3f997b1cc48dfc3092d18ed516bf1621b2a89fe9","user":{"login":"mrjana","id":1693482,"avatar_url":"https://avatars.githubusercontent.com/u/1693482?v=3","gravatar_id":"","url":"https://api.github.com/users/mrjana","html_url":"https://github.com/mrjana","followers_url":"https://api.github.com/users/mrjana/followers","following_url":"https://api.github.com/users/mrjana/following{/other_user}","gists_url":"https://api.github.com/users/mrjana/gists{/gist_id}","starred_url":"https://api.github.com/users/mrjana/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mrjana/subscriptions","organizations_url":"https://api.github.com/users/mrjana/orgs","repos_url":"https://api.github.com/users/mrjana/repos","events_url":"https://api.github.com/users/mrjana/events{/privacy}","received_events_url":"https://api.github.com/users/mrjana/received_events","type":"User","site_admin":false},"repo":{"id":60930975,"name":"swarmkit","full_name":"mrjana/swarmkit","owner":{"login":"mrjana","id":1693482,"avatar_url":"https://avatars.githubusercontent.com/u/1693482?v=3","gravatar_id":"","url":"https://api.github.com/users/mrjana","html_url":"https://github.com/mrjana","followers_url":"https://api.github.com/users/mrjana/followers","following_url":"https://api.github.com/users/mrjana/following{/other_user}","gists_url":"https://api.github.com/users/mrjana/gists{/gist_id}","starred_url":"https://api.github.com/users/mrjana/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mrjana/subscriptions","organizations_url":"https://api.github.com/users/mrjana/orgs","repos_url":"https://api.github.com/users/mrjana/repos","events_url":"https://api.github.com/users/mrjana/events{/privacy}","received_events_url":"https://api.github.com/users/mrjana/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/mrjana/swarmkit","description":"A toolkit for orchestrating distributed systems at any scale. It includes primitives for node discovery, raft-based consensus, task scheduling and more.","fork":true,"url":"https://api.github.com/repos/mrjana/swarmkit","forks_url":"https://api.github.com/repos/mrjana/swarmkit/forks","keys_url":"https://api.github.com/repos/mrjana/swarmkit/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mrjana/swarmkit/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mrjana/swarmkit/teams","hooks_url":"https://api.github.com/repos/mrjana/swarmkit/hooks","issue_events_url":"https://api.github.com/repos/mrjana/swarmkit/issues/events{/number}","events_url":"https://api.github.com/repos/mrjana/swarmkit/events","assignees_url":"https://api.github.com/repos/mrjana/swarmkit/assignees{/user}","branches_url":"https://api.github.com/repos/mrjana/swarmkit/branches{/branch}","tags_url":"https://api.github.com/repos/mrjana/swarmkit/tags","blobs_url":"https://api.github.com/repos/mrjana/swarmkit/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mrjana/swarmkit/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mrjana/swarmkit/git/refs{/sha}","trees_url":"https://api.github.com/repos/mrjana/swarmkit/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mrjana/swarmkit/statuses/{sha}","languages_url":"https://api.github.com/repos/mrjana/swarmkit/languages","stargazers_url":"https://api.github.com/repos/mrjana/swarmkit/stargazers","contributors_url":"https://api.github.com/repos/mrjana/swarmkit/contributors","subscribers_url":"https://api.github.com/repos/mrjana/swarmkit/subscribers","subscription_url":"https://api.github.com/repos/mrjana/swarmkit/subscription","commits_url":"https://api.github.com/repos/mrjana/swarmkit/commits{/sha}","git_commits_url":"https://api.github.com/repos/mrjana/swarmkit/git/commits{/sha}","comments_url":"https://api.github.com/repos/mrjana/swarmkit/comments{/number}","issue_comment_url":"https://api.github.com/repos/mrjana/swarmkit/issues/comments{/number}","contents_url":"https://api.github.com/repos/mrjana/swarmkit/contents/{+path}","compare_url":"https://api.github.com/repos/mrjana/swarmkit/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mrjana/swarmkit/merges","archive_url":"https://api.github.com/repos/mrjana/swarmkit/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mrjana/swarmkit/downloads","issues_url":"https://api.github.com/repos/mrjana/swarmkit/issues{/number}","pulls_url":"https://api.github.com/repos/mrjana/swarmkit/pulls{/number}","milestones_url":"https://api.github.com/repos/mrjana/swarmkit/milestones{/number}","notifications_url":"https://api.github.com/repos/mrjana/swarmkit/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mrjana/swarmkit/labels{/name}","releases_url":"https://api.github.com/repos/mrjana/swarmkit/releases{/id}","deployments_url":"https://api.github.com/repos/mrjana/swarmkit/deployments","created_at":"2016-06-11T22:41:22Z","updated_at":"2016-06-11T22:41:23Z","pushed_at":"2016-08-16T23:17:14Z","git_url":"git://github.com/mrjana/swarmkit.git","ssh_url":"git@github.com:mrjana/swarmkit.git","clone_url":"https://github.com/mrjana/swarmkit.git","svn_url":"https://github.com/mrjana/swarmkit","homepage":"","size":9104,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":false,"has_downloads":true,"has_wiki":false,"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":"docker:master","ref":"master","sha":"58c0bfb6dbd53fc03ca16439baa0c0a4268370ae","user":{"login":"docker","id":5429470,"avatar_url":"https://avatars.githubusercontent.com/u/5429470?v=3","gravatar_id":"","url":"https://api.github.com/users/docker","html_url":"https://github.com/docker","followers_url":"https://api.github.com/users/docker/followers","following_url":"https://api.github.com/users/docker/following{/other_user}","gists_url":"https://api.github.com/users/docker/gists{/gist_id}","starred_url":"https://api.github.com/users/docker/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/docker/subscriptions","organizations_url":"https://api.github.com/users/docker/orgs","repos_url":"https://api.github.com/users/docker/repos","events_url":"https://api.github.com/users/docker/events{/privacy}","received_events_url":"https://api.github.com/users/docker/received_events","type":"Organization","site_admin":false},"repo":{"id":51556828,"name":"swarmkit","full_name":"docker/swarmkit","owner":{"login":"docker","id":5429470,"avatar_url":"https://avatars.githubusercontent.com/u/5429470?v=3","gravatar_id":"","url":"https://api.github.com/users/docker","html_url":"https://github.com/docker","followers_url":"https://api.github.com/users/docker/followers","following_url":"https://api.github.com/users/docker/following{/other_user}","gists_url":"https://api.github.com/users/docker/gists{/gist_id}","starred_url":"https://api.github.com/users/docker/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/docker/subscriptions","organizations_url":"https://api.github.com/users/docker/orgs","repos_url":"https://api.github.com/users/docker/repos","events_url":"https://api.github.com/users/docker/events{/privacy}","received_events_url":"https://api.github.com/users/docker/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/docker/swarmkit","description":"A toolkit for orchestrating distributed systems at any scale. It includes primitives for node discovery, raft-based consensus, task scheduling and more.","fork":false,"url":"https://api.github.com/repos/docker/swarmkit","forks_url":"https://api.github.com/repos/docker/swarmkit/forks","keys_url":"https://api.github.com/repos/docker/swarmkit/keys{/key_id}","collaborators_url":"https://api.github.com/repos/docker/swarmkit/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/docker/swarmkit/teams","hooks_url":"https://api.github.com/repos/docker/swarmkit/hooks","issue_events_url":"https://api.github.com/repos/docker/swarmkit/issues/events{/number}","events_url":"https://api.github.com/repos/docker/swarmkit/events","assignees_url":"https://api.github.com/repos/docker/swarmkit/assignees{/user}","branches_url":"https://api.github.com/repos/docker/swarmkit/branches{/branch}","tags_url":"https://api.github.com/repos/docker/swarmkit/tags","blobs_url":"https://api.github.com/repos/docker/swarmkit/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/docker/swarmkit/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/docker/swarmkit/git/refs{/sha}","trees_url":"https://api.github.com/repos/docker/swarmkit/git/trees{/sha}","statuses_url":"https://api.github.com/repos/docker/swarmkit/statuses/{sha}","languages_url":"https://api.github.com/repos/docker/swarmkit/languages","stargazers_url":"https://api.github.com/repos/docker/swarmkit/stargazers","contributors_url":"https://api.github.com/repos/docker/swarmkit/contributors","subscribers_url":"https://api.github.com/repos/docker/swarmkit/subscribers","subscription_url":"https://api.github.com/repos/docker/swarmkit/subscription","commits_url":"https://api.github.com/repos/docker/swarmkit/commits{/sha}","git_commits_url":"https://api.github.com/repos/docker/swarmkit/git/commits{/sha}","comments_url":"https://api.github.com/repos/docker/swarmkit/comments{/number}","issue_comment_url":"https://api.github.com/repos/docker/swarmkit/issues/comments{/number}","contents_url":"https://api.github.com/repos/docker/swarmkit/contents/{+path}","compare_url":"https://api.github.com/repos/docker/swarmkit/compare/{base}...{head}","merges_url":"https://api.github.com/repos/docker/swarmkit/merges","archive_url":"https://api.github.com/repos/docker/swarmkit/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/docker/swarmkit/downloads","issues_url":"https://api.github.com/repos/docker/swarmkit/issues{/number}","pulls_url":"https://api.github.com/repos/docker/swarmkit/pulls{/number}","milestones_url":"https://api.github.com/repos/docker/swarmkit/milestones{/number}","notifications_url":"https://api.github.com/repos/docker/swarmkit/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/docker/swarmkit/labels{/name}","releases_url":"https://api.github.com/repos/docker/swarmkit/releases{/id}","deployments_url":"https://api.github.com/repos/docker/swarmkit/deployments","created_at":"2016-02-12T00:02:15Z","updated_at":"2016-08-18T02:34:24Z","pushed_at":"2016-08-18T00:24:29Z","git_url":"git://github.com/docker/swarmkit.git","ssh_url":"git@github.com:docker/swarmkit.git","clone_url":"https://github.com/docker/swarmkit.git","svn_url":"https://github.com/docker/swarmkit","homepage":"","size":20029,"stargazers_count":892,"watchers_count":892,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":158,"mirror_url":null,"open_issues_count":167,"forks":158,"open_issues":167,"watchers":892,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/docker/swarmkit/pulls/1373"},"html":{"href":"https://github.com/docker/swarmkit/pull/1373"},"issue":{"href":"https://api.github.com/repos/docker/swarmkit/issues/1373"},"comments":{"href":"https://api.github.com/repos/docker/swarmkit/issues/1373/comments"},"review_comments":{"href":"https://api.github.com/repos/docker/swarmkit/pulls/1373/comments"},"review_comment":{"href":"https://api.github.com/repos/docker/swarmkit/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/docker/swarmkit/pulls/1373/commits"},"statuses":{"href":"https://api.github.com/repos/docker/swarmkit/statuses/3f997b1cc48dfc3092d18ed516bf1621b2a89fe9"}}}}
{"actor":{"display_login":"mrjana"}}