def test_update_felix_status(self, m_monotime, m_datetime): m_datetime.utcnow.return_value = datetime(2015, 9, 10, 2, 1, 53, 1234) with patch.object(self.api.client, "set") as m_set: self.api._update_felix_status(10) self.api._update_felix_status(10) # Should write two keys into etcd, one with a TTL and another with # richer status. self.assertEqual(m_set.mock_calls, [ call("/calico/felix/v1/host/hostname/last_reported_status", JSONString({"uptime": 100, "time": "2015-09-10T02:01:53Z", "first_update": True})), call("/calico/felix/v1/host/hostname/status", JSONString({"uptime": 100, "time": "2015-09-10T02:01:53Z", "first_update": True}), ttl=10), call("/calico/felix/v1/host/hostname/last_reported_status", JSONString({"uptime": 100, "time": "2015-09-10T02:01:53Z", "first_update": False})), call("/calico/felix/v1/host/hostname/status", JSONString({"uptime": 100, "time": "2015-09-10T02:01:53Z", "first_update": False}), ttl=10), ])
def test_on_endpoint_status_v4_v6(self): # Send in endpoint status updates for v4 and v6. endpoint_id = EndpointId("foo", "bar", "baz", "biff") with patch("gevent.spawn_later", autospec=True) as m_spawn: self.rep.on_endpoint_status_changed(endpoint_id, IPV4, {"status": "up"}, async=True) self.rep.on_endpoint_status_changed(endpoint_id, IPV6, {"status": "down"}, async=True) self.step_actor(self.rep) # Should record the status. self.assertEqual( self.rep._endpoint_status, { IPV4: { endpoint_id: { "status": "up" } }, IPV6: { endpoint_id: { "status": "down" } }, }) # And do a write. self.assertEqual(self.m_client.set.mock_calls, [ call("/calico/felix/v1/host/foo/workload/bar/baz/endpoint/biff", JSONString({"status": "down"})) ])
def test_on_endpoint_status_failure(self): # Send in an endpoint status update. endpoint_id = EndpointId("foo", "bar", "baz", "biff") self.m_client.set.side_effect = EtcdException() with patch("gevent.spawn_later", autospec=True) as m_spawn: self.rep.on_endpoint_status_changed(endpoint_id, IPV4, {"status": "up"}, async=True) self.step_actor(self.rep) # Should do the write. self.assertEqual(self.m_client.set.mock_calls, [ call("/calico/felix/v1/host/foo/workload/bar/baz/endpoint/biff", JSONString({"status": "up"})) ]) # But endpoint should be re-queued in the newer set. self.assertEqual(self.rep._newer_dirty_endpoints, set([endpoint_id])) self.assertEqual(self.rep._older_dirty_endpoints, set())
def test_on_endpoint_status_mainline(self): # Send in an endpoint status update. endpoint_id = EndpointId("foo", "bar", "baz", "biff") with patch("gevent.spawn_later", autospec=True) as m_spawn: self.rep.on_endpoint_status_changed(endpoint_id, IPV4, {"status": "up"}, async=True) self.step_actor(self.rep) # Should record the status. self.assertEqual(self.rep._endpoint_status[IPV4], {endpoint_id: { "status": "up" }}) # And do a write. self.assertEqual(self.m_client.set.mock_calls, [ call("/calico/felix/v1/host/foo/workload/bar/baz/endpoint/biff", JSONString({"status": "up"})) ]) # Since we did a write, the rate limit timer should be scheduled. self.assertEqual(m_spawn.mock_calls, [call(ANY, self.rep._on_timer_pop, async=True)]) self.assertTrue(self.rep._timer_scheduled) self.assertFalse(self.rep._reporting_allowed) # Send in another update, shouldn't get written until we pop the timer. self.m_client.reset_mock() with patch("gevent.spawn_later", autospec=True) as m_spawn: self.rep.on_endpoint_status_changed(endpoint_id, IPV4, None, async=True) self.step_actor(self.rep) self.assertFalse(self.m_client.set.called) # Timer already scheduled, shouldn't get rescheduled. self.assertFalse(m_spawn.called) # Pop the timer, should trigger write and reschedule. with patch("gevent.spawn_later", autospec=True) as m_spawn: self.rep._on_timer_pop(async=True) self.step_actor(self.rep) self.maxDiff = 10000 self.assertEqual(self.m_client.delete.mock_calls, [ call("/calico/felix/v1/host/foo/workload/bar/baz/endpoint/" "biff"), call("calico/felix/v1/host/foo/workload/bar/baz/endpoint", dir=True, timeout=5), call("calico/felix/v1/host/foo/workload/bar/baz", dir=True, timeout=5), call("calico/felix/v1/host/foo/workload/bar", dir=True, timeout=5), call("calico/felix/v1/host/foo/workload", dir=True, timeout=5), ]) # Rate limit timer should be scheduled. self.assertEqual(m_spawn.mock_calls, [call(ANY, self.rep._on_timer_pop, async=True)]) spawn_delay = m_spawn.call_args[0][0] self.assertTrue(spawn_delay >= 0.89999) self.assertTrue(spawn_delay <= 1.10001) self.assertTrue(self.rep._timer_scheduled) self.assertFalse(self.rep._reporting_allowed) # Cache should be cleaned up. self.assertEqual(self.rep._endpoint_status[IPV4], {}) # Nothing queued. self.assertEqual(self.rep._newer_dirty_endpoints, set()) self.assertEqual(self.rep._older_dirty_endpoints, set())