Skip to content

Commit 1b3b49a

Browse files
authored
Merge pull request #430 from linguini-dev/feature/gcp-general-label-handling
Adds general label handling for GCP
2 parents 6b325c9 + f7aa90c commit 1b3b49a

File tree

2 files changed

+42
-23
lines changed

2 files changed

+42
-23
lines changed

ocw/lib/gce.py

+16-16
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,16 @@ def _delete_resource(self, api_call, resource_name, *_, **kwargs) -> None:
5656
self.compute_client().routes: "route",
5757
self.compute_client().subnetworks: "subnetwork",
5858
}.get(api_call, "resource")
59+
60+
# Get object details / metadata and check the labels
61+
resource_details = api_call().get(**kwargs).execute()
62+
labels = resource_details.get('labels', {})
63+
if labels:
64+
self.log_dbg(f"Resource {resource_type}/{resource_name} has these labels: {labels}")
65+
if 'pcw_ignore' in labels:
66+
self.log_info(f"Skipping deletion of {resource_type} {resource_name} due to 'pcw_ignore' label set on resource")
67+
return
68+
5969
if self.dry_run:
6070
self.log_info(f"Deletion of {resource_type} {resource_name} skipped due to dry run mode")
6171
return
@@ -177,29 +187,19 @@ def cleanup_disks(self) -> None:
177187
self.log_dbg(f"{len(disks)} disks found")
178188
for disk in disks:
179189
if self.is_outdated(parse(disk["creationTimestamp"]).astimezone(timezone.utc)):
180-
labels = disk.get('labels', [])
181-
pcw_ignore_tag = 'pcw_ignore' in labels
182-
if pcw_ignore_tag:
183-
self.log_dbg(f"Ignoring {disk['name']} due to 'pcw_ignore' label set to '1'")
184-
else:
185-
self._delete_resource(
186-
self.compute_client().disks, disk["name"], project=self.project, zone=zone, disk=disk["name"]
187-
)
190+
self._delete_resource(
191+
self.compute_client().disks, disk["name"], project=self.project, zone=zone, disk=disk["name"]
192+
)
188193

189194
def cleanup_images(self) -> None:
190195
self.log_dbg("Images cleanup")
191196
images = self._paginated(self.compute_client().images, project=self.project)
192197
self.log_dbg(f"{len(images)} images found")
193198
for image in images:
194199
if self.is_outdated(parse(image["creationTimestamp"]).astimezone(timezone.utc)):
195-
labels = image.get('labels', [])
196-
pcw_ignore_tag = 'pcw_ignore' in labels
197-
if pcw_ignore_tag:
198-
self.log_dbg(f"Ignoring {image['name']} due to 'pcw_ignore' label set to '1'")
199-
else:
200-
self._delete_resource(
201-
self.compute_client().images, image["name"], project=self.project, image=image["name"]
202-
)
200+
self._delete_resource(
201+
self.compute_client().images, image["name"], project=self.project, image=image["name"]
202+
)
203203

204204
def cleanup_firewalls(self) -> None:
205205
self.log_dbg("Firewalls cleanup")

tests/test_gce.py

+26-7
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,8 @@ def delete(self, *args, **kwargs):
5050
return MockRequest(None)
5151
raise ValueError("Unexpected delete request")
5252

53-
def get(self, project, region):
54-
def something():
55-
pass
56-
something.execute = lambda: self.responses
57-
return something
53+
def get(self, *args, **kwargs):
54+
return MockRequest()
5855

5956

6057
class MockClient:
@@ -111,6 +108,13 @@ def mocked_resource():
111108
], 'id': "id"}),
112109
MockRequest({'error': {'errors': [{'message': 'err message'}]},
113110
'warnings': [{'message': 'warning message'}]}),
111+
MockRequest({
112+
'items': [
113+
{'name': 'pcw_ignore', 'creationTimestamp': older_than_max_age, 'timeCreated': older_than_max_age,
114+
'network': 'mynetwork', 'labels': {'pcw_ignore': '1'}}
115+
], 'id': "id"
116+
}),
117+
MockRequest(), # on images().delete()
114118
None # on images().list_next()
115119
])
116120

@@ -142,7 +146,14 @@ def test_list_regions(gce):
142146
def test_list_zones(gce):
143147
gce.compute_client.regions = MockResource({'zones': ['somethingthatIdonotknow/RabbitHole']})
144148
gce.compute_client.list_zones = {'zones': ['somethingthatIdonotknow/RabbitHole']}
145-
assert gce.list_zones('Oxfordshire') == ['RabbitHole']
149+
150+
mock_region_response = {
151+
'zones': ['somethingthatIdonotknow/RabbitHole']
152+
}
153+
154+
# Mock the regions().get() method to return the mock response
155+
with patch.object(gce.compute_client.regions(), 'get', return_value=MockRequest(mock_region_response)):
156+
assert gce.list_zones('Oxfordshire') == ['RabbitHole']
146157

147158

148159
def _test_cleanup(gce, resource_type, cleanup_call, resources):
@@ -156,8 +167,10 @@ def _test_cleanup(gce, resource_type, cleanup_call, resources):
156167
cleanup_call()
157168
if gce.dry_run:
158169
assert resources.deleted_resources == []
159-
else:
170+
elif resources.get("labels") == "pcw_ignore":
160171
assert resources.deleted_resources == ['delete1', 'delete2']
172+
else:
173+
assert resources.deleted_resources == ['delete1', 'delete2', 'pcw_ignore']
161174

162175

163176
@mark.parametrize("dry_run", [True, False])
@@ -222,6 +235,12 @@ def test_cleanup_networks(gce, mocked_resource, dry_run):
222235
_test_cleanup(gce, "networks", gce.cleanup_networks, mocked_resource)
223236

224237

238+
@mark.parametrize("dry_run", [True, False])
239+
def test_pcw_ignore_label(gce, mocked_resource, dry_run):
240+
gce.dry_run = dry_run
241+
_test_cleanup(gce, "images", gce.cleanup_images, mocked_resource)
242+
243+
225244
def test_cleanup_all(gce):
226245
gce.cleanup_blobs = MagicMock()
227246
gce.cleanup_disks = MagicMock()

0 commit comments

Comments
 (0)