{"action":"created","comment":{"url":"https://api.github.com/repos/jupyter/enhancement-proposals/pulls/comments/41082142","id":41082142,"diff_hunk":"@@ -0,0 +1,380 @@\n+# API for on-demand environments\n+\n+## Problem\n+\n+The temporary notebook system (tmpnb) was put together to solve some immediate\n+demands, the primary of which were:\n+\n+* Instantaneous launching of a brand new notebook server\n+* Fully reproducible environment (installation, code, data, notebooks, etc.)\n+* Multi-tenant\n+* Launch as a user hits a URL (no interaction)\n+* Launch via a simple API (POST to `/api/spawn`), as used by e.g. thebe\n+\n+In order to make running a multi-tenant service like this simple to operate,\n+maintain, and extend we need a REST API that assists three classes of users:\n+\n+* Front end developers developing against the API (e.g. [Thebe](https://github.com/oreillymedia/thebe) and associated contexts)\n+* Operators (e.g. [codeneuro](http://notebooks.codeneuro.org/), [try.jupyter.org](https://try.jupyter.org), [mybinder](http://mybinder.org))\n+* Users (consuming Jupyter kernels as developers, readers, scientists, researchers)\n+\n+There are four main actions:\n+\n+* `build` - build an image from the contents of a GitHub repository (or possibly some other specification)\n+* `register` - register one or more images as a template for deployment, including specifying any additional services, and resource allocation\n+* `deploy` - deploys a named template, and provides status about running application from that template\n+* `pool` - pre-allocate and view details about current pools of running applications\n+\n+The four resources that support these actions are:\n+\n+* `builds`\n+* `templates`\n+* `applications`\n+* `pools`\n+\n+Some of these operations should have authorization, depending on their usage.\n+These are assumed to be run on an API endpoint (e.g. api.mybinder.org) or\n+potentially with a leading `/api/` path.\n+\n+\n+## Build images\n+\n+We build images from GitHub repositories through a `POST` to the `images` resource, by specifying a description of a runtime and its dependencies, and additional resources (e.g. data)\n+\n+Create an image from a repository\n+\n+```\n+POST /builds/repos HTTP 1.1\n+Content-Type: application/json\n+\n+{\n+  \"repository\": \"https://github.com/user/name\",\n+  \"dependencies\": [\"requirements.txt\"]\n+}\n+```\n+\n+*returns*\n+\n+```\n+{\n+\t\"image-name\": \"image-name\"\n+}\n+```\n+\n+\n+Get info on an image\n+\n+```\n+GET /builds/repos/{image-name}\n+```\n+\n+*returns*\n+\n+\n+```\n+{\n+\t\"image-name\": \"image-name\",\n+\t\"repository\": \"https://github.com/user/name\",\n+\t\"dependencies\": [\"requirements.txt\"]\n+}\n+```\n+\n+Get image id for a repository\n+\n+```\n+GET /builds/repos?repository=\"https://github.com/user/name\"\n+```\n+\n+*returns*\n+\n+```\n+{\n+\t\"image-name\": \"image-name\"\n+}\n+```\n+\n+Get status on a build\n+\n+```\n+GET /builds/repos/{image-name}/status HTTP 1.1\n+Authorization: 8a5b42ef54ceafe6af87e5\n+```\n+```\n+{\n+\t\"status\": \"completed\" | \"pending\" | \"failed\"\n+}\n+```\n+\n+\n+## Register templates\n+\n+We register templates by providing an image and a set of computing resources, as well as possible add-on services. This lets us either use an image we have already built from a repository (in the `build` step), or use an image that we've whitelisted (e.g. a known image we want to make available for a large-scale `thebe` deployment).\n+\n+Register a template for a named image (plus its configuration)\n+\n+```\n+POST /templates HTTP 1.1\n+Content-Type: application/json\n+Authorization: 8a5b42ef54ceafe6af87e5\n+\n+{\n+\t\"image-name\": \"image-name\",\n+\t\"limits\":\n+\t\t{\n+\t\t\t\"memory\": \"...\",\n+\t\t\t\"cpu\": \"...\"\n+\t\t}\n+\t\"services\":\n+\t[\n+\t\t{\n+\t\t\t\"name\": \"spark\",\n+\t\t\t\"version\": \"1.4.1\",\n+\t\t\t\"params\": {\n+\t\t\t\t\"heap_mem\": \"4g\",\n+\t\t\t\t\"stack_mem\": \"512m\"\n+\t\t\t}\n+\t\t}, ...\n+ \t]\n+}\n+```\n+\n+*returns*\n+\n+```\n+{\n+        \"template-name\": \"template-name\"\n+}\n+```\n+","path":"binder-api/README.md","position":148,"original_position":148,"commit_id":"2fdba2f74e65782448064b0c6595702b506b5031","original_commit_id":"2fdba2f74e65782448064b0c6595702b506b5031","user":{"login":"rgbkrk","id":836375,"avatar_url":"https://avatars.githubusercontent.com/u/836375?v=3","gravatar_id":"","url":"https://api.github.com/users/rgbkrk","html_url":"https://github.com/rgbkrk","followers_url":"https://api.github.com/users/rgbkrk/followers","following_url":"https://api.github.com/users/rgbkrk/following{/other_user}","gists_url":"https://api.github.com/users/rgbkrk/gists{/gist_id}","starred_url":"https://api.github.com/users/rgbkrk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rgbkrk/subscriptions","organizations_url":"https://api.github.com/users/rgbkrk/orgs","repos_url":"https://api.github.com/users/rgbkrk/repos","events_url":"https://api.github.com/users/rgbkrk/events{/privacy}","received_events_url":"https://api.github.com/users/rgbkrk/received_events","type":"User","site_admin":false},"body":"We also want to be able to do a PUT to update the template, possibly with:\r\n\r\n* CORS headers\r\n  * `Access-Control-Allow-Credentials`\r\n  * `Access-Control-Allow-Headers`\r\n  * `Access-Control-Allow-Methods`\r\n  * `Access-Control-Allow-Origin`\r\n  * `Access-Control-Expose-Headers`\r\n  * `Access-Control-Max-Age`\r\n* Origin checking, specifically for websockets\r\n* cull time\r\n* mem limit\r\n* cpu shares\r\n* command to run - `CMD` in Docker parlance (to include the `{path}` mustache template?)","created_at":"2015-10-03T01:26:58Z","updated_at":"2015-10-03T01:26:58Z","html_url":"https://github.com/jupyter/enhancement-proposals/pull/5#discussion_r41082142","pull_request_url":"https://api.github.com/repos/jupyter/enhancement-proposals/pulls/5","_links":{"self":{"href":"https://api.github.com/repos/jupyter/enhancement-proposals/pulls/comments/41082142"},"html":{"href":"https://github.com/jupyter/enhancement-proposals/pull/5#discussion_r41082142"},"pull_request":{"href":"https://api.github.com/repos/jupyter/enhancement-proposals/pulls/5"}}},"pull_request":{"url":"https://api.github.com/repos/jupyter/enhancement-proposals/pulls/5","id":46104150,"html_url":"https://github.com/jupyter/enhancement-proposals/pull/5","diff_url":"https://github.com/jupyter/enhancement-proposals/pull/5.diff","patch_url":"https://github.com/jupyter/enhancement-proposals/pull/5.patch","issue_url":"https://api.github.com/repos/jupyter/enhancement-proposals/issues/5","number":5,"state":"open","locked":false,"title":"Binder API for specifying, launching, and pooling notebook servers.","user":{"login":"rgbkrk","id":836375,"avatar_url":"https://avatars.githubusercontent.com/u/836375?v=3","gravatar_id":"","url":"https://api.github.com/users/rgbkrk","html_url":"https://github.com/rgbkrk","followers_url":"https://api.github.com/users/rgbkrk/followers","following_url":"https://api.github.com/users/rgbkrk/following{/other_user}","gists_url":"https://api.github.com/users/rgbkrk/gists{/gist_id}","starred_url":"https://api.github.com/users/rgbkrk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rgbkrk/subscriptions","organizations_url":"https://api.github.com/users/rgbkrk/orgs","repos_url":"https://api.github.com/users/rgbkrk/repos","events_url":"https://api.github.com/users/rgbkrk/events{/privacy}","received_events_url":"https://api.github.com/users/rgbkrk/received_events","type":"User","site_admin":false},"body":"The temporary notebook system (tmpnb) was put together to solve some immediate\r\ndemands, the primary of which were:\r\n\r\n* Instantaneous launching of a brand new notebook server\r\n* Fully reproducible environment (installation, code, data, notebooks, etc.)\r\n* Multi-tenant\r\n* Launch as a user hits a URL (no interaction)\r\n* Launch via a simple API (POST to `/api/spawn`), as used by e.g. thebe\r\n\r\nIn order to make running a multi-tenant service like this simple to operate,\r\nmaintain, and extend we need a REST API that assists three classes of users:\r\n\r\n* Front end developers developing against the API (e.g. Thebe and associated contexts)\r\n* Operators (e.g. codeneuro, try.jupyter.org, mybinder)\r\n* Users (consuming kernels as developers, readers, scientists, researchers)\r\n\r\nThere are four main actions:\r\n\r\n* `build` - build an image from the contents of a GitHub repository (or possibly some other specification)\r\n* `stage` - make one or more images ready for deployment, including specifying any additional services, and resource allocation\r\n* `deploy` - deploys a named environment, and provides status about running versions of that environment\r\n* `pool` - pre-allocate and view details about current pools of running environments\r\n\r\nThe four resources that support these actions are:\r\n\r\n* `builds`\r\n* `stagings`\r\n* `servers`\r\n* `pools`\r\n\r\nSome of these operations should have authorization, depending on their usage.\r\nThese are assumed to be run on an API endpoint (e.g. api.mybinder.org) or\r\npotentially with a leading `/api/` path.\r\n\r\nThe README is the main source to review right now and we can work toward a full spec in swagger.\r\n\r\nThis was also brought up in https://github.com/binder-project/binder/issues/8 as well as https://groups.google.com/forum/#!msg/jupyter/2K2Wuem1HB8/r4dQ_6FbEAAJ.","created_at":"2015-09-27T16:46:06Z","updated_at":"2015-10-03T01:26:58Z","closed_at":null,"merged_at":null,"merge_commit_sha":"90bbd951bd632bc005a6d8d0b21652d4d981ae6f","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/jupyter/enhancement-proposals/pulls/5/commits","review_comments_url":"https://api.github.com/repos/jupyter/enhancement-proposals/pulls/5/comments","review_comment_url":"https://api.github.com/repos/jupyter/enhancement-proposals/pulls/comments{/number}","comments_url":"https://api.github.com/repos/jupyter/enhancement-proposals/issues/5/comments","statuses_url":"https://api.github.com/repos/jupyter/enhancement-proposals/statuses/2fdba2f74e65782448064b0c6595702b506b5031","head":{"label":"rgbkrk:binder-api","ref":"binder-api","sha":"2fdba2f74e65782448064b0c6595702b506b5031","user":{"login":"rgbkrk","id":836375,"avatar_url":"https://avatars.githubusercontent.com/u/836375?v=3","gravatar_id":"","url":"https://api.github.com/users/rgbkrk","html_url":"https://github.com/rgbkrk","followers_url":"https://api.github.com/users/rgbkrk/followers","following_url":"https://api.github.com/users/rgbkrk/following{/other_user}","gists_url":"https://api.github.com/users/rgbkrk/gists{/gist_id}","starred_url":"https://api.github.com/users/rgbkrk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rgbkrk/subscriptions","organizations_url":"https://api.github.com/users/rgbkrk/orgs","repos_url":"https://api.github.com/users/rgbkrk/repos","events_url":"https://api.github.com/users/rgbkrk/events{/privacy}","received_events_url":"https://api.github.com/users/rgbkrk/received_events","type":"User","site_admin":false},"repo":{"id":41513166,"name":"enhancement-proposals","full_name":"rgbkrk/enhancement-proposals","owner":{"login":"rgbkrk","id":836375,"avatar_url":"https://avatars.githubusercontent.com/u/836375?v=3","gravatar_id":"","url":"https://api.github.com/users/rgbkrk","html_url":"https://github.com/rgbkrk","followers_url":"https://api.github.com/users/rgbkrk/followers","following_url":"https://api.github.com/users/rgbkrk/following{/other_user}","gists_url":"https://api.github.com/users/rgbkrk/gists{/gist_id}","starred_url":"https://api.github.com/users/rgbkrk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rgbkrk/subscriptions","organizations_url":"https://api.github.com/users/rgbkrk/orgs","repos_url":"https://api.github.com/users/rgbkrk/repos","events_url":"https://api.github.com/users/rgbkrk/events{/privacy}","received_events_url":"https://api.github.com/users/rgbkrk/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/rgbkrk/enhancement-proposals","description":"Enhancement proposals for the Jupyter Ecosystem","fork":true,"url":"https://api.github.com/repos/rgbkrk/enhancement-proposals","forks_url":"https://api.github.com/repos/rgbkrk/enhancement-proposals/forks","keys_url":"https://api.github.com/repos/rgbkrk/enhancement-proposals/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rgbkrk/enhancement-proposals/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rgbkrk/enhancement-proposals/teams","hooks_url":"https://api.github.com/repos/rgbkrk/enhancement-proposals/hooks","issue_events_url":"https://api.github.com/repos/rgbkrk/enhancement-proposals/issues/events{/number}","events_url":"https://api.github.com/repos/rgbkrk/enhancement-proposals/events","assignees_url":"https://api.github.com/repos/rgbkrk/enhancement-proposals/assignees{/user}","branches_url":"https://api.github.com/repos/rgbkrk/enhancement-proposals/branches{/branch}","tags_url":"https://api.github.com/repos/rgbkrk/enhancement-proposals/tags","blobs_url":"https://api.github.com/repos/rgbkrk/enhancement-proposals/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rgbkrk/enhancement-proposals/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rgbkrk/enhancement-proposals/git/refs{/sha}","trees_url":"https://api.github.com/repos/rgbkrk/enhancement-proposals/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rgbkrk/enhancement-proposals/statuses/{sha}","languages_url":"https://api.github.com/repos/rgbkrk/enhancement-proposals/languages","stargazers_url":"https://api.github.com/repos/rgbkrk/enhancement-proposals/stargazers","contributors_url":"https://api.github.com/repos/rgbkrk/enhancement-proposals/contributors","subscribers_url":"https://api.github.com/repos/rgbkrk/enhancement-proposals/subscribers","subscription_url":"https://api.github.com/repos/rgbkrk/enhancement-proposals/subscription","commits_url":"https://api.github.com/repos/rgbkrk/enhancement-proposals/commits{/sha}","git_commits_url":"https://api.github.com/repos/rgbkrk/enhancement-proposals/git/commits{/sha}","comments_url":"https://api.github.com/repos/rgbkrk/enhancement-proposals/comments{/number}","issue_comment_url":"https://api.github.com/repos/rgbkrk/enhancement-proposals/issues/comments{/number}","contents_url":"https://api.github.com/repos/rgbkrk/enhancement-proposals/contents/{+path}","compare_url":"https://api.github.com/repos/rgbkrk/enhancement-proposals/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rgbkrk/enhancement-proposals/merges","archive_url":"https://api.github.com/repos/rgbkrk/enhancement-proposals/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rgbkrk/enhancement-proposals/downloads","issues_url":"https://api.github.com/repos/rgbkrk/enhancement-proposals/issues{/number}","pulls_url":"https://api.github.com/repos/rgbkrk/enhancement-proposals/pulls{/number}","milestones_url":"https://api.github.com/repos/rgbkrk/enhancement-proposals/milestones{/number}","notifications_url":"https://api.github.com/repos/rgbkrk/enhancement-proposals/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rgbkrk/enhancement-proposals/labels{/name}","releases_url":"https://api.github.com/repos/rgbkrk/enhancement-proposals/releases{/id}","created_at":"2015-08-27T21:50:07Z","updated_at":"2015-08-27T21:09:35Z","pushed_at":"2015-10-03T00:48:13Z","git_url":"git://github.com/rgbkrk/enhancement-proposals.git","ssh_url":"git@github.com:rgbkrk/enhancement-proposals.git","clone_url":"https://github.com/rgbkrk/enhancement-proposals.git","svn_url":"https://github.com/rgbkrk/enhancement-proposals","homepage":null,"size":87,"stargazers_count":0,"watchers_count":0,"language":null,"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":"jupyter:master","ref":"master","sha":"65037886f480c8344a347b4ebefe81437868fdce","user":{"login":"jupyter","id":7388996,"avatar_url":"https://avatars.githubusercontent.com/u/7388996?v=3","gravatar_id":"","url":"https://api.github.com/users/jupyter","html_url":"https://github.com/jupyter","followers_url":"https://api.github.com/users/jupyter/followers","following_url":"https://api.github.com/users/jupyter/following{/other_user}","gists_url":"https://api.github.com/users/jupyter/gists{/gist_id}","starred_url":"https://api.github.com/users/jupyter/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jupyter/subscriptions","organizations_url":"https://api.github.com/users/jupyter/orgs","repos_url":"https://api.github.com/users/jupyter/repos","events_url":"https://api.github.com/users/jupyter/events{/privacy}","received_events_url":"https://api.github.com/users/jupyter/received_events","type":"Organization","site_admin":false},"repo":{"id":41511140,"name":"enhancement-proposals","full_name":"jupyter/enhancement-proposals","owner":{"login":"jupyter","id":7388996,"avatar_url":"https://avatars.githubusercontent.com/u/7388996?v=3","gravatar_id":"","url":"https://api.github.com/users/jupyter","html_url":"https://github.com/jupyter","followers_url":"https://api.github.com/users/jupyter/followers","following_url":"https://api.github.com/users/jupyter/following{/other_user}","gists_url":"https://api.github.com/users/jupyter/gists{/gist_id}","starred_url":"https://api.github.com/users/jupyter/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jupyter/subscriptions","organizations_url":"https://api.github.com/users/jupyter/orgs","repos_url":"https://api.github.com/users/jupyter/repos","events_url":"https://api.github.com/users/jupyter/events{/privacy}","received_events_url":"https://api.github.com/users/jupyter/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/jupyter/enhancement-proposals","description":"Enhancement proposals for the Jupyter Ecosystem","fork":false,"url":"https://api.github.com/repos/jupyter/enhancement-proposals","forks_url":"https://api.github.com/repos/jupyter/enhancement-proposals/forks","keys_url":"https://api.github.com/repos/jupyter/enhancement-proposals/keys{/key_id}","collaborators_url":"https://api.github.com/repos/jupyter/enhancement-proposals/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/jupyter/enhancement-proposals/teams","hooks_url":"https://api.github.com/repos/jupyter/enhancement-proposals/hooks","issue_events_url":"https://api.github.com/repos/jupyter/enhancement-proposals/issues/events{/number}","events_url":"https://api.github.com/repos/jupyter/enhancement-proposals/events","assignees_url":"https://api.github.com/repos/jupyter/enhancement-proposals/assignees{/user}","branches_url":"https://api.github.com/repos/jupyter/enhancement-proposals/branches{/branch}","tags_url":"https://api.github.com/repos/jupyter/enhancement-proposals/tags","blobs_url":"https://api.github.com/repos/jupyter/enhancement-proposals/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/jupyter/enhancement-proposals/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/jupyter/enhancement-proposals/git/refs{/sha}","trees_url":"https://api.github.com/repos/jupyter/enhancement-proposals/git/trees{/sha}","statuses_url":"https://api.github.com/repos/jupyter/enhancement-proposals/statuses/{sha}","languages_url":"https://api.github.com/repos/jupyter/enhancement-proposals/languages","stargazers_url":"https://api.github.com/repos/jupyter/enhancement-proposals/stargazers","contributors_url":"https://api.github.com/repos/jupyter/enhancement-proposals/contributors","subscribers_url":"https://api.github.com/repos/jupyter/enhancement-proposals/subscribers","subscription_url":"https://api.github.com/repos/jupyter/enhancement-proposals/subscription","commits_url":"https://api.github.com/repos/jupyter/enhancement-proposals/commits{/sha}","git_commits_url":"https://api.github.com/repos/jupyter/enhancement-proposals/git/commits{/sha}","comments_url":"https://api.github.com/repos/jupyter/enhancement-proposals/comments{/number}","issue_comment_url":"https://api.github.com/repos/jupyter/enhancement-proposals/issues/comments{/number}","contents_url":"https://api.github.com/repos/jupyter/enhancement-proposals/contents/{+path}","compare_url":"https://api.github.com/repos/jupyter/enhancement-proposals/compare/{base}...{head}","merges_url":"https://api.github.com/repos/jupyter/enhancement-proposals/merges","archive_url":"https://api.github.com/repos/jupyter/enhancement-proposals/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/jupyter/enhancement-proposals/downloads","issues_url":"https://api.github.com/repos/jupyter/enhancement-proposals/issues{/number}","pulls_url":"https://api.github.com/repos/jupyter/enhancement-proposals/pulls{/number}","milestones_url":"https://api.github.com/repos/jupyter/enhancement-proposals/milestones{/number}","notifications_url":"https://api.github.com/repos/jupyter/enhancement-proposals/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/jupyter/enhancement-proposals/labels{/name}","releases_url":"https://api.github.com/repos/jupyter/enhancement-proposals/releases{/id}","created_at":"2015-08-27T21:01:47Z","updated_at":"2015-09-29T18:33:41Z","pushed_at":"2015-10-03T00:48:13Z","git_url":"git://github.com/jupyter/enhancement-proposals.git","ssh_url":"git@github.com:jupyter/enhancement-proposals.git","clone_url":"https://github.com/jupyter/enhancement-proposals.git","svn_url":"https://github.com/jupyter/enhancement-proposals","homepage":null,"size":215,"stargazers_count":8,"watchers_count":8,"language":null,"has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":5,"mirror_url":null,"open_issues_count":2,"forks":5,"open_issues":2,"watchers":8,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/jupyter/enhancement-proposals/pulls/5"},"html":{"href":"https://github.com/jupyter/enhancement-proposals/pull/5"},"issue":{"href":"https://api.github.com/repos/jupyter/enhancement-proposals/issues/5"},"comments":{"href":"https://api.github.com/repos/jupyter/enhancement-proposals/issues/5/comments"},"review_comments":{"href":"https://api.github.com/repos/jupyter/enhancement-proposals/pulls/5/comments"},"review_comment":{"href":"https://api.github.com/repos/jupyter/enhancement-proposals/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/jupyter/enhancement-proposals/pulls/5/commits"},"statuses":{"href":"https://api.github.com/repos/jupyter/enhancement-proposals/statuses/2fdba2f74e65782448064b0c6595702b506b5031"}}}}