{"action":"created","comment":{"url":"https://api.github.com/repos/mesosphere/cassandra-mesos/pulls/comments/26290728","id":26290728,"diff_hunk":"@@ -0,0 +1,412 @@\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+package io.mesosphere.mesos.frameworks.cassandra;\n+\n+import org.apache.mesos.state.InMemoryState;\n+import org.apache.mesos.state.State;\n+import org.junit.Test;\n+\n+import static org.assertj.core.api.Assertions.*;\n+import static org.junit.Assert.*;\n+\n+public class PersistedCassandraClusterHealthCheckHistoryTest {\n+\n+    @Test\n+    public void testRecord() throws Exception {\n+        State state = new InMemoryState();\n+        PersistedCassandraClusterHealthCheckHistory hcHistory = new PersistedCassandraClusterHealthCheckHistory(state);\n+\n+        String exec1 = \"exec1\";\n+\n+        CassandraFrameworkProtos.NodeInfo.Builder ni = CassandraFrameworkProtos.NodeInfo.newBuilder()\n+            .setClusterName(\"cluster\")\n+            .setDataCenter(\"dc1\")\n+            .setUptimeMillis(1);\n+        CassandraFrameworkProtos.HealthCheckDetails.Builder hc = CassandraFrameworkProtos.HealthCheckDetails.newBuilder()\n+            .setHealthy(true)\n+            .setInfo(ni.build());\n+        hcHistory.record(exec1, 1L, hc.build());\n+\n+        CassandraFrameworkProtos.HealthCheckHistoryEntry hce1 = hcHistory.last(exec1);\n+        assertNotNull(hce1);\n+        assertThat(hcHistory.entries())\n+            .hasSize(1)\n+            .contains(hce1);\n+        assertThat(hcHistory.entriesForExecutor(exec1))\n+            .hasSize(1)\n+            .contains(hce1);\n+        assertEquals(1L, hce1.getTimestampFirst());\n+        assertEquals(1L, hce1.getTimestampLast());\n+\n+        // just increase uptime\n+        hc.setInfo(ni\n+            .setUptimeMillis(2)\n+            .build());\n+        hcHistory.record(exec1, 2L, hc.build());\n+\n+        CassandraFrameworkProtos.HealthCheckHistoryEntry hce2 = hcHistory.last(exec1);\n+        assertNotNull(hce2);\n+        assertThat(hcHistory.entries())\n+            .hasSize(1)\n+            .contains(hce2);\n+        assertThat(hcHistory.entriesForExecutor(exec1))\n+            .hasSize(1)\n+            .contains(hce2);\n+        assertEquals(1L, hce2.getTimestampFirst());\n+        assertEquals(2L, hce2.getTimestampLast());\n+\n+        // toggle a field\n+        hc.setInfo(ni\n+            .setNativeTransportRunning(true)\n+            .build());\n+        hcHistory.record(exec1, 3L, hc.build());\n+\n+        CassandraFrameworkProtos.HealthCheckHistoryEntry hce3 = hcHistory.last(exec1);\n+        assertNotNull(hce3);\n+        assertThat(hcHistory.entries())\n+            .hasSize(2)\n+            .contains(hce2)\n+            .contains(hce3);\n+        assertThat(hcHistory.entriesForExecutor(exec1))\n+            .hasSize(2)\n+            .contains(hce2)\n+            .contains(hce3);\n+        assertEquals(3L, hce3.getTimestampFirst());\n+        assertEquals(3L, hce3.getTimestampLast());\n+\n+        // toggle more fields and record\n+        hc.setInfo(ni\n+            .setNativeTransportRunning(false)\n+            .setRpcServerRunning(true)\n+            .build());\n+        hcHistory.record(exec1, 4L, hc.build());\n+        CassandraFrameworkProtos.HealthCheckHistoryEntry hce4 = hcHistory.last(exec1);\n+        assertThat(hcHistory.entries()).hasSize(3);\n+\n+        hc.setInfo(ni\n+            .setNativeTransportRunning(true)\n+            .setRpcServerRunning(true)\n+            .build());\n+        hcHistory.record(exec1, 5L, hc.build());\n+        CassandraFrameworkProtos.HealthCheckHistoryEntry hce5 = hcHistory.last(exec1);\n+        assertThat(hcHistory.entries()).hasSize(4);\n+        assertThat(hcHistory.entriesForExecutor(exec1))\n+            .hasSize(4)\n+            .contains(hce2)\n+            .contains(hce3)\n+            .contains(hce4)\n+            .contains(hce5);\n+\n+        hc.setHealthy(true)\n+            .setMsg(\"msg\");\n+        hcHistory.record(exec1, 6L, hc.build());\n+        CassandraFrameworkProtos.HealthCheckHistoryEntry hce6 = hcHistory.last(exec1);\n+        assertThat(hcHistory.entries()).hasSize(5);\n+        assertThat(hcHistory.entriesForExecutor(exec1))\n+            .hasSize(5)\n+            .contains(hce2)\n+            .contains(hce3)\n+            .contains(hce4)\n+            .contains(hce5)\n+            .contains(hce6);\n+\n+        hc.setHealthy(false)\n+            .setMsg(\"foo\");\n+        hcHistory.record(exec1, 7L, hc.build());\n+        CassandraFrameworkProtos.HealthCheckHistoryEntry hce7 = hcHistory.last(exec1);\n+        assertThat(hcHistory.entries()).hasSize(5);\n+        assertThat(hcHistory.entriesForExecutor(exec1))\n+            .hasSize(5)\n+            .doesNotContain(hce2)\n+            .contains(hce3)\n+            .contains(hce4)\n+            .contains(hce5)\n+            .contains(hce6)\n+            .contains(hce7);\n+\n+        hc.setHealthy(true)\n+            .clearMsg();\n+        hcHistory.record(exec1, 8L, hc.build());\n+        CassandraFrameworkProtos.HealthCheckHistoryEntry hce8 = hcHistory.last(exec1);\n+        assertThat(hcHistory.entries()).hasSize(5);\n+        assertThat(hcHistory.entriesForExecutor(exec1))\n+            .hasSize(5)\n+            .doesNotContain(hce2)\n+            .doesNotContain(hce3)\n+            .contains(hce4)\n+            .contains(hce5)\n+            .contains(hce6)\n+            .contains(hce7)\n+            .contains(hce8);\n+\n+        //\n+        // similar for another executor\n+        //\n+\n+        String exec2 = \"exec2\";\n+\n+        CassandraFrameworkProtos.NodeInfo.Builder otherNi = CassandraFrameworkProtos.NodeInfo.newBuilder()\n+            .setClusterName(\"cluster\")\n+            .setDataCenter(\"dc1\")\n+            .setUptimeMillis(1);\n+        CassandraFrameworkProtos.HealthCheckDetails.Builder otherHc = CassandraFrameworkProtos.HealthCheckDetails.newBuilder()\n+            .setHealthy(true)\n+            .setInfo(otherNi.build());\n+        hcHistory.record(exec2, 1L, otherHc.build());\n+\n+        CassandraFrameworkProtos.HealthCheckHistoryEntry otherHce1 = hcHistory.last(exec2);\n+        assertNotNull(otherHce1);\n+        assertThat(hcHistory.entries())\n+            .hasSize(6)\n+            .contains(otherHce1)\n+            //\n+            .doesNotContain(hce2)\n+            .doesNotContain(hce3)\n+            .contains(hce4)\n+            .contains(hce5)\n+            .contains(hce6)\n+            .contains(hce7)\n+            .contains(hce8);\n+        assertThat(hcHistory.entriesForExecutor(exec2))\n+            .hasSize(1)\n+            .contains(otherHce1);\n+        assertEquals(1L, otherHce1.getTimestampFirst());\n+        assertEquals(1L, otherHce1.getTimestampLast());\n+\n+        // just increase uptime\n+        otherHc.setInfo(otherNi\n+            .setUptimeMillis(2)\n+            .build());\n+        hcHistory.record(exec2, 2L, otherHc.build());\n+\n+        CassandraFrameworkProtos.HealthCheckHistoryEntry otherHce2 = hcHistory.last(exec2);\n+        assertNotNull(otherHce2);\n+        assertThat(hcHistory.entries())\n+            .hasSize(6)\n+            .contains(otherHce2);\n+        assertThat(hcHistory.entriesForExecutor(exec2))\n+            .hasSize(1)\n+            .contains(otherHce2);\n+        assertEquals(1L, otherHce2.getTimestampFirst());\n+        assertEquals(2L, otherHce2.getTimestampLast());\n+\n+        // toggle a field\n+        otherHc.setInfo(otherNi\n+            .setNativeTransportRunning(true)\n+            .build());\n+        hcHistory.record(exec2, 3L, otherHc.build());\n+\n+        CassandraFrameworkProtos.HealthCheckHistoryEntry otherHce3 = hcHistory.last(exec2);\n+        assertNotNull(otherHce3);\n+        assertThat(hcHistory.entries())\n+            .hasSize(7)\n+            .contains(otherHce2)\n+            .contains(otherHce3);\n+        assertThat(hcHistory.entriesForExecutor(exec2))\n+            .hasSize(2)\n+            .contains(otherHce2)\n+            .contains(otherHce3);\n+        assertEquals(3L, otherHce3.getTimestampFirst());\n+        assertEquals(3L, otherHce3.getTimestampLast());\n+\n+        // toggle more fields and record\n+        otherHc.setInfo(otherNi\n+            .setNativeTransportRunning(false)\n+            .setRpcServerRunning(true)\n+            .build());\n+        hcHistory.record(exec2, 4L, otherHc.build());\n+        CassandraFrameworkProtos.HealthCheckHistoryEntry otherHce4 = hcHistory.last(exec2);\n+        assertThat(hcHistory.entries()).hasSize(8);\n+\n+        otherHc.setInfo(otherNi\n+            .setNativeTransportRunning(true)\n+            .setRpcServerRunning(true)\n+            .build());\n+        hcHistory.record(exec2, 5L, otherHc.build());\n+        CassandraFrameworkProtos.HealthCheckHistoryEntry otherHce5 = hcHistory.last(exec2);\n+        assertThat(hcHistory.entries()).hasSize(9);\n+        assertThat(hcHistory.entriesForExecutor(exec2))\n+            .hasSize(4)\n+            .contains(otherHce2)\n+            .contains(otherHce3)\n+            .contains(otherHce4)\n+            .contains(otherHce5);\n+\n+        otherHc.setHealthy(true)\n+            .setMsg(\"msg\");\n+        hcHistory.record(exec2, 6L, otherHc.build());\n+        CassandraFrameworkProtos.HealthCheckHistoryEntry otherHce6 = hcHistory.last(exec2);\n+        assertThat(hcHistory.entries()).hasSize(10);\n+        assertThat(hcHistory.entriesForExecutor(exec2))\n+            .hasSize(5)\n+            .contains(otherHce2)\n+            .contains(otherHce3)\n+            .contains(otherHce4)\n+            .contains(otherHce5)\n+            .contains(otherHce6);\n+\n+        otherHc.setHealthy(false)\n+            .setMsg(\"foo\");\n+        hcHistory.record(exec2, 7L, otherHc.build());\n+        CassandraFrameworkProtos.HealthCheckHistoryEntry otherHce7 = hcHistory.last(exec2);\n+        assertThat(hcHistory.entries()).hasSize(10);\n+        assertThat(hcHistory.entriesForExecutor(exec2))\n+            .hasSize(5)\n+            .doesNotContain(otherHce2)\n+            .contains(otherHce3)\n+            .contains(otherHce4)\n+            .contains(otherHce5)\n+            .contains(otherHce6)\n+            .contains(otherHce7);\n+\n+        otherHc.setHealthy(true)\n+            .clearMsg();\n+        hcHistory.record(exec2, 8L, otherHc.build());\n+        CassandraFrameworkProtos.HealthCheckHistoryEntry otherHce8 = hcHistory.last(exec2);\n+        assertThat(hcHistory.entries())\n+            .hasSize(10)\n+            //\n+            .doesNotContain(otherHce2)\n+            .doesNotContain(otherHce3)\n+            .contains(otherHce4)\n+            .contains(otherHce5)\n+            .contains(otherHce6)\n+            .contains(otherHce7)\n+            .contains(otherHce8)\n+            //\n+            .doesNotContain(hce2)\n+            .doesNotContain(hce3)\n+            .contains(hce4)\n+            .contains(hce5)\n+            .contains(hce6)\n+            .contains(hce7)\n+            .contains(hce8);\n+        assertThat(hcHistory.entriesForExecutor(exec2))\n+            .hasSize(5)\n+            .doesNotContain(otherHce2)\n+            .doesNotContain(otherHce3)\n+            .contains(otherHce4)\n+            .contains(otherHce5)\n+            .contains(otherHce6)\n+            .contains(otherHce7)\n+            .contains(otherHce8);\n+\n+    }\n+\n+    @Test\n+    public void testIsSimilarEntryHealthCheckDetails() throws Exception {\n+        CassandraFrameworkProtos.HealthCheckDetails.Builder hc1 = CassandraFrameworkProtos.HealthCheckDetails.newBuilder();\n+        CassandraFrameworkProtos.HealthCheckDetails.Builder hc2 = CassandraFrameworkProtos.HealthCheckDetails.newBuilder();\n+\n+        CassandraFrameworkProtos.NodeInfo.Builder ni1 = CassandraFrameworkProtos.NodeInfo.newBuilder();\n+        CassandraFrameworkProtos.NodeInfo.Builder ni2 = CassandraFrameworkProtos.NodeInfo.newBuilder();\n+\n+        hc1.setHealthy(true);\n+        hc2.setHealthy(true);\n+\n+        assertTrue(PersistedCassandraClusterHealthCheckHistory.isSimilarEntry(hc1.build(), hc2.build()));\n+\n+        hc1.setInfo(ni1);\n+        hc2.setInfo(ni2);\n+\n+        assertTrue(PersistedCassandraClusterHealthCheckHistory.isSimilarEntry(hc1.build(), hc2.build()));\n+\n+        ni1.setUptimeMillis(1234);\n+        ni2.setUptimeMillis(5678);\n+        ni1.setClusterName(\"cluster\");\n+        ni2.setClusterName(\"cluster\");\n+        ni1.setNativeTransportRunning(true);\n+        ni2.setNativeTransportRunning(true);\n+        hc1.setInfo(ni1);\n+        hc2.setInfo(ni2);\n+\n+        assertTrue(PersistedCassandraClusterHealthCheckHistory.isSimilarEntry(hc1.build(), hc2.build()));\n+\n+        ni2.setNativeTransportRunning(false);\n+        hc2.setInfo(ni2);\n+        assertFalse(PersistedCassandraClusterHealthCheckHistory.isSimilarEntry(hc1.build(), hc2.build()));\n+\n+        ni2.setNativeTransportRunning(true);\n+        ni2.setClusterName(\"foo\");\n+        hc2.setInfo(ni2);\n+        assertFalse(PersistedCassandraClusterHealthCheckHistory.isSimilarEntry(hc1.build(), hc2.build()));\n+\n+        ni2.setClusterName(\"cluster\");\n+        hc2.setInfo(ni2);\n+        assertTrue(PersistedCassandraClusterHealthCheckHistory.isSimilarEntry(hc1.build(), hc2.build()));\n+\n+        hc2.setHealthy(false);\n+        assertFalse(PersistedCassandraClusterHealthCheckHistory.isSimilarEntry(hc1.build(), hc2.build()));\n+\n+        hc2.setHealthy(true);\n+        hc2.setMsg(\"msg\");\n+        assertFalse(PersistedCassandraClusterHealthCheckHistory.isSimilarEntry(hc1.build(), hc2.build()));\n+\n+        hc2.clearMsg();\n+        hc1.setMsg(\"msg\");\n+        assertFalse(PersistedCassandraClusterHealthCheckHistory.isSimilarEntry(hc1.build(), hc2.build()));\n+\n+        hc1.clearMsg();\n+        assertTrue(PersistedCassandraClusterHealthCheckHistory.isSimilarEntry(hc1.build(), hc2.build()));\n+\n+    }\n+\n+    @Test\n+    public void testIsSimilarEntryNodeInfo() throws Exception {\n+        CassandraFrameworkProtos.NodeInfo.Builder ni1 = CassandraFrameworkProtos.NodeInfo.newBuilder();\n+        CassandraFrameworkProtos.NodeInfo.Builder ni2 = CassandraFrameworkProtos.NodeInfo.newBuilder();\n+\n+        assertTrue(PersistedCassandraClusterHealthCheckHistory.isSimilarEntry(ni1.build(), ni2.build()));\n+        ni1.setUptimeMillis(1234);\n+        ni2.setUptimeMillis(5678);\n+        assertTrue(PersistedCassandraClusterHealthCheckHistory.isSimilarEntry(ni1.build(), ni2.build()));\n+\n+        ni1.setClusterName(\"cluster\");\n+        ni2.setClusterName(\"cluster\");\n+        assertTrue(PersistedCassandraClusterHealthCheckHistory.isSimilarEntry(ni1.build(), ni2.build()));\n+\n+        ni1.setNativeTransportRunning(true);\n+        ni2.setNativeTransportRunning(true);\n+        assertTrue(PersistedCassandraClusterHealthCheckHistory.isSimilarEntry(ni1.build(), ni2.build()));\n+\n+        ni2.setNativeTransportRunning(false);\n+        assertFalse(PersistedCassandraClusterHealthCheckHistory.isSimilarEntry(ni1.build(), ni2.build()));\n+\n+        ni2.setNativeTransportRunning(true);\n+        ni2.setClusterName(\"foo\");\n+        assertFalse(PersistedCassandraClusterHealthCheckHistory.isSimilarEntry(ni1.build(), ni2.build()));\n+\n+        ni2.setNativeTransportRunning(true);\n+        ni2.setClusterName(\"cluster\");\n+        assertTrue(PersistedCassandraClusterHealthCheckHistory.isSimilarEntry(ni1.build(), ni2.build()));\n+\n+        ni1.setDataCenter(\"dc\");\n+        assertFalse(PersistedCassandraClusterHealthCheckHistory.isSimilarEntry(ni1.build(), ni2.build()));\n+\n+        ni1.clearDataCenter();\n+        ni2.setRack(\"rac\");\n+        assertFalse(PersistedCassandraClusterHealthCheckHistory.isSimilarEntry(ni1.build(), ni2.build()));\n+    }\n+\n+    @Test\n+    public void testObjEquals() throws Exception {\n+        assertTrue(PersistedCassandraClusterHealthCheckHistory.objEquals(null, null));\n+        assertFalse(PersistedCassandraClusterHealthCheckHistory.objEquals(null, \"\"));\n+        assertFalse(PersistedCassandraClusterHealthCheckHistory.objEquals(\"\", null));\n+        assertTrue(PersistedCassandraClusterHealthCheckHistory.objEquals(\"1\", \"1\"));\n+        assertTrue(PersistedCassandraClusterHealthCheckHistory.objEquals(1, 1));\n+        assertFalse(PersistedCassandraClusterHealthCheckHistory.objEquals(\"1\", \"2\"));\n+        assertFalse(PersistedCassandraClusterHealthCheckHistory.objEquals(1, 2));\n+    }","path":"cassandra-scheduler/src/test/java/io/mesosphere/mesos/frameworks/cassandra/PersistedCassandraClusterHealthCheckHistoryTest.java","position":411,"original_position":411,"commit_id":"5f5bcb36727abb61d157c6fb2cf0fe8c77520e9c","original_commit_id":"5f5bcb36727abb61d157c6fb2cf0fe8c77520e9c","user":{"login":"snazy","id":957468,"avatar_url":"https://avatars.githubusercontent.com/u/957468?v=3","gravatar_id":"","url":"https://api.github.com/users/snazy","html_url":"https://github.com/snazy","followers_url":"https://api.github.com/users/snazy/followers","following_url":"https://api.github.com/users/snazy/following{/other_user}","gists_url":"https://api.github.com/users/snazy/gists{/gist_id}","starred_url":"https://api.github.com/users/snazy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/snazy/subscriptions","organizations_url":"https://api.github.com/users/snazy/orgs","repos_url":"https://api.github.com/users/snazy/repos","events_url":"https://api.github.com/users/snazy/events{/privacy}","received_events_url":"https://api.github.com/users/snazy/received_events","type":"User","site_admin":false},"body":"Damn out-of-order protocols ;)\r\n\r\nIn this case - I've added some code to silently drop records that are older that the most-recent one. Since we're not building a descent monitoring tool it should be fine IMO to drop outdated health-check info.","created_at":"2015-03-12T10:26:57Z","updated_at":"2015-03-12T10:26:57Z","html_url":"https://github.com/mesosphere/cassandra-mesos/pull/48#discussion_r26290728","pull_request_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/pulls/48","_links":{"self":{"href":"https://api.github.com/repos/mesosphere/cassandra-mesos/pulls/comments/26290728"},"html":{"href":"https://github.com/mesosphere/cassandra-mesos/pull/48#discussion_r26290728"},"pull_request":{"href":"https://api.github.com/repos/mesosphere/cassandra-mesos/pulls/48"}}},"pull_request":{"url":"https://api.github.com/repos/mesosphere/cassandra-mesos/pulls/48","id":30941178,"html_url":"https://github.com/mesosphere/cassandra-mesos/pull/48","diff_url":"https://github.com/mesosphere/cassandra-mesos/pull/48.diff","patch_url":"https://github.com/mesosphere/cassandra-mesos/pull/48.patch","issue_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/issues/48","number":48,"state":"open","locked":false,"title":"bounded health check history","user":{"login":"snazy","id":957468,"avatar_url":"https://avatars.githubusercontent.com/u/957468?v=3","gravatar_id":"","url":"https://api.github.com/users/snazy","html_url":"https://github.com/snazy","followers_url":"https://api.github.com/users/snazy/followers","following_url":"https://api.github.com/users/snazy/following{/other_user}","gists_url":"https://api.github.com/users/snazy/gists{/gist_id}","starred_url":"https://api.github.com/users/snazy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/snazy/subscriptions","organizations_url":"https://api.github.com/users/snazy/orgs","repos_url":"https://api.github.com/users/snazy/repos","events_url":"https://api.github.com/users/snazy/events{/privacy}","received_events_url":"https://api.github.com/users/snazy/received_events","type":"User","site_admin":false},"body":"Limit health check history to N _different_ health check results.\r\nThat is - only changes of the `HealthCheckDetails` and `NodeInfo` will be recorded (plus _first_ and _last_ timestamp of occurence).\r\nThe `uptimeMillis` field is ignored in change-detection.\r\n\r\nTBH I think we should use separate objects in state for each node/executor. But we should do that in a separate PR. We can also merge HC history into `CassandraNode` since `CassandraNode` is also updated on every HC.\r\n\r\nThis PR is independent from other PRs.","created_at":"2015-03-11T13:10:33Z","updated_at":"2015-03-12T10:26:57Z","closed_at":null,"merged_at":null,"merge_commit_sha":"02876f2dfa27205d85179f46af75753283d91281","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/pulls/48/commits","review_comments_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/pulls/48/comments","review_comment_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/pulls/comments{/number}","comments_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/issues/48/comments","statuses_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/statuses/5f5bcb36727abb61d157c6fb2cf0fe8c77520e9c","head":{"label":"snazy:bounded-hc-history","ref":"bounded-hc-history","sha":"5f5bcb36727abb61d157c6fb2cf0fe8c77520e9c","user":{"login":"snazy","id":957468,"avatar_url":"https://avatars.githubusercontent.com/u/957468?v=3","gravatar_id":"","url":"https://api.github.com/users/snazy","html_url":"https://github.com/snazy","followers_url":"https://api.github.com/users/snazy/followers","following_url":"https://api.github.com/users/snazy/following{/other_user}","gists_url":"https://api.github.com/users/snazy/gists{/gist_id}","starred_url":"https://api.github.com/users/snazy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/snazy/subscriptions","organizations_url":"https://api.github.com/users/snazy/orgs","repos_url":"https://api.github.com/users/snazy/repos","events_url":"https://api.github.com/users/snazy/events{/privacy}","received_events_url":"https://api.github.com/users/snazy/received_events","type":"User","site_admin":false},"repo":{"id":30885937,"name":"cassandra-mesos","full_name":"snazy/cassandra-mesos","owner":{"login":"snazy","id":957468,"avatar_url":"https://avatars.githubusercontent.com/u/957468?v=3","gravatar_id":"","url":"https://api.github.com/users/snazy","html_url":"https://github.com/snazy","followers_url":"https://api.github.com/users/snazy/followers","following_url":"https://api.github.com/users/snazy/following{/other_user}","gists_url":"https://api.github.com/users/snazy/gists{/gist_id}","starred_url":"https://api.github.com/users/snazy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/snazy/subscriptions","organizations_url":"https://api.github.com/users/snazy/orgs","repos_url":"https://api.github.com/users/snazy/repos","events_url":"https://api.github.com/users/snazy/events{/privacy}","received_events_url":"https://api.github.com/users/snazy/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/snazy/cassandra-mesos","description":"Cassandra on Mesos","fork":true,"url":"https://api.github.com/repos/snazy/cassandra-mesos","forks_url":"https://api.github.com/repos/snazy/cassandra-mesos/forks","keys_url":"https://api.github.com/repos/snazy/cassandra-mesos/keys{/key_id}","collaborators_url":"https://api.github.com/repos/snazy/cassandra-mesos/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/snazy/cassandra-mesos/teams","hooks_url":"https://api.github.com/repos/snazy/cassandra-mesos/hooks","issue_events_url":"https://api.github.com/repos/snazy/cassandra-mesos/issues/events{/number}","events_url":"https://api.github.com/repos/snazy/cassandra-mesos/events","assignees_url":"https://api.github.com/repos/snazy/cassandra-mesos/assignees{/user}","branches_url":"https://api.github.com/repos/snazy/cassandra-mesos/branches{/branch}","tags_url":"https://api.github.com/repos/snazy/cassandra-mesos/tags","blobs_url":"https://api.github.com/repos/snazy/cassandra-mesos/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/snazy/cassandra-mesos/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/snazy/cassandra-mesos/git/refs{/sha}","trees_url":"https://api.github.com/repos/snazy/cassandra-mesos/git/trees{/sha}","statuses_url":"https://api.github.com/repos/snazy/cassandra-mesos/statuses/{sha}","languages_url":"https://api.github.com/repos/snazy/cassandra-mesos/languages","stargazers_url":"https://api.github.com/repos/snazy/cassandra-mesos/stargazers","contributors_url":"https://api.github.com/repos/snazy/cassandra-mesos/contributors","subscribers_url":"https://api.github.com/repos/snazy/cassandra-mesos/subscribers","subscription_url":"https://api.github.com/repos/snazy/cassandra-mesos/subscription","commits_url":"https://api.github.com/repos/snazy/cassandra-mesos/commits{/sha}","git_commits_url":"https://api.github.com/repos/snazy/cassandra-mesos/git/commits{/sha}","comments_url":"https://api.github.com/repos/snazy/cassandra-mesos/comments{/number}","issue_comment_url":"https://api.github.com/repos/snazy/cassandra-mesos/issues/comments{/number}","contents_url":"https://api.github.com/repos/snazy/cassandra-mesos/contents/{+path}","compare_url":"https://api.github.com/repos/snazy/cassandra-mesos/compare/{base}...{head}","merges_url":"https://api.github.com/repos/snazy/cassandra-mesos/merges","archive_url":"https://api.github.com/repos/snazy/cassandra-mesos/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/snazy/cassandra-mesos/downloads","issues_url":"https://api.github.com/repos/snazy/cassandra-mesos/issues{/number}","pulls_url":"https://api.github.com/repos/snazy/cassandra-mesos/pulls{/number}","milestones_url":"https://api.github.com/repos/snazy/cassandra-mesos/milestones{/number}","notifications_url":"https://api.github.com/repos/snazy/cassandra-mesos/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/snazy/cassandra-mesos/labels{/name}","releases_url":"https://api.github.com/repos/snazy/cassandra-mesos/releases{/id}","created_at":"2015-02-16T20:08:31Z","updated_at":"2015-03-02T14:32:54Z","pushed_at":"2015-03-12T10:00:54Z","git_url":"git://github.com/snazy/cassandra-mesos.git","ssh_url":"git@github.com:snazy/cassandra-mesos.git","clone_url":"https://github.com/snazy/cassandra-mesos.git","svn_url":"https://github.com/snazy/cassandra-mesos","homepage":null,"size":1213,"stargazers_count":0,"watchers_count":0,"language":"Java","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":"rewrite"}},"base":{"label":"mesosphere:rewrite","ref":"rewrite","sha":"c83974ee959b5a123edb8172889af79860c5be5b","user":{"login":"mesosphere","id":3458585,"avatar_url":"https://avatars.githubusercontent.com/u/3458585?v=3","gravatar_id":"","url":"https://api.github.com/users/mesosphere","html_url":"https://github.com/mesosphere","followers_url":"https://api.github.com/users/mesosphere/followers","following_url":"https://api.github.com/users/mesosphere/following{/other_user}","gists_url":"https://api.github.com/users/mesosphere/gists{/gist_id}","starred_url":"https://api.github.com/users/mesosphere/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mesosphere/subscriptions","organizations_url":"https://api.github.com/users/mesosphere/orgs","repos_url":"https://api.github.com/users/mesosphere/repos","events_url":"https://api.github.com/users/mesosphere/events{/privacy}","received_events_url":"https://api.github.com/users/mesosphere/received_events","type":"Organization","site_admin":false},"repo":{"id":15693035,"name":"cassandra-mesos","full_name":"mesosphere/cassandra-mesos","owner":{"login":"mesosphere","id":3458585,"avatar_url":"https://avatars.githubusercontent.com/u/3458585?v=3","gravatar_id":"","url":"https://api.github.com/users/mesosphere","html_url":"https://github.com/mesosphere","followers_url":"https://api.github.com/users/mesosphere/followers","following_url":"https://api.github.com/users/mesosphere/following{/other_user}","gists_url":"https://api.github.com/users/mesosphere/gists{/gist_id}","starred_url":"https://api.github.com/users/mesosphere/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mesosphere/subscriptions","organizations_url":"https://api.github.com/users/mesosphere/orgs","repos_url":"https://api.github.com/users/mesosphere/repos","events_url":"https://api.github.com/users/mesosphere/events{/privacy}","received_events_url":"https://api.github.com/users/mesosphere/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/mesosphere/cassandra-mesos","description":"Cassandra on Mesos","fork":false,"url":"https://api.github.com/repos/mesosphere/cassandra-mesos","forks_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/forks","keys_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/teams","hooks_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/hooks","issue_events_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/issues/events{/number}","events_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/events","assignees_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/assignees{/user}","branches_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/branches{/branch}","tags_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/tags","blobs_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/git/refs{/sha}","trees_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/statuses/{sha}","languages_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/languages","stargazers_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/stargazers","contributors_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/contributors","subscribers_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/subscribers","subscription_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/subscription","commits_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/commits{/sha}","git_commits_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/git/commits{/sha}","comments_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/comments{/number}","issue_comment_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/issues/comments{/number}","contents_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/contents/{+path}","compare_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/merges","archive_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/downloads","issues_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/issues{/number}","pulls_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/pulls{/number}","milestones_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/milestones{/number}","notifications_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/labels{/name}","releases_url":"https://api.github.com/repos/mesosphere/cassandra-mesos/releases{/id}","created_at":"2014-01-07T02:27:47Z","updated_at":"2015-03-11T23:35:55Z","pushed_at":"2015-03-11T02:34:05Z","git_url":"git://github.com/mesosphere/cassandra-mesos.git","ssh_url":"git@github.com:mesosphere/cassandra-mesos.git","clone_url":"https://github.com/mesosphere/cassandra-mesos.git","svn_url":"https://github.com/mesosphere/cassandra-mesos","homepage":null,"size":1620,"stargazers_count":86,"watchers_count":86,"language":"Scala","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":17,"mirror_url":null,"open_issues_count":20,"forks":17,"open_issues":20,"watchers":86,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/mesosphere/cassandra-mesos/pulls/48"},"html":{"href":"https://github.com/mesosphere/cassandra-mesos/pull/48"},"issue":{"href":"https://api.github.com/repos/mesosphere/cassandra-mesos/issues/48"},"comments":{"href":"https://api.github.com/repos/mesosphere/cassandra-mesos/issues/48/comments"},"review_comments":{"href":"https://api.github.com/repos/mesosphere/cassandra-mesos/pulls/48/comments"},"review_comment":{"href":"https://api.github.com/repos/mesosphere/cassandra-mesos/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/mesosphere/cassandra-mesos/pulls/48/commits"},"statuses":{"href":"https://api.github.com/repos/mesosphere/cassandra-mesos/statuses/5f5bcb36727abb61d157c6fb2cf0fe8c77520e9c"}}}}