def test_delete_conflict(self):
        id1 = "foo"
        id2 = "bar"
        before = datetime(year=2021, month=6, day=1, hour=12, minute=1)
        after = datetime(year=2021, month=6, day=1, hour=12, minute=2)
        config1 = config.Ingress(
            subdomain="hello",
            ip_whitelist=[IPv4Network("200.100.9.0/27")],
            last_updated=after,
            group_id=0,
        )
        config2 = config.Ingress(
            subdomain="elloh",
            ip_whitelist=[],
            last_updated=after,
            group_id=0,
        )
        s = state.State(configs={
            id1: config1,
            id2: config2,
        })

        with self.assertRaises(state.UpdateConflictError):
            s.delete(id1, before)

        self.assertEqual(
            s,
            state.State(configs={
                id1: config1,
                id2: config2,
            }),
        )
    def test_delete_existing(self):
        id1 = "foo"
        id2 = "bar"
        before = datetime(year=2021, month=6, day=1, hour=12, minute=1)
        after = datetime(year=2021, month=6, day=1, hour=12, minute=2)
        config1 = config.Ingress(
            subdomain="hello",
            ip_whitelist=[IPv4Network("200.100.9.0/27")],
            last_updated=before,
            group_id=0,
        )
        config2 = config.Ingress(
            subdomain="elloh",
            ip_whitelist=[],
            last_updated=before,
            group_id=0,
        )
        s = state.State(configs={
            id1: config1,
            id2: config2,
        })

        event = s.delete(id1, after)

        self.assertEqual(s, state.State(configs={id2: config2}))
        self.assertEqual(
            event,
            state.UpdateEvent(
                id=id1,
                previous_config=config1,
                next_config=None,
            ),
        )
    def test_upsert_new_on_empty(self):
        id = "foo"
        ingress_update = config.IngressUpdate(
            subdomain="hello",
            ip_whitelist=[IPv4Network("200.100.9.0/27")],
        )
        timestamp = datetime(year=2021, month=6, day=1, hour=12, minute=2)
        s = state.State()
        expected_config = config.Ingress(
            subdomain=ingress_update.subdomain,
            ip_whitelist=ingress_update.ip_whitelist,
            last_updated=timestamp,
            group_id=0,
        )

        event = s.upsert(id, ingress_update, timestamp)

        self.assertEqual(s.configs, {id: expected_config})
        self.assertEqual(
            event,
            state.UpdateEvent(
                id=id,
                previous_config=None,
                next_config=expected_config,
            ),
        )
    def test_has_updated_since(self):
        before = datetime(year=2021, month=6, day=1, hour=12, minute=1)
        timestamp = datetime(year=2021, month=6, day=1, hour=12, minute=2)
        after = datetime(year=2021, month=6, day=1, hour=12, minute=3)
        cfg = config.Ingress(
            subdomain="hello",
            ip_whitelist=[],
            last_updated=timestamp,
            group_id=1,
        )

        self.assertTrue(cfg.has_updated_since(before))
        self.assertTrue(cfg.has_updated_since(timestamp))
        self.assertFalse(cfg.has_updated_since(after))
    def test_upsert_new_group(self):
        id = "foo"
        ingress_update = config.IngressUpdate(
            subdomain="hello",
            ip_whitelist=[IPv4Network("200.100.9.0/27")],
        )
        before = datetime(year=2021, month=6, day=1, hour=12, minute=1)
        timestamp = datetime(year=2021, month=6, day=1, hour=12, minute=2)
        s = state.State(
            configs={
                f"id{n}": config.Ingress(
                    subdomain=f"sub{n}",
                    ip_whitelist=[],
                    last_updated=before,
                    group_id=0,
                )
                for n in range(0, 95)
            })
        expected_config = config.Ingress(
            subdomain=ingress_update.subdomain,
            ip_whitelist=ingress_update.ip_whitelist,
            last_updated=timestamp,
            group_id=1,
        )

        event = s.upsert(id, ingress_update, timestamp)

        self.assertEqual(s.configs[id], expected_config)
        self.assertEqual(
            event,
            state.UpdateEvent(
                id=id,
                previous_config=None,
                next_config=expected_config,
            ),
        )
    def test_upsert_update(self):
        id = "foo"
        ingress_update = config.IngressUpdate(
            subdomain="hello2",
            ip_whitelist=[
                IPv4Network("200.100.9.0/27"),
                IPv4Network("200.100.10.0/27"),
            ],
        )
        before = datetime(year=2021, month=6, day=1, hour=12, minute=1)
        after = datetime(year=2021, month=6, day=1, hour=12, minute=2)
        stored_config = config.Ingress(
            subdomain="hello",
            ip_whitelist=[IPv4Network("200.100.9.0/27")],
            last_updated=before,
            group_id=0,
        )
        s = state.State(configs={id: stored_config})
        expected_config = config.Ingress(
            subdomain=ingress_update.subdomain,
            ip_whitelist=ingress_update.ip_whitelist,
            last_updated=after,
            group_id=0,
        )

        event = s.upsert(id, ingress_update, after)

        self.assertEqual(s.configs, {id: expected_config})
        self.assertEqual(
            event,
            state.UpdateEvent(
                id=id,
                previous_config=stored_config,
                next_config=expected_config,
            ),
        )
 def _insert(self, id: config.Id, ingress_update: config.IngressUpdate,
             timestamp: datetime) -> UpdateEvent:
     group_id = self._next_group_id()
     next_config = config.Ingress(
         subdomain=ingress_update.subdomain,
         ip_whitelist=ingress_update.ip_whitelist,
         last_updated=timestamp,
         group_id=group_id,
     )
     self.configs[id] = next_config
     return UpdateEvent(
         id=id,
         previous_config=None,
         next_config=next_config,
     )
    def _update(self, id: config.Id, ingress_update: config.IngressUpdate,
                timestamp: datetime) -> UpdateEvent:
        previous_config = self.configs[id]
        if previous_config.has_updated_since(timestamp):
            raise UpdateConflictError("Config already updated")

        next_config = config.Ingress(
            subdomain=ingress_update.subdomain,
            ip_whitelist=ingress_update.ip_whitelist,
            group_id=previous_config.group_id,
            last_updated=timestamp,
        )

        self.configs[id] = next_config
        return UpdateEvent(
            id=id,
            previous_config=previous_config,
            next_config=next_config,
        )
    def test_upsert_conflict(self):
        id = "foo"
        ingress_update = config.IngressUpdate(
            subdomain="hello2",
            ip_whitelist=[
                IPv4Network("200.100.9.0/27"),
                IPv4Network("200.100.10.0/27"),
            ],
        )
        before = datetime(year=2021, month=6, day=1, hour=12, minute=1)
        after = datetime(year=2021, month=6, day=1, hour=12, minute=2)
        stored_config = config.Ingress(
            subdomain="hello",
            ip_whitelist=[IPv4Network("200.100.9.0/27")],
            last_updated=after,
            group_id=0,
        )
        s = state.State(configs={id: stored_config})

        with self.assertRaises(state.UpdateConflictError):
            s.upsert(id, ingress_update, before)

        self.assertEqual(s, state.State(configs={id: stored_config}))