Skip to content

Commit

Permalink
BUGFIX: resource container management during resource init (#110)
Browse files Browse the repository at this point in the history
* Fix resource container management during resource init
---------

Co-authored-by: TJ Murphy <[email protected]>
  • Loading branch information
teej and teej committed Sep 7, 2024
1 parent 2d481d0 commit c0ff78c
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 5 deletions.
59 changes: 59 additions & 0 deletions tests/test_resource_containers.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,62 @@ def test_resource_already_belongs_to_container():

with pytest.raises(ResourceHasContainerException):
schema2.add(view)


def test_resource_container_init():
# Explicitly set container chain - 1st degree links
db = res.Database(name="DB")
schema = res.Schema(name="SCH", database=db)
assert schema.container == db
assert str(schema.fqn) == "DB.SCH"
task = res.Task(name="TASK", schema=schema)
assert task.container == schema
assert task.container.container == db
assert str(task.fqn) == "DB.SCH.TASK"

# Explicitly set container chain - 2nd degree link
db = res.Database(name="DB")
schema = res.Schema(name="SCH", database=db)
assert schema.container == db
assert str(schema.fqn) == "DB.SCH"
task = res.Task(name="TASK", database=db, schema=schema)
assert task.container == schema
assert task.container.container == db
assert str(task.fqn) == "DB.SCH.TASK"

# Build container chain bottoms-up
db = res.Database(name="DB")
schema = res.Schema(name="SCH")
task = res.Task(name="TASK", database=db, schema=schema)
assert task.container == schema
assert task.container.container == db
assert str(task.fqn) == "DB.SCH.TASK"

# Init with fully qualified name
task = res.Task(name="DB.SCH.TASK")
assert task.container.name == "SCH"
assert task.container.container.name == "DB"
assert str(task.fqn) == "DB.SCH.TASK"

# Partially qualified name
task = res.Task(name="SCH.TASK")
assert task.container.name == "SCH"
assert str(task.fqn) == "SCH.TASK"

# Mix string-specified and object-specified container
db = "DB"
schema = res.Schema(name="SCH", database=db)
assert schema.container.name == db
assert str(schema.fqn) == "DB.SCH"
task = res.Task(name="TASK", database=db, schema=schema)
assert task.container == schema
assert task.container.container.name == db
assert str(task.fqn) == "DB.SCH.TASK"


def test_prevent_container_chaining_if_already_set():
db1 = res.Database(name="DB1")
db2 = res.Database(name="DB2")
schema = res.Schema(name="SCH", database=db1)
with pytest.raises(ResourceHasContainerException):
res.Task(name="TASK", database=db2, schema=schema)
29 changes: 29 additions & 0 deletions tests/test_resource_rendering.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import titan.resources as res


def test_resource_pointer_rendering():
db = res.Database(name="DB")
schema = res.Schema(name="SCH")
network_rule = res.NetworkRule(
name="TITAN_TEST_NETWORK_RULE",
type="IPV4",
value_list=["85.83.225.229"],
mode="INGRESS",
database=db,
schema=schema,
)

network_policy = res.NetworkPolicy(
name="TITAN_TEST_NETWORK_POLICY",
allowed_network_rule_list=[network_rule],
blocked_network_rule_list=None,
allowed_ip_list=None,
blocked_ip_list=None,
database=db,
schema=schema,
)
rendered = network_policy.create_sql()
assert (
rendered
== "CREATE NETWORK POLICY TITAN_TEST_NETWORK_POLICY ALLOWED_NETWORK_RULE_LIST = (DB.SCH.TITAN_TEST_NETWORK_RULE)"
)
16 changes: 11 additions & 5 deletions titan/resources/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -328,8 +328,8 @@ def _serialize(field, value):
elif isinstance(value, Resource):
if getattr(value, "serialize_inline", False):
return value.to_dict()
if hasattr(value._data, "name"):
return getattr(value._data, "name")
elif isinstance(value, NamedResource):
return str(value.fqn)
else:
raise Exception(f"Cannot serialize {value}")
elif isinstance(value, ParseableEnum):
Expand Down Expand Up @@ -376,10 +376,10 @@ def requires(self, *resources: "Resource"):

def _register_scope(self, database=None, schema=None):
if isinstance(database, str):
database: ResourceContainer = ResourcePointer(name=database, resource_type=ResourceType.DATABASE)
database = ResourcePointer(name=database, resource_type=ResourceType.DATABASE)

if isinstance(schema, str):
schema: ResourceContainer = ResourcePointer(name=schema, resource_type=ResourceType.SCHEMA)
schema = ResourcePointer(name=schema, resource_type=ResourceType.SCHEMA)
if database is not None:
database.add(schema)

Expand All @@ -389,9 +389,15 @@ def _register_scope(self, database=None, schema=None):
if database is not None:
database.add(self)

if isinstance(self.scope, SchemaScope):
elif isinstance(self.scope, SchemaScope):
if schema is not None:
schema.add(self)
if database is not None:
if schema.container is None:
database.add(schema)
elif schema.container != database:
raise ResourceHasContainerException(f"Schema {schema} does not belong to database {database}")

elif database is not None:
database.find(name="PUBLIC", resource_type=ResourceType.SCHEMA).add(self)

Expand Down

0 comments on commit c0ff78c

Please sign in to comment.