mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-11 05:06:36 +00:00
Production hosts carry objects from before the compose project was named after the entity: galaxyserver's mariadb, openldap and postgres networks have no project label, and echoserver's openldap_data volume is labelled svc-db-openldap, the role id older deploys passed as -p. The pre-flight stopped both deploys although compose reuses such networks and volumes with a warning. A network named after its entity now passes without a label or with a declaring role id, still checked against its subnet; a volume passes with a declaring role id as well. A container does not, because compose cannot see a container of another project and fails on its name. A label naming another project still stops the deploy, and the volume message now says compose would hand the role another project's data instead of claiming it refuses the volume. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
124 lines
4.4 KiB
Python
124 lines
4.4 KiB
Python
import unittest
|
|
|
|
from utils.preflight.ownership import labelled_ownership_errors, parse_labelled
|
|
|
|
DECLARED = {
|
|
"matomo": [("web-app-matomo", "matomo")],
|
|
"matomo_data": [("web-app-matomo", "matomo")],
|
|
"redis": [("svc-db-redis", "redis"), ("web-app-nextcloud", "nextcloud")],
|
|
}
|
|
|
|
|
|
class TestParseLabelled(unittest.TestCase):
|
|
def test_lines_split_into_name_project_and_namespace(self):
|
|
output = "matomo\tmatomo\t\nmatomo_matomo.1.abc\t\tmatomo\n\n"
|
|
self.assertEqual(
|
|
parse_labelled(output),
|
|
[("matomo", "matomo", ""), ("matomo_matomo.1.abc", "", "matomo")],
|
|
)
|
|
|
|
def test_a_container_with_several_names_yields_each(self):
|
|
self.assertEqual(
|
|
parse_labelled("matomo,web/matomo\tmatomo\t"),
|
|
[("matomo", "matomo", ""), ("web/matomo", "matomo", "")],
|
|
)
|
|
|
|
def test_a_line_without_three_fields_is_rejected(self):
|
|
with self.assertRaises(ValueError):
|
|
parse_labelled("matomo matomo")
|
|
|
|
|
|
class TestLabelledOwnershipErrors(unittest.TestCase):
|
|
def test_objects_labelled_with_their_entity_pass(self):
|
|
objects = [
|
|
("matomo", "matomo", ""),
|
|
("matomo_data", "", "matomo"),
|
|
]
|
|
self.assertEqual(labelled_ownership_errors("volume", objects, DECLARED), [])
|
|
|
|
def test_undeclared_objects_pass_whatever_their_labels(self):
|
|
objects = [("legacy", "", ""), ("bridge-helper", "other", "")]
|
|
self.assertEqual(labelled_ownership_errors("container", objects, DECLARED), [])
|
|
|
|
def test_any_declaring_entity_is_accepted(self):
|
|
objects = [("redis", "nextcloud", "")]
|
|
self.assertEqual(labelled_ownership_errors("container", objects, DECLARED), [])
|
|
|
|
def test_a_foreign_project_names_the_owner(self):
|
|
objects = [("matomo", "nextcloud", "")]
|
|
self.assertEqual(
|
|
labelled_ownership_errors("container", objects, DECLARED),
|
|
[
|
|
(
|
|
"container 'matomo' belongs to compose project 'nextcloud', "
|
|
"but it is the container of web-app-matomo (entity 'matomo')"
|
|
)
|
|
],
|
|
)
|
|
|
|
def test_a_container_without_labels_fails(self):
|
|
objects = [("matomo", "", "")]
|
|
self.assertEqual(
|
|
labelled_ownership_errors("container", objects, DECLARED),
|
|
[
|
|
(
|
|
"container 'matomo' belongs to no compose project or stack, "
|
|
"but it is the container of web-app-matomo (entity 'matomo')"
|
|
)
|
|
],
|
|
)
|
|
|
|
def test_a_volume_without_any_label_passes(self):
|
|
objects = [("matomo_data", "", "")]
|
|
self.assertEqual(labelled_ownership_errors("volume", objects, DECLARED), [])
|
|
|
|
def test_a_volume_labelled_with_its_role_id_passes(self):
|
|
self.assertEqual(
|
|
labelled_ownership_errors(
|
|
"volume", [("matomo_data", "web-app-matomo", "")], DECLARED
|
|
),
|
|
[],
|
|
)
|
|
|
|
def test_a_container_labelled_with_its_role_id_still_fails(self):
|
|
self.assertEqual(
|
|
labelled_ownership_errors(
|
|
"container", [("matomo", "web-app-matomo", "")], DECLARED
|
|
),
|
|
[
|
|
(
|
|
"container 'matomo' belongs to compose project 'web-app-matomo', "
|
|
"but it is the container of web-app-matomo (entity 'matomo')"
|
|
)
|
|
],
|
|
)
|
|
|
|
def test_a_volume_of_a_foreign_project_fails(self):
|
|
objects = [("matomo_data", "nextcloud", "")]
|
|
self.assertEqual(
|
|
labelled_ownership_errors("volume", objects, DECLARED),
|
|
[
|
|
(
|
|
"volume 'matomo_data' belongs to compose project 'nextcloud', "
|
|
"but it is the volume of web-app-matomo (entity 'matomo')"
|
|
)
|
|
],
|
|
)
|
|
|
|
def test_both_foreign_labels_and_every_owner_are_named(self):
|
|
objects = [("redis", "mailu", "mailu")]
|
|
self.assertEqual(
|
|
labelled_ownership_errors("container", objects, DECLARED),
|
|
[
|
|
(
|
|
"container 'redis' belongs to compose project 'mailu' and stack 'mailu', "
|
|
"but it is the container of svc-db-redis (entity 'redis') or "
|
|
"web-app-nextcloud (entity 'nextcloud')"
|
|
)
|
|
],
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|