Skip to content

Commit b1190d8

Browse files
committed
Allow destroying RPAs without destroying consumers
1 parent 717e740 commit b1190d8

File tree

3 files changed

+62
-27
lines changed

3 files changed

+62
-27
lines changed

coral_credits/api/models.py

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -100,30 +100,15 @@ def __str__(self) -> str:
100100

101101
class Consumer(models.Model):
102102
consumer_ref = models.CharField(max_length=200)
103-
consumer_uuid = models.UUIDField()
104-
# Should protect against deletion with on_delete=models.DO_NOTHING but means can't
105-
# delete accounts with expired consumers so protected against in API instead
103+
consumer_uuid = models.UUIDField(unique=True)
106104
resource_provider_account = models.ForeignKey(
107-
ResourceProviderAccount, on_delete=models.CASCADE
105+
ResourceProviderAccount, on_delete=models.SET_NULL, null=True
108106
)
109107
user_ref = models.UUIDField()
110108
created = models.DateTimeField(auto_now_add=True)
111109
start = models.DateTimeField()
112110
end = models.DateTimeField()
113111

114-
class Meta:
115-
# TODO(tylerchristie): allow either/or nullable?
116-
# constraints = [
117-
# models.CheckConstraint(
118-
# check=Q(consumer_ref=False) | Q(consumer_uuid=False),
119-
# name='not_both_null'
120-
# )
121-
# ]
122-
unique_together = (
123-
"consumer_uuid",
124-
"resource_provider_account",
125-
)
126-
127112
def __str__(self) -> str:
128113
return (
129114
f"consumer ref:{self.consumer_ref} with "
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
resource_provider_name = "Test Provider"
2+
resource_provider_email = "[email protected]"
3+
resource_provider_info_url = "https://www.google.com"
4+
5+
accounts = []
6+
allocations = {}

tofu/tests/tofu_tests.py

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import os
55
from datetime import datetime
66
from dateutil.relativedelta import relativedelta
7+
import uuid
78

89
coral_uri = os.environ.get("TF_VAR_coral_uri")
910
headers = {"Authorization": "Bearer "+os.environ.get("TF_VAR_auth_token")}
@@ -19,7 +20,7 @@ def get_lease_request_json():
1920
"region_name": "RegionOne"
2021
},
2122
"lease": {
22-
"id": "e96b5a17-ada0-4034-a5ea-34db024b8e04",
23+
"id": str(uuid.uuid4()),
2324
"name": "my_new_lease",
2425
"start_date": start_time,
2526
"end_date": end_time,
@@ -46,14 +47,15 @@ def get_lease_request_json():
4647
def terraform_rest_setup():
4748
working_dir = os.path.join(os.path.dirname(__file__), "..")
4849
var_file = os.path.join(working_dir, "tests", "tofu_configs", "initial.tfvars")
50+
delete_file = os.path.join(working_dir, "tests", "tofu_configs", "empty.tfvars")
4951

5052
tf = Tofu(cwd=working_dir)
5153
tf.init()
5254
tf.apply(extra_args=["--var-file="+var_file])
5355

5456
yield tf
5557

56-
destroy = tf.apply(extra_args=["--var-file="+var_file],destroy=True)
58+
destroy = tf.apply(extra_args=["--var-file="+delete_file])
5759
assert len(destroy.errors) == 0
5860

5961
@pytest.fixture(scope="session")
@@ -78,7 +80,17 @@ def add_consumer_request(terraform_rest_setup):
7880
def try_delete_active_allocation(add_consumer_request):
7981
delete_file = os.path.join(os.path.dirname(__file__), "..", "tests", "tofu_configs", "delete-active.tfvars")
8082
try_delete = add_consumer_request["tf_workspace"].apply(extra_args=["--var-file="+delete_file])
81-
return len(try_delete.errors)
83+
return dict(error_count = len(try_delete.errors),tf_workspace = add_consumer_request["tf_workspace"])
84+
85+
@pytest.fixture(scope="session")
86+
def try_destroy_with_active_consumers(try_delete_active_allocation):
87+
all_file = os.path.join(os.path.dirname(__file__), "..", "tests", "tofu_configs", "initial.tfvars")
88+
delete_file = os.path.join(os.path.dirname(__file__), "..", "tests", "tofu_configs", "empty.tfvars")
89+
try_delete = try_delete_active_allocation["tf_workspace"].apply(extra_args=["--var-file="+delete_file])
90+
yield len(try_delete.errors)
91+
# Undo any destroys
92+
reapply = try_delete_active_allocation["tf_workspace"].apply(extra_args=["--var-file="+all_file])
93+
assert len(reapply.errors) == 0
8294

8395

8496
def api_get_request(resource):
@@ -151,18 +163,39 @@ def test_only_allocation_resources_returned(terraform_rest_setup):
151163
allocation_id = api_get_request("allocation")[0]["id"]
152164
assert len(api_get_request("allocation/"+str(allocation_id)+"/resources")) == 3
153165

154-
def test_resource_allocations_created(terraform_rest_setup):
166+
@pytest.mark.parametrize(
167+
"fixture_name, expected_resources",
168+
[
169+
(
170+
"terraform_rest_setup",
171+
{
172+
"Q1-0": {"VCPU": 40000, "MEMORY_MB": 4423680, "DISK_GB": 108000},
173+
"Q1-1": {"VCPU": 20000, "MEMORY_MB": 2000000, "DISK_GB": 200000},
174+
"Q2-0": {"VCPU": 80000, "MEMORY_MB": 8000000, "DISK_GB": 300000},
175+
},
176+
),
177+
(
178+
"add_consumer_request",
179+
{
180+
# q1-0 = original - resource hours requested for a month by lease
181+
"Q1-0": {"VCPU": 37120, "MEMORY_MB": 3703680, "DISK_GB": 82800},
182+
"Q1-1": {"VCPU": 20000, "MEMORY_MB": 2000000, "DISK_GB": 200000},
183+
"Q2-0": {"VCPU": 80000, "MEMORY_MB": 8000000, "DISK_GB": 300000},
184+
},
185+
),
186+
],
187+
)
188+
def test_resource_allocations_have_correct_resources(request, fixture_name,expected_resources):
189+
request.getfixturevalue(fixture_name) # needed to dynamically set fixtures
155190
allocations = api_get_request("allocation")
156191
allocation_resources = {
157192
a["name"]: to_resource_map(api_get_request("allocation/"+str(a["id"])+"/resources"))
158193
for a in allocations
159194
}
160-
assert allocation_resources["Q1-0"] == {"VCPU": 40000, "MEMORY_MB": 4423680, "DISK_GB": 108000}
161-
assert allocation_resources["Q1-1"] == {"VCPU": 20000, "MEMORY_MB": 2000000, "DISK_GB": 200000}
162-
assert allocation_resources["Q2-0"] == {"VCPU": 80000, "MEMORY_MB": 8000000, "DISK_GB": 300000}
195+
assert allocation_resources["Q1-0"] == expected_resources["Q1-0"]
196+
assert allocation_resources["Q1-1"] == expected_resources["Q1-1"]
197+
assert allocation_resources["Q2-0"] == expected_resources["Q2-0"]
163198

164-
def test_resources_consumed_by_consumers(add_consumer_request):
165-
raise NotImplementedError()
166199

167200
def test_resources_still_consumed_after_consumer_delete():
168201
raise NotImplementedError()
@@ -174,11 +207,22 @@ def test_can_query_consumer(add_consumer_request):
174207
assert len(api_get_request("consumer")) == 1
175208

176209
def test_delete_allocation_with_consumer_forbidden(try_delete_active_allocation):
177-
assert try_delete_active_allocation > 0
210+
assert try_delete_active_allocation["error_count"] > 0
178211

179212
def test_delete_active_allocation_resources_fails(try_delete_active_allocation):
180213
allocations = api_get_request("allocation")
181214
q1_allocations = [a for a in allocations if a["name"][:2] == "Q1"]
182215
for alloc in q1_allocations:
183216
tst = api_get_request("allocation/"+str(alloc["id"])+"/resources")
184217
assert len(tst) == 3
218+
219+
def test_destroy_with_consumers_fails(try_destroy_with_active_consumers):
220+
assert try_destroy_with_active_consumers > 0
221+
222+
def test_all_resources_fail_destroy_for_active_consumers(try_destroy_with_active_consumers):
223+
assert len(api_get_request("resource_class")) == 3
224+
assert len(api_get_request("resource_provider")) == 1
225+
assert len(api_get_request("account")) == 2
226+
assert len(api_get_request("resource_provider_account")) == 2
227+
assert len(api_get_request("allocation")) == 2 #Q2 has no active consumers so destroyed
228+
assert len(api_get_request("consumer")) == 1

0 commit comments

Comments
 (0)