{"action":"created","comment":{"url":"https://api.github.com/repos/BuoyantIO/linkerd/pulls/comments/58906367","id":58906367,"diff_hunk":"@@ -0,0 +1,176 @@\n+package io.buoyant.k8s\n+\n+import com.fasterxml.jackson.annotation.JsonIgnore\n+import com.twitter.finagle.http\n+import com.twitter.io.{Buf, Reader}\n+import com.twitter.util._\n+\n+/**\n+ * Contains various classes and methods useful for interacting with the Kubernetes API.\n+ */\n+object Api {\n+  val BufSize = 8 * 1024\n+\n+  object Closed extends Throwable\n+  case class UnexpectedResponse(rsp: http.Response) extends Throwable\n+  /**\n+   * Represents an HTTP 409 Conflict response, returned by the k8s API when attempting to update a resource with\n+   * an out-of-date resource version or when attempting to create a resource at an existing name.\n+   */\n+  case class Conflict(rsp: http.Response) extends Throwable\n+  case class NotFound(rsp: http.Response) extends Throwable\n+\n+  private[k8s] def mkreq(\n+    method: http.Method,\n+    path: String,\n+    content: Option[Buf],\n+    optParams: (String, Option[String])*\n+  ): http.Request = {\n+    val params = optParams collect { case (k, Some(v)) => (k, v) }\n+    val req = http.Request(path, params: _*)\n+    req.method = method\n+    req.contentType = \"application/json\"\n+    content.foreach(req.content = _)\n+    req\n+  }\n+\n+  private[k8s] def dechunk(reader: Reader, init: Buf = Buf.Empty): Future[Buf] =\n+    reader.read(BufSize) flatMap {\n+      case Some(chunk) =>\n+        dechunk(reader, init.concat(chunk))\n+      case None =>\n+        Future.value(init)\n+    }\n+\n+  private[k8s] def getContent(msg: http.Message): Future[Buf] =\n+    msg.headerMap.get(\"transfer-encoding\") match {\n+      case Some(\"chunked\") => dechunk(msg.reader)\n+      case _ => Future.value(msg.content)\n+    }\n+\n+  private[k8s] def parse[T: Manifest](rsp: http.Response): Future[T] =\n+    getContent(rsp) flatMap { content =>\n+      Future.const(Json.read[T](content))\n+    }\n+}\n+\n+/**\n+ * Generally required as an implicit for list resources. Provides the kubernetes-designated\n+ * name for the resource, as well as a means of transforming an individual instance into a type-specialized\n+ * Watch.\n+ */\n+trait ObjectDescriptor[O <: Object, W <: Watch[O]] {\n+  /**\n+   * @return the URI path segment used for serving lists of resources of type O, e.g. \"endpoints\", \"configmaps\".\n+   */\n+  def listName: String\n+\n+  /**\n+   *\n+   * @param o a current object instance\n+   * @return a Watch (usually Watch.Modified) wrapping `o`\n+   */\n+  def toWatch(o: O): W\n+}\n+\n+/**\n+ * Describes an object in the Kubernetes API (i.e. http://kubernetes.io/docs/api-reference/v1/definitions/#_v1_endpoints)\n+ */\n+trait Object {","path":"k8s/src/main/scala/io/buoyant/k8s/Api.scala","position":79,"original_position":79,"commit_id":"bdcf45a009609d392bdc9aeb2919815fe00e5a82","original_commit_id":"bdcf45a009609d392bdc9aeb2919815fe00e5a82","user":{"login":"adleong","id":3979810,"avatar_url":"https://avatars.githubusercontent.com/u/3979810?v=3","gravatar_id":"","url":"https://api.github.com/users/adleong","html_url":"https://github.com/adleong","followers_url":"https://api.github.com/users/adleong/followers","following_url":"https://api.github.com/users/adleong/following{/other_user}","gists_url":"https://api.github.com/users/adleong/gists{/gist_id}","starred_url":"https://api.github.com/users/adleong/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/adleong/subscriptions","organizations_url":"https://api.github.com/users/adleong/orgs","repos_url":"https://api.github.com/users/adleong/repos","events_url":"https://api.github.com/users/adleong/events{/privacy}","received_events_url":"https://api.github.com/users/adleong/received_events","type":"User","site_admin":false},"body":"maybe rename to not conflict with `java.lang.Object`","created_at":"2016-04-07T16:56:23Z","updated_at":"2016-04-07T16:56:23Z","html_url":"https://github.com/BuoyantIO/linkerd/pull/247#discussion_r58906367","pull_request_url":"https://api.github.com/repos/BuoyantIO/linkerd/pulls/247","_links":{"self":{"href":"https://api.github.com/repos/BuoyantIO/linkerd/pulls/comments/58906367"},"html":{"href":"https://github.com/BuoyantIO/linkerd/pull/247#discussion_r58906367"},"pull_request":{"href":"https://api.github.com/repos/BuoyantIO/linkerd/pulls/247"}}},"pull_request":{"url":"https://api.github.com/repos/BuoyantIO/linkerd/pulls/247","id":65575082,"html_url":"https://github.com/BuoyantIO/linkerd/pull/247","diff_url":"https://github.com/BuoyantIO/linkerd/pull/247.diff","patch_url":"https://github.com/BuoyantIO/linkerd/pull/247.patch","issue_url":"https://api.github.com/repos/BuoyantIO/linkerd/issues/247","number":247,"state":"open","locked":false,"title":"Implement namerd storage using the Kubernetes ThirdPartyResource APIs.","user":{"login":"gtcampbell","id":14003771,"avatar_url":"https://avatars.githubusercontent.com/u/14003771?v=3","gravatar_id":"","url":"https://api.github.com/users/gtcampbell","html_url":"https://github.com/gtcampbell","followers_url":"https://api.github.com/users/gtcampbell/followers","following_url":"https://api.github.com/users/gtcampbell/following{/other_user}","gists_url":"https://api.github.com/users/gtcampbell/gists{/gist_id}","starred_url":"https://api.github.com/users/gtcampbell/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gtcampbell/subscriptions","organizations_url":"https://api.github.com/users/gtcampbell/orgs","repos_url":"https://api.github.com/users/gtcampbell/repos","events_url":"https://api.github.com/users/gtcampbell/events{/privacy}","received_events_url":"https://api.github.com/users/gtcampbell/received_events","type":"User","site_admin":false},"body":"Fixes #219. I have split this into two commits, and could split further or split into multiple pull requests if needed. I have performed a decent amount of manual testing on this, but suggestions on proper automated tests would be appreciated!","created_at":"2016-04-07T05:15:42Z","updated_at":"2016-04-07T16:56:23Z","closed_at":null,"merged_at":null,"merge_commit_sha":"7a26cb45337af463c07face9c9d697da7123e330","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/BuoyantIO/linkerd/pulls/247/commits","review_comments_url":"https://api.github.com/repos/BuoyantIO/linkerd/pulls/247/comments","review_comment_url":"https://api.github.com/repos/BuoyantIO/linkerd/pulls/comments{/number}","comments_url":"https://api.github.com/repos/BuoyantIO/linkerd/issues/247/comments","statuses_url":"https://api.github.com/repos/BuoyantIO/linkerd/statuses/bdcf45a009609d392bdc9aeb2919815fe00e5a82","head":{"label":"BuoyantIO:greg/k8s3p+namer","ref":"greg/k8s3p+namer","sha":"bdcf45a009609d392bdc9aeb2919815fe00e5a82","user":{"login":"BuoyantIO","id":10824329,"avatar_url":"https://avatars.githubusercontent.com/u/10824329?v=3","gravatar_id":"","url":"https://api.github.com/users/BuoyantIO","html_url":"https://github.com/BuoyantIO","followers_url":"https://api.github.com/users/BuoyantIO/followers","following_url":"https://api.github.com/users/BuoyantIO/following{/other_user}","gists_url":"https://api.github.com/users/BuoyantIO/gists{/gist_id}","starred_url":"https://api.github.com/users/BuoyantIO/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/BuoyantIO/subscriptions","organizations_url":"https://api.github.com/users/BuoyantIO/orgs","repos_url":"https://api.github.com/users/BuoyantIO/repos","events_url":"https://api.github.com/users/BuoyantIO/events{/privacy}","received_events_url":"https://api.github.com/users/BuoyantIO/received_events","type":"Organization","site_admin":false},"repo":{"id":49605596,"name":"linkerd","full_name":"BuoyantIO/linkerd","owner":{"login":"BuoyantIO","id":10824329,"avatar_url":"https://avatars.githubusercontent.com/u/10824329?v=3","gravatar_id":"","url":"https://api.github.com/users/BuoyantIO","html_url":"https://github.com/BuoyantIO","followers_url":"https://api.github.com/users/BuoyantIO/followers","following_url":"https://api.github.com/users/BuoyantIO/following{/other_user}","gists_url":"https://api.github.com/users/BuoyantIO/gists{/gist_id}","starred_url":"https://api.github.com/users/BuoyantIO/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/BuoyantIO/subscriptions","organizations_url":"https://api.github.com/users/BuoyantIO/orgs","repos_url":"https://api.github.com/users/BuoyantIO/repos","events_url":"https://api.github.com/users/BuoyantIO/events{/privacy}","received_events_url":"https://api.github.com/users/BuoyantIO/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/BuoyantIO/linkerd","description":"A dynamic linker for microservices.","fork":false,"url":"https://api.github.com/repos/BuoyantIO/linkerd","forks_url":"https://api.github.com/repos/BuoyantIO/linkerd/forks","keys_url":"https://api.github.com/repos/BuoyantIO/linkerd/keys{/key_id}","collaborators_url":"https://api.github.com/repos/BuoyantIO/linkerd/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/BuoyantIO/linkerd/teams","hooks_url":"https://api.github.com/repos/BuoyantIO/linkerd/hooks","issue_events_url":"https://api.github.com/repos/BuoyantIO/linkerd/issues/events{/number}","events_url":"https://api.github.com/repos/BuoyantIO/linkerd/events","assignees_url":"https://api.github.com/repos/BuoyantIO/linkerd/assignees{/user}","branches_url":"https://api.github.com/repos/BuoyantIO/linkerd/branches{/branch}","tags_url":"https://api.github.com/repos/BuoyantIO/linkerd/tags","blobs_url":"https://api.github.com/repos/BuoyantIO/linkerd/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/BuoyantIO/linkerd/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/BuoyantIO/linkerd/git/refs{/sha}","trees_url":"https://api.github.com/repos/BuoyantIO/linkerd/git/trees{/sha}","statuses_url":"https://api.github.com/repos/BuoyantIO/linkerd/statuses/{sha}","languages_url":"https://api.github.com/repos/BuoyantIO/linkerd/languages","stargazers_url":"https://api.github.com/repos/BuoyantIO/linkerd/stargazers","contributors_url":"https://api.github.com/repos/BuoyantIO/linkerd/contributors","subscribers_url":"https://api.github.com/repos/BuoyantIO/linkerd/subscribers","subscription_url":"https://api.github.com/repos/BuoyantIO/linkerd/subscription","commits_url":"https://api.github.com/repos/BuoyantIO/linkerd/commits{/sha}","git_commits_url":"https://api.github.com/repos/BuoyantIO/linkerd/git/commits{/sha}","comments_url":"https://api.github.com/repos/BuoyantIO/linkerd/comments{/number}","issue_comment_url":"https://api.github.com/repos/BuoyantIO/linkerd/issues/comments{/number}","contents_url":"https://api.github.com/repos/BuoyantIO/linkerd/contents/{+path}","compare_url":"https://api.github.com/repos/BuoyantIO/linkerd/compare/{base}...{head}","merges_url":"https://api.github.com/repos/BuoyantIO/linkerd/merges","archive_url":"https://api.github.com/repos/BuoyantIO/linkerd/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/BuoyantIO/linkerd/downloads","issues_url":"https://api.github.com/repos/BuoyantIO/linkerd/issues{/number}","pulls_url":"https://api.github.com/repos/BuoyantIO/linkerd/pulls{/number}","milestones_url":"https://api.github.com/repos/BuoyantIO/linkerd/milestones{/number}","notifications_url":"https://api.github.com/repos/BuoyantIO/linkerd/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/BuoyantIO/linkerd/labels{/name}","releases_url":"https://api.github.com/repos/BuoyantIO/linkerd/releases{/id}","deployments_url":"https://api.github.com/repos/BuoyantIO/linkerd/deployments","created_at":"2016-01-13T22:14:52Z","updated_at":"2016-04-07T01:18:00Z","pushed_at":"2016-04-07T16:13:09Z","git_url":"git://github.com/BuoyantIO/linkerd.git","ssh_url":"git@github.com:BuoyantIO/linkerd.git","clone_url":"https://github.com/BuoyantIO/linkerd.git","svn_url":"https://github.com/BuoyantIO/linkerd","homepage":"https://linkerd.io","size":1101,"stargazers_count":562,"watchers_count":562,"language":"Scala","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":26,"mirror_url":null,"open_issues_count":43,"forks":26,"open_issues":43,"watchers":562,"default_branch":"master"}},"base":{"label":"BuoyantIO:master","ref":"master","sha":"cb4fd1ae97905177f3d739ca1f31285d5a44c2bd","user":{"login":"BuoyantIO","id":10824329,"avatar_url":"https://avatars.githubusercontent.com/u/10824329?v=3","gravatar_id":"","url":"https://api.github.com/users/BuoyantIO","html_url":"https://github.com/BuoyantIO","followers_url":"https://api.github.com/users/BuoyantIO/followers","following_url":"https://api.github.com/users/BuoyantIO/following{/other_user}","gists_url":"https://api.github.com/users/BuoyantIO/gists{/gist_id}","starred_url":"https://api.github.com/users/BuoyantIO/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/BuoyantIO/subscriptions","organizations_url":"https://api.github.com/users/BuoyantIO/orgs","repos_url":"https://api.github.com/users/BuoyantIO/repos","events_url":"https://api.github.com/users/BuoyantIO/events{/privacy}","received_events_url":"https://api.github.com/users/BuoyantIO/received_events","type":"Organization","site_admin":false},"repo":{"id":49605596,"name":"linkerd","full_name":"BuoyantIO/linkerd","owner":{"login":"BuoyantIO","id":10824329,"avatar_url":"https://avatars.githubusercontent.com/u/10824329?v=3","gravatar_id":"","url":"https://api.github.com/users/BuoyantIO","html_url":"https://github.com/BuoyantIO","followers_url":"https://api.github.com/users/BuoyantIO/followers","following_url":"https://api.github.com/users/BuoyantIO/following{/other_user}","gists_url":"https://api.github.com/users/BuoyantIO/gists{/gist_id}","starred_url":"https://api.github.com/users/BuoyantIO/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/BuoyantIO/subscriptions","organizations_url":"https://api.github.com/users/BuoyantIO/orgs","repos_url":"https://api.github.com/users/BuoyantIO/repos","events_url":"https://api.github.com/users/BuoyantIO/events{/privacy}","received_events_url":"https://api.github.com/users/BuoyantIO/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/BuoyantIO/linkerd","description":"A dynamic linker for microservices.","fork":false,"url":"https://api.github.com/repos/BuoyantIO/linkerd","forks_url":"https://api.github.com/repos/BuoyantIO/linkerd/forks","keys_url":"https://api.github.com/repos/BuoyantIO/linkerd/keys{/key_id}","collaborators_url":"https://api.github.com/repos/BuoyantIO/linkerd/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/BuoyantIO/linkerd/teams","hooks_url":"https://api.github.com/repos/BuoyantIO/linkerd/hooks","issue_events_url":"https://api.github.com/repos/BuoyantIO/linkerd/issues/events{/number}","events_url":"https://api.github.com/repos/BuoyantIO/linkerd/events","assignees_url":"https://api.github.com/repos/BuoyantIO/linkerd/assignees{/user}","branches_url":"https://api.github.com/repos/BuoyantIO/linkerd/branches{/branch}","tags_url":"https://api.github.com/repos/BuoyantIO/linkerd/tags","blobs_url":"https://api.github.com/repos/BuoyantIO/linkerd/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/BuoyantIO/linkerd/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/BuoyantIO/linkerd/git/refs{/sha}","trees_url":"https://api.github.com/repos/BuoyantIO/linkerd/git/trees{/sha}","statuses_url":"https://api.github.com/repos/BuoyantIO/linkerd/statuses/{sha}","languages_url":"https://api.github.com/repos/BuoyantIO/linkerd/languages","stargazers_url":"https://api.github.com/repos/BuoyantIO/linkerd/stargazers","contributors_url":"https://api.github.com/repos/BuoyantIO/linkerd/contributors","subscribers_url":"https://api.github.com/repos/BuoyantIO/linkerd/subscribers","subscription_url":"https://api.github.com/repos/BuoyantIO/linkerd/subscription","commits_url":"https://api.github.com/repos/BuoyantIO/linkerd/commits{/sha}","git_commits_url":"https://api.github.com/repos/BuoyantIO/linkerd/git/commits{/sha}","comments_url":"https://api.github.com/repos/BuoyantIO/linkerd/comments{/number}","issue_comment_url":"https://api.github.com/repos/BuoyantIO/linkerd/issues/comments{/number}","contents_url":"https://api.github.com/repos/BuoyantIO/linkerd/contents/{+path}","compare_url":"https://api.github.com/repos/BuoyantIO/linkerd/compare/{base}...{head}","merges_url":"https://api.github.com/repos/BuoyantIO/linkerd/merges","archive_url":"https://api.github.com/repos/BuoyantIO/linkerd/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/BuoyantIO/linkerd/downloads","issues_url":"https://api.github.com/repos/BuoyantIO/linkerd/issues{/number}","pulls_url":"https://api.github.com/repos/BuoyantIO/linkerd/pulls{/number}","milestones_url":"https://api.github.com/repos/BuoyantIO/linkerd/milestones{/number}","notifications_url":"https://api.github.com/repos/BuoyantIO/linkerd/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/BuoyantIO/linkerd/labels{/name}","releases_url":"https://api.github.com/repos/BuoyantIO/linkerd/releases{/id}","deployments_url":"https://api.github.com/repos/BuoyantIO/linkerd/deployments","created_at":"2016-01-13T22:14:52Z","updated_at":"2016-04-07T01:18:00Z","pushed_at":"2016-04-07T16:13:09Z","git_url":"git://github.com/BuoyantIO/linkerd.git","ssh_url":"git@github.com:BuoyantIO/linkerd.git","clone_url":"https://github.com/BuoyantIO/linkerd.git","svn_url":"https://github.com/BuoyantIO/linkerd","homepage":"https://linkerd.io","size":1101,"stargazers_count":562,"watchers_count":562,"language":"Scala","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":26,"mirror_url":null,"open_issues_count":43,"forks":26,"open_issues":43,"watchers":562,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/BuoyantIO/linkerd/pulls/247"},"html":{"href":"https://github.com/BuoyantIO/linkerd/pull/247"},"issue":{"href":"https://api.github.com/repos/BuoyantIO/linkerd/issues/247"},"comments":{"href":"https://api.github.com/repos/BuoyantIO/linkerd/issues/247/comments"},"review_comments":{"href":"https://api.github.com/repos/BuoyantIO/linkerd/pulls/247/comments"},"review_comment":{"href":"https://api.github.com/repos/BuoyantIO/linkerd/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/BuoyantIO/linkerd/pulls/247/commits"},"statuses":{"href":"https://api.github.com/repos/BuoyantIO/linkerd/statuses/bdcf45a009609d392bdc9aeb2919815fe00e5a82"}}}}