diff --git a/tests/test_children.py b/tests/test_children.py index 21a6287..ecacf56 100644 --- a/tests/test_children.py +++ b/tests/test_children.py @@ -37,13 +37,13 @@ def test_valid_children(self): "children": [{"key": "gis", "purpose": "The purpose.", "notes": "Some notes.", "filters": "tags:gis"}] } """ - self.assertEqual(len(Twine(source=source)._children), 1) + self.assertEqual(len(Twine(source=source).children), 1) def test_empty_children(self): """ Ensures that a twine file will validate with an empty list object as children """ twine = Twine(source="""{"children": []}""") - self.assertEqual(len(twine._children), 0) + self.assertEqual(len(twine.children), 0) class TestChildrenValidation(BaseTestCase): @@ -58,7 +58,15 @@ class TestChildrenValidation(BaseTestCase): VALID_CHILD_VALUE = """ [ - {"key": "gis", "id": "some-id", "uri_env_name": "NAME_OF_SOME_ENV_VAR_THAT_CONTAINS_A_URI"} + { + "key": "gis", + "id": "some-id", + "backend": { + "name": "GCPPubSubBackend", + "project_name": "my-project", + "credentials_filename": "hello.json" + } + } ] """ @@ -79,6 +87,13 @@ def test_extra_children(self): with self.assertRaises(exceptions.InvalidValuesContents): Twine().validate_children(source=self.VALID_CHILD_VALUE) + def test_backend_cannot_be_empty(self): + """ Test that the backend field of a child cannot be empty. """ + single_child_missing_backend = """[{"key": "gis", "id": "some-id", "backend": {}}]""" + + with self.assertRaises(exceptions.InvalidValuesContents): + Twine().validate_children(source=single_child_missing_backend) + def test_extra_key_validation_on_empty_twine(self): """ Test that children with extra data will not raise a validation error on an empty twine. """ @@ -101,7 +116,11 @@ def test_extra_key_validation_on_valid_twine(self): { "key": "gis", "id": "some-id", - "uri_env_name": "SOME_ENV_VAR_NAME", + "backend": { + "name": "GCPPubSubBackend", + "project_name": "my-project", + "credentials_filename": "hello.json" + }, "some_extra_property": "should not be a problem if present" } ] diff --git a/twined/schema/children_schema.json b/twined/schema/children_schema.json index 6f84192..4aa0368 100644 --- a/twined/schema/children_schema.json +++ b/twined/schema/children_schema.json @@ -8,15 +8,36 @@ "type": "string" }, "id": { - "description": "The universally unique ID of the running child twin", + "description": "The universally unique ID (UUID) of the running child twin", "type": "string" }, - "uri_env_name": { - "description": "Name of the environment variable containing the URI of the twin (which may contain credentials)", - "type": "string", - "pattern": "^[A-Z]+(?:_[A-Z]+)*$" + "backend": { + "description": "The backend running the child.", + "type": "object", + "oneOf": [ + { + "type": "object", + "title": "GCP Pub/Sub", + "properties": { + "name": { + "description": "Type of backend (in this case, it can only be GCPPubSubBackend)", + "type": "string", + "pattern": "^(GCPPubSubBackend)$" + }, + "project_name": { + "description": "Name of the Google Cloud Platform (GCP) project the child exists in.", + "type": "string" + }, + "credentials_filename": { + "description": "Absolute path to Google Cloud Platform credentials JSON file.", + "type": "string" + } + }, + "required": ["name", "project_name", "credentials_filename"] + } + ] } }, - "required": ["key", "id", "uri_env_name"] + "required": ["key", "id", "backend"] } } diff --git a/twined/twine.py b/twined/twine.py index 0ef56fe..2ac0d88 100644 --- a/twined/twine.py +++ b/twined/twine.py @@ -54,7 +54,7 @@ def __init__(self, **kwargs): """ Constructor for the twine class """ for name, strand in self._load_twine(**kwargs).items(): - setattr(self, "_" + name, strand) + setattr(self, name, strand) self._available_strands = tuple(trim_suffix(name, "_schema") for name in vars(self)) @@ -119,7 +119,7 @@ def _validate_against_schema(self, strand, data): else: if strand not in SCHEMA_STRANDS: raise exceptions.UnknownStrand(f"Unknown strand {strand}. Try one of {ALL_STRANDS}.") - schema_key = "_" + strand + "_schema" + schema_key = strand + "_schema" try: schema = getattr(self, schema_key) except AttributeError: @@ -178,14 +178,14 @@ def available_strands(self): """ return self._available_strands - def validate_children(self, **kwargs): + def validate_children(self, source, **kwargs): """ Validates that the children values, passed as either a file or a json string, are correct """ # TODO cache this loaded data keyed on a hashed version of kwargs - children = self._load_json("children", **kwargs) + children = self._load_json("children", source, **kwargs) self._validate_against_schema("children", children) - strand = getattr(self, "_children", []) + strand = getattr(self, "children", []) # Loop the children and accumulate values so we have an O(1) check children_keys = {} @@ -249,7 +249,7 @@ def validate_credentials(self, dotenv_path=None): # Loop through the required credentials to check for presence of each credentials = {} - for credential in getattr(self, "_credentials", []): + for credential in getattr(self, "credentials", []): name = credential["name"] default = credential.get("default", None) credentials[name] = os.environ.get(name, default)