{"action":"created","comment":{"url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/pulls/comments/23985658","id":23985658,"diff_hunk":"@@ -0,0 +1,246 @@\n+/*\n+Copyright 2015 Google Inc. All rights reserved.\n+\n+Licensed under the Apache License, Version 2.0 (the \"License\");\n+you may not use this file except in compliance with the License.\n+You may obtain a copy of the License at\n+\n+    http://www.apache.org/licenses/LICENSE-2.0\n+\n+Unless required by applicable law or agreed to in writing, software\n+distributed under the License is distributed on an \"AS IS\" BASIS,\n+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+See the License for the specific language governing permissions and\n+limitations under the License.\n+*/\n+\n+package apiserver\n+\n+import (\n+\t\"net/http\"\n+\t\"reflect\"\n+\n+\t\"github.com/GoogleCloudPlatform/kubernetes/pkg/api\"\n+\n+\t\"github.com/emicklei/go-restful\"\n+\t\"github.com/golang/glog\"\n+)\n+\n+type APIInstaller struct {\n+\tprefix      string // Path prefix where API resources are to be registered.\n+\tversion     string // The API version being installed.\n+\trestHandler *RESTHandler\n+}\n+\n+// Installs handlers for API resources.\n+func (a *APIInstaller) Install() (ws *restful.WebService, errors []error) {\n+\terrors = make([]error, 0)\n+\n+\t// Create the WebService.\n+\tws = a.newWebService()\n+\n+\t// Initialize the custom handlers.\n+\twatchHandler := (&WatchHandler{\n+\t\tstorage:         a.restHandler.storage,\n+\t\tcodec:           a.restHandler.codec,\n+\t\tcanonicalPrefix: a.restHandler.canonicalPrefix,\n+\t\tselfLinker:      a.restHandler.selfLinker,\n+\t})\n+\tredirectHandler := (&RedirectHandler{a.restHandler.storage, a.restHandler.codec})\n+\tproxyHandler := (&ProxyHandler{a.prefix + \"/proxy/\", a.restHandler.storage, a.restHandler.codec})\n+\n+\tfor path, storage := range a.restHandler.storage {\n+\t\t// register legacy patterns where namespace is optional in path\n+\t\tif err := a.registerResourceHandlers(path, storage, ws, watchHandler, redirectHandler, proxyHandler, false); err != nil {\n+\t\t\terrors = append(errors, err)\n+\t\t}\n+\t\t// register patterns where namespace is required in path\n+\t\tif err := a.registerResourceHandlers(path, storage, ws, watchHandler, redirectHandler, proxyHandler, true); err != nil {\n+\t\t\terrors = append(errors, err)\n+\t\t}\n+\t}\n+\treturn ws, errors\n+}\n+\n+func (a *APIInstaller) newWebService() *restful.WebService {\n+\tws := new(restful.WebService)\n+\tws.Path(a.prefix)\n+\tws.Doc(\"API at \" + a.prefix + \" version \" + a.version)\n+\t// TODO: change to restful.MIME_JSON when we set content type in client\n+\tws.Consumes(\"*/*\")\n+\tws.Produces(restful.MIME_JSON)\n+\tws.ApiVersion(a.version)\n+\treturn ws\n+}\n+\n+// Registers the appropriate handlers for the given REST resource.\n+func (a *APIInstaller) registerResourceHandlers(path string, storage RESTStorage, ws *restful.WebService, watchHandler http.Handler, redirectHandler http.Handler, proxyHandler http.Handler, namespaceScope bool) error {\n+\t// Handler for standard REST verbs (GET, PUT, POST, DELETE).\n+\trestVerbHandler := restfulStripPrefix(a.prefix, a.restHandler)\n+\tobject := storage.New()\n+\t// TODO: add scheme to APIInstaller rather than using api.Scheme\n+\t_, kind, err := api.Scheme.ObjectVersionAndKind(object)\n+\tif err != nil {\n+\t\treturn err\n+\t}\n+\tversionedPtr, err := api.Scheme.New(a.version, kind)\n+\tif err != nil {\n+\t\treturn err\n+\t}\n+\tversionedObject := indirectArbitraryPointer(versionedPtr)\n+\n+\tif namespaceScope {\n+\t\tpath = \"ns/{namespace}/\" + path\n+\t}\n+\n+\tglog.V(5).Infof(\"Installing version=/%s, kind=/%s, path=/%s\", a.version, kind, path)\n+\n+\tnameParam := ws.PathParameter(\"name\", \"name of the \"+kind).DataType(\"string\")\n+\tnamespaceParam := ws.PathParameter(\"namespace\", \"object name and auth scope, such as for teams and projects\").DataType(\"string\")\n+\n+\t// TODO: Add status documentation using Returns()\n+\t// Errors (see api/errors/errors.go as well as go-restful router):\n+\t// http.StatusNotFound, http.StatusMethodNotAllowed,\n+\t// http.StatusUnsupportedMediaType, http.StatusNotAcceptable,\n+\t// http.StatusBadRequest, http.StatusUnauthorized, http.StatusForbidden,\n+\t// http.StatusRequestTimeout, http.StatusConflict, http.StatusPreconditionFailed,\n+\t// 422 (StatusUnprocessableEntity), http.StatusInternalServerError,\n+\t// http.StatusServiceUnavailable\n+\t// and api error codes\n+\t// Note that if we specify a versioned Status object here, we may need to\n+\t// create one for the tests, also\n+\t// Success:\n+\t// http.StatusOK, http.StatusCreated, http.StatusAccepted, http.StatusNoContent\n+\t//\n+\t// test/integration/auth_test.go is currently the most comprehensive status code test\n+\n+\tcreateRoute := ws.POST(path).To(restVerbHandler).\n+\t\tDoc(\"create a \" + kind).\n+\t\tOperation(\"create\" + kind)\n+\taddParamIf(createRoute, namespaceParam, namespaceScope)\n+\tif _, ok := storage.(RESTCreater); ok {\n+\t\tws.Route(createRoute.Reads(versionedObject)) // from the request\n+\t} else {\n+\t\tws.Route(createRoute.Returns(http.StatusMethodNotAllowed, \"creating objects is not supported\", nil))\n+\t}\n+\n+\tlistRoute := ws.GET(path).To(restVerbHandler).\n+\t\tDoc(\"list objects of kind \" + kind).\n+\t\tOperation(\"list\" + kind)\n+\taddParamIf(listRoute, namespaceParam, namespaceScope)\n+\tif lister, ok := storage.(RESTLister); ok {\n+\t\tlist := lister.NewList()\n+\t\t_, listKind, err := api.Scheme.ObjectVersionAndKind(list)\n+\t\tversionedListPtr, err := api.Scheme.New(a.version, listKind)\n+\t\tif err != nil {\n+\t\t\treturn err\n+\t\t}\n+\t\tversionedList := indirectArbitraryPointer(versionedListPtr)\n+\t\tglog.V(5).Infoln(\"type: \", reflect.TypeOf(versionedList))\n+\t\tws.Route(listRoute.Returns(http.StatusOK, \"OK\", versionedList))\n+\t} else {\n+\t\tws.Route(listRoute.Returns(http.StatusMethodNotAllowed, \"listing objects is not supported\", nil))\n+\t}\n+\n+\tgetRoute := ws.GET(path + \"/{name}\").To(restVerbHandler).\n+\t\tDoc(\"read the specified \" + kind).\n+\t\tOperation(\"read\" + kind).\n+\t\tParam(nameParam)\n+\taddParamIf(getRoute, namespaceParam, namespaceScope)\n+\tif _, ok := storage.(RESTGetter); ok {\n+\t\tws.Route(getRoute.Writes(versionedObject)) // on the response\n+\t} else {\n+\t\tws.Route(getRoute.Returns(http.StatusMethodNotAllowed, \"reading individual objects is not supported\", nil))\n+\t}\n+\n+\tupdateRoute := ws.PUT(path + \"/{name}\").To(restVerbHandler).\n+\t\tDoc(\"update the specified \" + kind).\n+\t\tOperation(\"update\" + kind).\n+\t\tParam(nameParam)\n+\taddParamIf(updateRoute, namespaceParam, namespaceScope)\n+\tif _, ok := storage.(RESTUpdater); ok {\n+\t\tws.Route(updateRoute.Reads(versionedObject)) // from the request\n+\t} else {\n+\t\tws.Route(updateRoute.Returns(http.StatusMethodNotAllowed, \"updating objects is not supported\", nil))\n+\t}\n+\n+\t// TODO: Support PATCH\n+\tdeleteRoute := ws.DELETE(path + \"/{name}\").To(restVerbHandler).\n+\t\tDoc(\"delete the specified \" + kind).\n+\t\tOperation(\"delete\" + kind).\n+\t\tParam(nameParam)\n+\taddParamIf(deleteRoute, namespaceParam, namespaceScope)\n+\tif _, ok := storage.(RESTDeleter); ok {\n+\t\tws.Route(deleteRoute)\n+\t} else {\n+\t\tws.Route(deleteRoute.Returns(http.StatusMethodNotAllowed, \"deleting objects is not supported\", nil))\n+\t}\n+\n+\t// Handlers for custom verbs.\n+\t// Note: update GetAttribs() when adding a handler.\n+\t// Watch.\n+\tif _, ok := storage.(ResourceWatcher); ok {\n+\t\t// Watch is supported on this resource.\n+\t\twatchKindRoute := ws.GET(\"/watch/\" + path).To(restfulStripPrefix(a.prefix+\"/watch\", watchHandler)).\n+\t\t\tDoc(\"watch \" + kind).\n+\t\t\tOperation(\"watch\" + kind)\n+\t\taddParamIf(watchKindRoute, namespaceParam, namespaceScope)\n+\t\tws.Route(watchKindRoute)\n+\n+\t\twatchNamedRoute := ws.GET(\"/watch/\" + path + \"/{name}\").To(restfulStripPrefix(a.prefix+\"/watch\", watchHandler)).\n+\t\t\tDoc(\"watch a particular \" + kind).\n+\t\t\tOperation(\"watchNamed\" + kind).\n+\t\t\tParam(nameParam)\n+\t\taddParamIf(watchNamedRoute, namespaceParam, namespaceScope)\n+\t\tws.Route(watchNamedRoute)\n+\t}\n+\n+\t// Redirect and proxy\n+\tif _, ok := storage.(Redirector); ok {\n+\t\t// Redirect and proxy are supported on this resource.\n+\t\tredirectRoute := ws.GET(\"/redirect/\" + path + \"/{name}\").To(restfulStripPrefix(a.prefix+\"/redirect\", redirectHandler)).\n+\t\t\tDoc(\"get the redirect URL for \" + kind).\n+\t\t\tOperation(\"redirect\" + kind).\n+\t\t\tParam(nameParam)\n+\t\taddParamIf(redirectRoute, namespaceParam, namespaceScope)\n+\t\tws.Route(redirectRoute)\n+\n+\t\t// Accept all methods as per https://github.com/GoogleCloudPlatform/kubernetes/issues/3996\n+\t\taddProxyRoute(ws, \"GET\", a.prefix, path, proxyHandler, kind, nameParam, namespaceParam, namespaceScope)\n+\t\taddProxyRoute(ws, \"PUT\", a.prefix, path, proxyHandler, kind, nameParam, namespaceParam, namespaceScope)\n+\t\taddProxyRoute(ws, \"POST\", a.prefix, path, proxyHandler, kind, nameParam, namespaceParam, namespaceScope)\n+\t\taddProxyRoute(ws, \"DELETE\", a.prefix, path, proxyHandler, kind, nameParam, namespaceParam, namespaceScope)\n+\t}\n+\n+\treturn nil\n+}\n+\n+// This magic incantation returns *ptrToObject for an arbitrary pointer\n+func indirectArbitraryPointer(ptrToObject interface{}) interface{} {\n+\treturn reflect.Indirect(reflect.ValueOf(ptrToObject)).Interface()\n+}\n+\n+// Adds the given param to the given route builder if shouldAdd is true. Does nothing if shouldAdd is false.\n+func addParamIf(b *restful.RouteBuilder, parameter *restful.Parameter, shouldAdd bool) *restful.RouteBuilder {\n+\tif !shouldAdd {\n+\t\treturn b\n+\t}\n+\treturn b.Param(parameter)\n+}\n+\n+// Returns a restful RouteFunction that calls the given handler after stripping prefix from the request path.\n+func restfulStripPrefix(prefix string, handler http.Handler) restful.RouteFunction {\n+\treturn func(restReq *restful.Request, restResp *restful.Response) {\n+\t\t//\thandler.ServeHTTP(restResp.ResponseWriter, restReq.Request)\n+\t\thttp.StripPrefix(prefix, handler).ServeHTTP(restResp.ResponseWriter, restReq.Request)\n+\t}\n+}\n+\n+func addProxyRoute(ws *restful.WebService, method string, prefix string, path string, proxyHandler http.Handler, kind string, nameParam *restful.Parameter, namespaceParam *restful.Parameter, namespaceScope bool) {\n+\tproxyRoute := ws.Method(method).Path(\"/proxy/\" + path + \"/{name}/{*}\").To(restfulStripPrefix(prefix+\"/proxy\", proxyHandler)).","path":"pkg/apiserver/api_installer.go","position":240,"original_position":240,"commit_id":"50708cc3ccab1844cffa7b7319fe598467d0acde","original_commit_id":"50708cc3ccab1844cffa7b7319fe598467d0acde","user":{"login":"bgrant0607","id":7725777,"avatar_url":"https://avatars.githubusercontent.com/u/7725777?v=3","gravatar_id":"","url":"https://api.github.com/users/bgrant0607","html_url":"https://github.com/bgrant0607","followers_url":"https://api.github.com/users/bgrant0607/followers","following_url":"https://api.github.com/users/bgrant0607/following{/other_user}","gists_url":"https://api.github.com/users/bgrant0607/gists{/gist_id}","starred_url":"https://api.github.com/users/bgrant0607/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bgrant0607/subscriptions","organizations_url":"https://api.github.com/users/bgrant0607/orgs","repos_url":"https://api.github.com/users/bgrant0607/repos","events_url":"https://api.github.com/users/bgrant0607/events{/privacy}","received_events_url":"https://api.github.com/users/bgrant0607/received_events","type":"User","site_admin":false},"body":"What does the swagger for this look like? Please add an identifier to the trailing subpath, such as `{path:*}`.\r\n\r\nAre you sure that the default router doesn't work for such paths? I know the test and examples use the curly router, but it looks like the path tokenization is actually in common code rather than in the routers.\r\nhttps://github.com/emicklei/go-restful/blob/master/route.go#L113\r\n\r\nI've come to the conclusion that proxy and redirect aren't really part of the API, but are convenience functions provided by the apiserver. However, since the do need to be registered on a per-object basis, and we do need some kind of documentation for them, I can see the rationale for registering them with the other handlers.","created_at":"2015-02-03T06:43:05Z","updated_at":"2015-02-03T06:43:05Z","html_url":"https://github.com/GoogleCloudPlatform/kubernetes/pull/3999#discussion_r23985658","pull_request_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/pulls/3999","_links":{"self":{"href":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/pulls/comments/23985658"},"html":{"href":"https://github.com/GoogleCloudPlatform/kubernetes/pull/3999#discussion_r23985658"},"pull_request":{"href":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/pulls/3999"}}},"pull_request":{"url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/pulls/3999","id":28404301,"html_url":"https://github.com/GoogleCloudPlatform/kubernetes/pull/3999","diff_url":"https://github.com/GoogleCloudPlatform/kubernetes/pull/3999.diff","patch_url":"https://github.com/GoogleCloudPlatform/kubernetes/pull/3999.patch","issue_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/issues/3999","number":3999,"state":"open","locked":false,"title":"Moving /watch, /proxy and /redirect registrations to go-restful","user":{"login":"nikhiljindal","id":10199099,"avatar_url":"https://avatars.githubusercontent.com/u/10199099?v=3","gravatar_id":"","url":"https://api.github.com/users/nikhiljindal","html_url":"https://github.com/nikhiljindal","followers_url":"https://api.github.com/users/nikhiljindal/followers","following_url":"https://api.github.com/users/nikhiljindal/following{/other_user}","gists_url":"https://api.github.com/users/nikhiljindal/gists{/gist_id}","starred_url":"https://api.github.com/users/nikhiljindal/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nikhiljindal/subscriptions","organizations_url":"https://api.github.com/users/nikhiljindal/orgs","repos_url":"https://api.github.com/users/nikhiljindal/repos","events_url":"https://api.github.com/users/nikhiljindal/events{/privacy}","received_events_url":"https://api.github.com/users/nikhiljindal/received_events","type":"User","site_admin":false},"body":"Have moved apiserver.InstallRest code to a separate api_installer file.","created_at":"2015-01-31T00:16:29Z","updated_at":"2015-02-03T06:43:05Z","closed_at":null,"merged_at":null,"merge_commit_sha":"7b1ba82dfd6148f467f87083b80fdebc633fdd34","assignee":{"login":"bgrant0607","id":7725777,"avatar_url":"https://avatars.githubusercontent.com/u/7725777?v=3","gravatar_id":"","url":"https://api.github.com/users/bgrant0607","html_url":"https://github.com/bgrant0607","followers_url":"https://api.github.com/users/bgrant0607/followers","following_url":"https://api.github.com/users/bgrant0607/following{/other_user}","gists_url":"https://api.github.com/users/bgrant0607/gists{/gist_id}","starred_url":"https://api.github.com/users/bgrant0607/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bgrant0607/subscriptions","organizations_url":"https://api.github.com/users/bgrant0607/orgs","repos_url":"https://api.github.com/users/bgrant0607/repos","events_url":"https://api.github.com/users/bgrant0607/events{/privacy}","received_events_url":"https://api.github.com/users/bgrant0607/received_events","type":"User","site_admin":false},"milestone":null,"commits_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/pulls/3999/commits","review_comments_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/pulls/3999/comments","review_comment_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/pulls/comments/{number}","comments_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/issues/3999/comments","statuses_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/statuses/50708cc3ccab1844cffa7b7319fe598467d0acde","head":{"label":"nikhiljindal:go-restful","ref":"go-restful","sha":"50708cc3ccab1844cffa7b7319fe598467d0acde","user":{"login":"nikhiljindal","id":10199099,"avatar_url":"https://avatars.githubusercontent.com/u/10199099?v=3","gravatar_id":"","url":"https://api.github.com/users/nikhiljindal","html_url":"https://github.com/nikhiljindal","followers_url":"https://api.github.com/users/nikhiljindal/followers","following_url":"https://api.github.com/users/nikhiljindal/following{/other_user}","gists_url":"https://api.github.com/users/nikhiljindal/gists{/gist_id}","starred_url":"https://api.github.com/users/nikhiljindal/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nikhiljindal/subscriptions","organizations_url":"https://api.github.com/users/nikhiljindal/orgs","repos_url":"https://api.github.com/users/nikhiljindal/repos","events_url":"https://api.github.com/users/nikhiljindal/events{/privacy}","received_events_url":"https://api.github.com/users/nikhiljindal/received_events","type":"User","site_admin":false},"repo":{"id":29988055,"name":"kubernetes","full_name":"nikhiljindal/kubernetes","owner":{"login":"nikhiljindal","id":10199099,"avatar_url":"https://avatars.githubusercontent.com/u/10199099?v=3","gravatar_id":"","url":"https://api.github.com/users/nikhiljindal","html_url":"https://github.com/nikhiljindal","followers_url":"https://api.github.com/users/nikhiljindal/followers","following_url":"https://api.github.com/users/nikhiljindal/following{/other_user}","gists_url":"https://api.github.com/users/nikhiljindal/gists{/gist_id}","starred_url":"https://api.github.com/users/nikhiljindal/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nikhiljindal/subscriptions","organizations_url":"https://api.github.com/users/nikhiljindal/orgs","repos_url":"https://api.github.com/users/nikhiljindal/repos","events_url":"https://api.github.com/users/nikhiljindal/events{/privacy}","received_events_url":"https://api.github.com/users/nikhiljindal/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/nikhiljindal/kubernetes","description":"Container Cluster Manager","fork":true,"url":"https://api.github.com/repos/nikhiljindal/kubernetes","forks_url":"https://api.github.com/repos/nikhiljindal/kubernetes/forks","keys_url":"https://api.github.com/repos/nikhiljindal/kubernetes/keys{/key_id}","collaborators_url":"https://api.github.com/repos/nikhiljindal/kubernetes/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/nikhiljindal/kubernetes/teams","hooks_url":"https://api.github.com/repos/nikhiljindal/kubernetes/hooks","issue_events_url":"https://api.github.com/repos/nikhiljindal/kubernetes/issues/events{/number}","events_url":"https://api.github.com/repos/nikhiljindal/kubernetes/events","assignees_url":"https://api.github.com/repos/nikhiljindal/kubernetes/assignees{/user}","branches_url":"https://api.github.com/repos/nikhiljindal/kubernetes/branches{/branch}","tags_url":"https://api.github.com/repos/nikhiljindal/kubernetes/tags","blobs_url":"https://api.github.com/repos/nikhiljindal/kubernetes/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/nikhiljindal/kubernetes/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/nikhiljindal/kubernetes/git/refs{/sha}","trees_url":"https://api.github.com/repos/nikhiljindal/kubernetes/git/trees{/sha}","statuses_url":"https://api.github.com/repos/nikhiljindal/kubernetes/statuses/{sha}","languages_url":"https://api.github.com/repos/nikhiljindal/kubernetes/languages","stargazers_url":"https://api.github.com/repos/nikhiljindal/kubernetes/stargazers","contributors_url":"https://api.github.com/repos/nikhiljindal/kubernetes/contributors","subscribers_url":"https://api.github.com/repos/nikhiljindal/kubernetes/subscribers","subscription_url":"https://api.github.com/repos/nikhiljindal/kubernetes/subscription","commits_url":"https://api.github.com/repos/nikhiljindal/kubernetes/commits{/sha}","git_commits_url":"https://api.github.com/repos/nikhiljindal/kubernetes/git/commits{/sha}","comments_url":"https://api.github.com/repos/nikhiljindal/kubernetes/comments{/number}","issue_comment_url":"https://api.github.com/repos/nikhiljindal/kubernetes/issues/comments/{number}","contents_url":"https://api.github.com/repos/nikhiljindal/kubernetes/contents/{+path}","compare_url":"https://api.github.com/repos/nikhiljindal/kubernetes/compare/{base}...{head}","merges_url":"https://api.github.com/repos/nikhiljindal/kubernetes/merges","archive_url":"https://api.github.com/repos/nikhiljindal/kubernetes/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/nikhiljindal/kubernetes/downloads","issues_url":"https://api.github.com/repos/nikhiljindal/kubernetes/issues{/number}","pulls_url":"https://api.github.com/repos/nikhiljindal/kubernetes/pulls{/number}","milestones_url":"https://api.github.com/repos/nikhiljindal/kubernetes/milestones{/number}","notifications_url":"https://api.github.com/repos/nikhiljindal/kubernetes/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/nikhiljindal/kubernetes/labels{/name}","releases_url":"https://api.github.com/repos/nikhiljindal/kubernetes/releases{/id}","created_at":"2015-01-28T21:01:50Z","updated_at":"2015-01-28T21:01:53Z","pushed_at":"2015-01-31T00:56:06Z","git_url":"git://github.com/nikhiljindal/kubernetes.git","ssh_url":"git@github.com:nikhiljindal/kubernetes.git","clone_url":"https://github.com/nikhiljindal/kubernetes.git","svn_url":"https://github.com/nikhiljindal/kubernetes","homepage":"http://kubernetes.io","size":25990,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"GoogleCloudPlatform:master","ref":"master","sha":"af25c3c671d592bf8643d65d24fb8b37b3aec994","user":{"login":"GoogleCloudPlatform","id":2810941,"avatar_url":"https://avatars.githubusercontent.com/u/2810941?v=3","gravatar_id":"","url":"https://api.github.com/users/GoogleCloudPlatform","html_url":"https://github.com/GoogleCloudPlatform","followers_url":"https://api.github.com/users/GoogleCloudPlatform/followers","following_url":"https://api.github.com/users/GoogleCloudPlatform/following{/other_user}","gists_url":"https://api.github.com/users/GoogleCloudPlatform/gists{/gist_id}","starred_url":"https://api.github.com/users/GoogleCloudPlatform/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/GoogleCloudPlatform/subscriptions","organizations_url":"https://api.github.com/users/GoogleCloudPlatform/orgs","repos_url":"https://api.github.com/users/GoogleCloudPlatform/repos","events_url":"https://api.github.com/users/GoogleCloudPlatform/events{/privacy}","received_events_url":"https://api.github.com/users/GoogleCloudPlatform/received_events","type":"Organization","site_admin":false},"repo":{"id":20580498,"name":"kubernetes","full_name":"GoogleCloudPlatform/kubernetes","owner":{"login":"GoogleCloudPlatform","id":2810941,"avatar_url":"https://avatars.githubusercontent.com/u/2810941?v=3","gravatar_id":"","url":"https://api.github.com/users/GoogleCloudPlatform","html_url":"https://github.com/GoogleCloudPlatform","followers_url":"https://api.github.com/users/GoogleCloudPlatform/followers","following_url":"https://api.github.com/users/GoogleCloudPlatform/following{/other_user}","gists_url":"https://api.github.com/users/GoogleCloudPlatform/gists{/gist_id}","starred_url":"https://api.github.com/users/GoogleCloudPlatform/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/GoogleCloudPlatform/subscriptions","organizations_url":"https://api.github.com/users/GoogleCloudPlatform/orgs","repos_url":"https://api.github.com/users/GoogleCloudPlatform/repos","events_url":"https://api.github.com/users/GoogleCloudPlatform/events{/privacy}","received_events_url":"https://api.github.com/users/GoogleCloudPlatform/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/GoogleCloudPlatform/kubernetes","description":"Container Cluster Manager","fork":false,"url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes","forks_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/forks","keys_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/keys{/key_id}","collaborators_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/teams","hooks_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/hooks","issue_events_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/issues/events{/number}","events_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/events","assignees_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/assignees{/user}","branches_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/branches{/branch}","tags_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/tags","blobs_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/git/refs{/sha}","trees_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/git/trees{/sha}","statuses_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/statuses/{sha}","languages_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/languages","stargazers_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/stargazers","contributors_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/contributors","subscribers_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/subscribers","subscription_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/subscription","commits_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/commits{/sha}","git_commits_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/git/commits{/sha}","comments_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/comments{/number}","issue_comment_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/issues/comments/{number}","contents_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/contents/{+path}","compare_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/compare/{base}...{head}","merges_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/merges","archive_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/downloads","issues_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/issues{/number}","pulls_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/pulls{/number}","milestones_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/milestones{/number}","notifications_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/labels{/name}","releases_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/releases{/id}","created_at":"2014-06-06T22:56:04Z","updated_at":"2015-02-03T06:27:00Z","pushed_at":"2015-02-03T02:58:49Z","git_url":"git://github.com/GoogleCloudPlatform/kubernetes.git","ssh_url":"git@github.com:GoogleCloudPlatform/kubernetes.git","clone_url":"https://github.com/GoogleCloudPlatform/kubernetes.git","svn_url":"https://github.com/GoogleCloudPlatform/kubernetes","homepage":"http://kubernetes.io","size":66003,"stargazers_count":6040,"watchers_count":6040,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":1020,"mirror_url":null,"open_issues_count":648,"forks":1020,"open_issues":648,"watchers":6040,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/pulls/3999"},"html":{"href":"https://github.com/GoogleCloudPlatform/kubernetes/pull/3999"},"issue":{"href":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/issues/3999"},"comments":{"href":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/issues/3999/comments"},"review_comments":{"href":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/pulls/3999/comments"},"review_comment":{"href":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/pulls/3999/commits"},"statuses":{"href":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/statuses/50708cc3ccab1844cffa7b7319fe598467d0acde"}}}}