def test_touching_when_alive(): with freezegun.freeze_time('2020-01-01T10:20:30'): peer = Peer(id='id1', name='name1', lifetime=123) assert not peer.is_dead with freezegun.freeze_time('2020-02-02T11:22:33'): peer.touch() assert peer.lifetime == datetime.timedelta(seconds=123) assert peer.lastseen == datetime.datetime(2020, 2, 2, 11, 22, 33) assert peer.deadline == datetime.datetime(2020, 2, 2, 11, 24, 36) assert not peer.is_dead
async def test_ignored_for_higher_priority_peer_when_already_on(caplog, assert_logs): event = bodies.RawEvent( type='ADDED', # irrelevant object={ 'metadata': {'name': 'name', 'namespace': 'namespace'}, # for matching 'status': { 'higher-prio': { 'priority': 101, 'lifetime': 10, 'lastseen': '2020-12-31T23:59:59' }, }, }) replenished = asyncio.Event() freeze_mode = primitives.Toggle(True) ourselves = Peer(id='id', name='name', namespace='namespace', priority=100) caplog.set_level(0) assert freeze_mode.is_on() await process_peering_event( raw_event=event, freeze_mode=freeze_mode, ourselves=ourselves, replenished=replenished, autoclean=False, ) assert freeze_mode.is_on() assert_logs([], prohibited=[ "Possibly conflicting operators", "Freezing all operators, including self", "Freezing operations in favour of", "Resuming operations after the freeze", ])
def test_defaults(): peer = Peer(id='id', name='name') assert peer.id == 'id' assert peer.name == 'name' assert peer.namespace is None assert peer.legacy is False assert peer.lifetime == datetime.timedelta(seconds=60) assert peer.lastseen == datetime.datetime(2020, 12, 31, 23, 59, 59, 123456)
def test_repr(): peer = Peer(identity='some-id') text = repr(peer) assert text.startswith('Peer(') assert text.endswith(')') assert 'identity=some-id' in text assert 'priority=0' in text assert 'lastseen=' in text assert 'lifetime=' in text
def test_creation_as_dead(): peer = Peer( identity='id', lifetime=10, lastseen='2020-12-31T23:59:49.123456', # 10 seconds before "now" sharp ) assert peer.lifetime == datetime.timedelta(seconds=10) assert peer.lastseen == datetime.datetime(2020, 12, 31, 23, 59, 49, 123456) assert peer.deadline == datetime.datetime(2020, 12, 31, 23, 59, 59, 123456) assert peer.is_dead is True
def test_creation_as_alive(): peer = Peer( identity='id', lifetime=10, lastseen= '2020-12-31T23:59:50.123456', # less than 10 seconds before "now" ) assert peer.lifetime == datetime.timedelta(seconds=10) assert peer.lastseen == datetime.datetime(2020, 12, 31, 23, 59, 50, 123456) assert peer.deadline == datetime.datetime(2021, 1, 1, 0, 0, 0, 123456) assert peer.is_dead is False
async def test_disappear( hostname, aresponses, resp_mocker, namespace, peering_resource, lastseen): patch_mock = resp_mocker(return_value=aiohttp.web.json_response({})) url = peering_resource.get_url(name='name0', namespace=namespace) aresponses.add(hostname, url, 'patch', patch_mock) peer = Peer(id='id1', name='name0', namespace=namespace, lastseen=lastseen) await peer.disappear() assert patch_mock.called patch = await patch_mock.call_args_list[0][0][0].json() assert set(patch['status']) == {'id1'} assert patch['status']['id1'] is None
async def test_applying_a_dead_peer_purges_it( hostname, aresponses, resp_mocker, namespace, peering_resource): patch_mock = resp_mocker(return_value=aiohttp.web.json_response({})) url = peering_resource.get_url(name='name0', namespace=namespace) aresponses.add(hostname, url, 'patch', patch_mock) peer = Peer(id='id1', name='...', namespace='ns1', lastseen='2020-01-01T00:00:00') await apply_peers(peers=[peer], name='name0', namespace=namespace) assert patch_mock.called patch = await patch_mock.call_args_list[0][0][0].json() assert set(patch['status']) == {'id1'} assert patch['status']['id1'] is None
def test_repr(): peer = Peer(id='some-id', name='some-name', namespace='some-namespace') text = repr(peer) assert text.startswith('Peer(') assert text.endswith(')') assert '(some-id, ' in text assert 'priority=0' in text assert 'lastseen=' in text assert 'lifetime=' in text # The peering object's name is of no interest, the peer's id is. assert 'name=' not in text # The namespace of the operator can affect the conflict detection. # It is not always the same as the peering object's namespace. assert 'namespace=some-namespace' in text
async def test_cleaning_peers_purges_them(hostname, aresponses, resp_mocker, namespace, peering_resource, settings, lastseen): settings.peering.name = 'name0' patch_mock = resp_mocker(return_value=aiohttp.web.json_response({})) url = peering_resource.get_url(name='name0', namespace=namespace) aresponses.add(hostname, url, 'patch', patch_mock) peer = Peer(identity='id1', lastseen=lastseen) await clean(peers=[peer], settings=settings, namespace=namespace) assert patch_mock.called patch = await patch_mock.call_args_list[0][0][0].json() assert set(patch['status']) == {'id1'} assert patch['status']['id1'] is None
async def test_keepalive( hostname, aresponses, resp_mocker, namespace, peering_resource, lastseen): patch_mock = resp_mocker(return_value=aiohttp.web.json_response({})) url = peering_resource.get_url(name='name0', namespace=namespace) aresponses.add(hostname, url, 'patch', patch_mock) peer = Peer(id='id1', name='name0', namespace=namespace, lastseen=lastseen) await peer.keepalive() assert patch_mock.called patch = await patch_mock.call_args_list[0][0][0].json() assert set(patch['status']) == {'id1'} assert patch['status']['id1']['namespace'] == namespace assert patch['status']['id1']['priority'] == 0 assert patch['status']['id1']['lastseen'] == '2020-12-31T23:59:59.123456' assert patch['status']['id1']['lifetime'] == 60
async def test_applying_an_alive_peer_stores_it( hostname, aresponses, resp_mocker, namespace, peering_resource): patch_mock = resp_mocker(return_value=aiohttp.web.json_response({})) url = peering_resource.get_url(name='name0', namespace=namespace) aresponses.add(hostname, url, 'patch', patch_mock) peer = Peer(id='id1', name='...', namespace='ns1', lastseen='2020-12-31T23:59:59') await apply_peers(peers=[peer], name='name0', namespace=namespace) assert patch_mock.called patch = await patch_mock.call_args_list[0][0][0].json() assert set(patch['status']) == {'id1'} assert patch['status']['id1']['namespace'] == 'ns1' assert patch['status']['id1']['priority'] == 0 assert patch['status']['id1']['lastseen'] == '2020-12-31T23:59:59' assert patch['status']['id1']['lifetime'] == 60
async def test_background_task_runs(mocker): ourselves = Peer(id='id', name='name', namespace='namespace', lifetime=33) keepalive_mock = mocker.patch.object(ourselves, 'keepalive') disappear_mock = mocker.patch.object(ourselves, 'disappear') sleep_mock = mocker.patch('asyncio.sleep') sleep_mock.side_effect = [None, None, StopInfiniteCycleException] with pytest.raises(StopInfiniteCycleException): await peers_keepalive(ourselves=ourselves) assert sleep_mock.call_count == 3 assert sleep_mock.call_args_list[0][0][0] == 33 - 10 assert sleep_mock.call_args_list[1][0][0] == 33 - 10 assert sleep_mock.call_args_list[2][0][0] == 33 - 10 assert keepalive_mock.call_count == 3 assert disappear_mock.call_count == 1
async def test_other_peering_objects_are_ignored( mocker, our_name, our_namespace, their_name, their_namespace): ourselves = Peer(id='id', name=our_name, namespace=our_namespace) status = mocker.Mock() status.items.side_effect = Exception("This should not be called.") event = bodies.RawEvent( type='ADDED', # irrelevant object={ 'metadata': {'name': their_name, 'namespace': their_namespace}, 'status': status, }) await process_peering_event( raw_event=event, ourselves=ourselves, freeze_mode=primitives.Toggle(), replenished=asyncio.Event(), autoclean=False, ) assert not status.items.called
def test_defaults(): peer = Peer(identity='id') assert peer.identity == 'id' assert peer.lifetime == datetime.timedelta(seconds=60) assert peer.lastseen == datetime.datetime(2020, 12, 31, 23, 59, 59, 123456)
def test_resource_for_cluster_peering(): peer = Peer(id='id', name='name', legacy=False, namespace=None) assert peer.legacy is False assert peer.resource == CLUSTER_PEERING_RESOURCE assert peer.namespace is None
def test_creation_with_lastseen_unspecified(): peer = Peer(identity='id') assert peer.lastseen == datetime.datetime(2020, 12, 31, 23, 59, 59, 123456)
def test_priority_specified(): peer = Peer(id='id', name='name', priority=123) assert peer.priority == 123
def test_creation_with_lastseen_as_datetime(): peer = Peer(identity='id', lastseen=datetime.datetime(2020, 1, 1, 12, 34, 56, 789123)) assert peer.lastseen == datetime.datetime(2020, 1, 1, 12, 34, 56, 789123)
def test_creation_with_lastseen_as_string(): peer = Peer(identity='id', lastseen='2020-01-01T12:34:56.789123') assert peer.lastseen == datetime.datetime(2020, 1, 1, 12, 34, 56, 789123)
def test_creation_with_lifetime_as_number(): peer = Peer(identity='id', lifetime=123) assert peer.lifetime == datetime.timedelta(seconds=123)
def test_creation_with_lifetime_unspecified(): peer = Peer(identity='id') assert peer.lifetime == datetime.timedelta(seconds=60)
def test_priority_specified(): peer = Peer(identity='id', priority=123) assert peer.priority == 123
def test_priority_unspecified(): peer = Peer(identity='id') assert peer.priority == 0
def test_priority_unspecified(): peer = Peer(id='id', name='name') assert peer.priority == 0
def test_repr(): peer = Peer(identity='some-id') text = repr(peer) assert text == "<Peer some-id: priority=0, lifetime=60, lastseen='2020-12-31T23:59:59.123456'>"
def test_creation_with_lifetime_as_timedelta(): peer = Peer(id='id', name='name', lifetime=datetime.timedelta(seconds=123)) assert peer.lifetime == datetime.timedelta(seconds=123)
def test_resource_for_namespaced_peering(): peer = Peer(id='id', name='name', legacy=False, namespace='namespaced') assert peer.legacy is False assert peer.resource == NAMESPACED_PEERING_RESOURCE assert peer.namespace == 'namespaced'
def test_resource_for_legacy_peering(namespace): peer = Peer(id='id', name='name', legacy=True, namespace=namespace) assert peer.legacy is True assert peer.resource == LEGACY_PEERING_RESOURCE