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_delete_non_existent(self):
        s = state.State()

        event = s.delete("foo", datetime.now())

        self.assertIsNone(event)
        self.assertEqual(s, state.State())
    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_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}))
    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,
            ),
        )