Skip to content

Commit 523c2a8

Browse files
committed
src/cloud-prune: rework duration conversion, move to cosalib
Rework the duration parsing code to support days, weeks, months and years. Also use a regexp so we don't need the space. In preparation for the container garbage collection code, which will consume the same policy files, move the code to the shared cosalib. Also updates the parse_fcos_version to returns the stream id in a tuple along the build timestamp.
1 parent 398ee5a commit 523c2a8

File tree

2 files changed

+41
-22
lines changed

2 files changed

+41
-22
lines changed

src/cmd-cloud-prune

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@
66
# Example of policy.yaml
77
# rawhide:
88
# # all cloud images
9-
# cloud-uploads: 2 years
9+
# cloud-uploads: 2y
1010
# # artifacts in meta.json's `images` key
11-
# images: 2 years
11+
# images: 2y
1212
# images-keep: [qemu, live-iso]
13-
# build: 3 years
13+
# build: 3y
14+
# containers: 2w
1415
# The script also updates the builds.json for the respective stream by
1516
# adding the policy-cleanup key when we set the upload_builds_json flag.
1617
# It adds the relevant actions completed to that key
@@ -44,7 +45,8 @@ from cosalib.gcp import remove_gcp_image
4445
from cosalib.aws import deregister_aws_resource
4546
from cosalib.builds import BUILDFILES
4647
from cosalib.s3 import s3_copy
47-
from cosalib.cmdlib import parse_fcos_version_to_timestamp
48+
from cosalib.cmdlib import parse_fcos_version_to_timestamp_and_stream
49+
from cosalib.cmdlib import convert_duration_to_days
4850

4951
Build = collections.namedtuple("Build", ["id", "images", "arch", "meta_json"])
5052
# set metadata caching to 5m
@@ -105,17 +107,17 @@ def main():
105107
for action in ['cloud-uploads', 'images', 'build']:
106108
if action not in policy[stream]:
107109
continue
108-
duration = get_period_in_months(policy[stream][action])
109-
ref_date = today_date - relativedelta(months=int(duration))
110+
duration = convert_duration_to_days(policy[stream][action])
111+
ref_date = today_date - relativedelta(days=int(duration))
110112

111-
print(f"Pruning resources of type {action} older than {duration} months ({ref_date.date()}) on stream {stream}")
113+
print(f"Pruning resources of type {action} older than {policy[stream][action]} ({ref_date.date()}) on stream {stream}")
112114
# Enumerating in reverse to go from the oldest build to the newest one
113115
for index, build in enumerate(reversed(builds_json_data["builds"])):
114116
build_id = build["id"]
115117
if action in build.get("policy-cleanup", []):
116118
print(f"Build {build_id} has already had {action} pruning completed")
117119
continue
118-
build_date = parse_fcos_version_to_timestamp(build_id)
120+
(build_date, _) = parse_fcos_version_to_timestamp_and_stream(build_id)
119121

120122
if build_date >= ref_date:
121123
break
@@ -172,8 +174,8 @@ def validate_policy(stream, policy):
172174
actions = policy[stream]
173175
if 'cloud-uploads' not in actions:
174176
raise Exception("Pruning for cloud-uploads must be set before we prune the builds")
175-
cloud_uploads_duration = get_period_in_months(actions["cloud-uploads"])
176-
build_duration = get_period_in_months(actions["build"])
177+
cloud_uploads_duration = convert_duration_to_days(actions["cloud-uploads"])
178+
build_duration = convert_duration_to_days(actions["build"])
177179
if cloud_uploads_duration > build_duration:
178180
raise Exception("Duration of pruning cloud-uploads must be less than or equal to pruning a build")
179181

@@ -286,15 +288,5 @@ def delete_gcp_image(build, cloud_config, dry_run):
286288
return errors
287289

288290

289-
def get_period_in_months(duration):
290-
val, unit = duration.split(maxsplit=1)
291-
if unit in ["years", "year", "y"]:
292-
return int(val) * 12
293-
elif unit in ["months", "month", "m"]:
294-
return int(val)
295-
else:
296-
raise Exception(f"Duration unit provided is {unit}. Pruning duration is only supported in years and months")
297-
298-
299291
if __name__ == "__main__":
300292
main()

src/cosalib/cmdlib.py

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ def get_basearch():
339339
return get_basearch.saved
340340

341341

342-
def parse_fcos_version_to_timestamp(version):
342+
def parse_fcos_version_to_timestamp_and_stream(version):
343343
'''
344344
Parses an FCOS build ID and verifies the versioning is accurate. Then
345345
it verifies that the parsed timestamp has %Y%m%d format and returns that.
@@ -351,7 +351,34 @@ def parse_fcos_version_to_timestamp(version):
351351
timestamp = datetime.datetime.strptime(m.group(2), '%Y%m%d')
352352
except ValueError:
353353
raise Exception(f"FCOS build {version} has incorrect date format. It should be in (%Y%m%d)")
354-
return timestamp
354+
return (timestamp, int(m.group(3)))
355+
356+
357+
def convert_duration_to_days(duration_arg):
358+
"""
359+
Parses duration strings and convert them into days.
360+
The excpected format is Nd/D, nw/W, Nm/M, Ny/Y where N is a positive integer.
361+
The return value is the number of days represented, in integer format
362+
"""
363+
match = re.match(r'^([0-9]+)([dDmMyYwW])$', duration_arg)
364+
365+
if match is None:
366+
raise ValueError(f"Incorrect duration '{duration_arg}'. Valid values are in the form of 1d, 2w, 3m, 4y")
367+
368+
unit = match.group(2)
369+
value = int(match.group(1))
370+
match unit.lower():
371+
case "y":
372+
days = value * 365
373+
case "m":
374+
days = value * 30
375+
case "w":
376+
days = value * 7
377+
case "d":
378+
days = value
379+
case _:
380+
raise ValueError(f"Invalid unit '{match.group(2)}'. Please use y (years), m (months), w (weeks), or d (days).")
381+
return days
355382

356383

357384
def parse_date_string(date_string):

0 commit comments

Comments
 (0)