Skip to content

Commit cda52d3

Browse files
committed
Added pydantic to create a Track object so it becomes easier to manage. Wrote a module.tf parser.
1 parent 354882b commit cda52d3

File tree

11 files changed

+229
-119
lines changed

11 files changed

+229
-119
lines changed

ctf/deploy.py

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@
1111
from ctf.destroy import destroy
1212
from ctf.generate import generate
1313
from ctf.logger import LOG
14+
from ctf.models import Track
1415
from ctf.utils import (
1516
add_tracks_to_terraform_modules,
1617
check_git_lfs,
18+
does_track_require_build_container,
1719
find_ctf_root_directory,
1820
get_all_available_tracks,
1921
get_terraform_tracks_from_modules,
@@ -61,6 +63,18 @@ def deploy(
6163
if validate_track_can_be_deployed(track=track) and track in tracks
6264
)
6365

66+
tmp_tracks: set[Track] = set()
67+
for track in distinct_tracks:
68+
tmp_tracks.add(
69+
Track(
70+
name=track.name,
71+
remote=track.remote,
72+
production=track.production,
73+
require_build_container=does_track_require_build_container(track),
74+
)
75+
)
76+
distinct_tracks = tmp_tracks
77+
6478
add_tracks_to_terraform_modules(
6579
tracks=distinct_tracks - get_terraform_tracks_from_modules(),
6680
remote=remote,
@@ -84,7 +98,7 @@ def deploy(
8498
"git",
8599
"lfs",
86100
"pull",
87-
f"--include={','.join([os.path.join('challenges', track, 'ansible', '*') for track in distinct_tracks])}",
101+
f"--include={','.join([os.path.join('challenges', track.name, 'ansible', '*') for track in distinct_tracks])}",
88102
],
89103
check=True,
90104
)
@@ -106,6 +120,8 @@ def deploy(
106120
force = True
107121
destroy(tracks=tracks, production=production, remote=remote, force=force)
108122

123+
distinct_tracks = generate(tracks=tracks, production=production, remote=remote)
124+
109125
subprocess.run(
110126
args=[terraform_binary(), "apply", "-auto-approve"],
111127
cwd=os.path.join(find_ctf_root_directory(), ".deploy"),
@@ -120,17 +136,23 @@ def deploy(
120136
exit(code=0)
121137

122138
for track in distinct_tracks:
139+
if track.require_build_container:
140+
# TODO: Ansible build containers here
141+
142+
# TODO: Set the "build_container" OpenTofu variable to false in module.tf
143+
pass
144+
123145
if not os.path.exists(
124146
path=(
125147
path := os.path.join(
126-
find_ctf_root_directory(), "challenges", track, "ansible"
148+
find_ctf_root_directory(), "challenges", track.name, "ansible"
127149
)
128150
)
129151
):
130152
continue
131153

132154
run_ansible_playbook(
133-
remote=remote, production=production, track=track, path=path
155+
remote=remote, production=production, track=track.name, path=path
134156
)
135157

136158
if not production:
@@ -154,7 +176,7 @@ def deploy(
154176

155177
if remote == "local":
156178
LOG.debug(msg=f"Parsing track.yaml for track {track}")
157-
track_yaml = parse_track_yaml(track_name=track)
179+
track_yaml = parse_track_yaml(track_name=track.name)
158180

159181
for service in track_yaml["services"]:
160182
if service.get("dev_port_mapping"):
@@ -175,12 +197,12 @@ def deploy(
175197
"device",
176198
"add",
177199
machine_name,
178-
f"proxy-{track}-{service['dev_port_mapping']}-to-{service['port']}",
200+
f"proxy-{track.name}-{service['dev_port_mapping']}-to-{service['port']}",
179201
"proxy",
180202
f"listen=tcp:0.0.0.0:{service['dev_port_mapping']}",
181203
f"connect=tcp:127.0.0.1:{service['port']}",
182204
"--project",
183-
track,
205+
track.name,
184206
],
185207
cwd=path,
186208
check=True,
@@ -212,7 +234,7 @@ def deploy(
212234
msg=f"Running `incus project switch {tracks_list[track_index - 1]}`"
213235
)
214236
subprocess.run(
215-
args=["incus", "project", "switch", tracks_list[track_index - 1]],
237+
args=["incus", "project", "switch", tracks_list[track_index - 1].name],
216238
check=True,
217239
env=ENV,
218240
)

ctf/destroy.py

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
from ctf import ENV
99
from ctf.logger import LOG
10+
from ctf.models import Track
1011
from ctf.utils import (
1112
find_ctf_root_directory,
1213
get_terraform_tracks_from_modules,
@@ -60,8 +61,8 @@ def destroy(
6061

6162
total_deployed_tracks = len(terraform_tracks)
6263

63-
r = (
64-
subprocess.run(
64+
current_project = Track(
65+
name=subprocess.run(
6566
args=["incus", "project", "get-current"],
6667
check=True,
6768
capture_output=True,
@@ -71,16 +72,16 @@ def destroy(
7172
.strip()
7273
)
7374

74-
tmp_tracks = set(tracks)
75+
tmp_tracks: set[Track] = set(Track(name=x) for x in tracks)
7576
if tmp_tracks and tmp_tracks != terraform_tracks:
7677
terraform_tracks &= tmp_tracks
7778
if not terraform_tracks:
7879
LOG.warning("No track to destroy.")
7980
return
8081

81-
if r in terraform_tracks:
82-
projects = {
83-
project["name"]
82+
if current_project in terraform_tracks:
83+
projects: set[Track] = {
84+
Track(name=project["name"])
8485
for project in json.loads(
8586
s=subprocess.run(
8687
args=["incus", "project", "list", "--format=json"],
@@ -91,8 +92,8 @@ def destroy(
9192
)
9293
}
9394

94-
projects = list((projects - terraform_tracks))
95-
if len(projects) == 0:
95+
project_list = list((projects - terraform_tracks))
96+
if len(project_list) == 0:
9697
LOG.critical(
9798
msg="No project to switch to. This should never happen as the default should always exists."
9899
)
@@ -102,7 +103,7 @@ def destroy(
102103
"incus",
103104
"project",
104105
"switch",
105-
"default" if "default" in projects else projects[0],
106+
"default" if "default" in project_list else project_list[0].name,
106107
]
107108

108109
LOG.info(msg=f"Running `{' '.join(cmd)}`")
@@ -116,15 +117,15 @@ def destroy(
116117
*(
117118
[] # If every track needs to be destroyed, destroy everything including the network zone as well.
118119
if total_deployed_tracks == len(terraform_tracks)
119-
else [f"-target=module.track-{track}" for track in terraform_tracks]
120+
else [f"-target=module.track-{track.name}" for track in terraform_tracks]
120121
),
121122
],
122123
cwd=os.path.join(find_ctf_root_directory(), ".deploy"),
123124
check=False,
124125
)
125126

126-
projects = [
127-
project["name"]
127+
projects = {
128+
Track(name=project["name"])
128129
for project in json.loads(
129130
s=subprocess.run(
130131
args=["incus", "project", "list", "--format=json"],
@@ -133,10 +134,10 @@ def destroy(
133134
env=ENV,
134135
).stdout.decode()
135136
)
136-
]
137+
}
137138

138-
networks = [
139-
network["name"]
139+
networks = {
140+
Track(name=network["name"])
140141
for network in json.loads(
141142
s=subprocess.run(
142143
args=["incus", "network", "list", "--format=json"],
@@ -145,10 +146,10 @@ def destroy(
145146
env=ENV,
146147
).stdout.decode()
147148
)
148-
]
149+
}
149150

150-
network_acls = [
151-
network_acl["name"]
151+
network_acls = {
152+
Track(name=network_acl["name"])
152153
for network_acl in json.loads(
153154
s=subprocess.run(
154155
args=["incus", "network", "acl", "list", "--format=json"],
@@ -157,46 +158,46 @@ def destroy(
157158
env=ENV,
158159
).stdout.decode()
159160
)
160-
]
161+
}
161162

162163
for module in terraform_tracks:
163164
if module in projects:
164-
LOG.warning(msg=f"The project {module} was not destroyed properly.")
165+
LOG.warning(msg=f"The project {module.name} was not destroyed properly.")
165166
if (
166167
force
167168
or (input("Do you want to destroy it? [Y/n] ").lower() or "y") == "y"
168169
):
169170
subprocess.run(
170-
args=["incus", "project", "delete", module, "--force"],
171+
args=["incus", "project", "delete", module.name, "--force"],
171172
check=False,
172173
capture_output=True,
173174
input=b"yes\n",
174175
env=ENV,
175176
)
176177

177-
if (tmp_module := module[0:15]) in networks:
178-
LOG.warning(msg=f"The network {tmp_module} was not destroyed properly.")
178+
if (tmp_module_name := module.name[0:15]) in networks:
179+
LOG.warning(msg=f"The network {tmp_module_name} was not destroyed properly.")
179180
if (
180181
force
181182
or (input("Do you want to destroy it? [Y/n] ").lower() or "y") == "y"
182183
):
183184
subprocess.run(
184-
args=["incus", "network", "delete", tmp_module],
185+
args=["incus", "network", "delete", tmp_module_name],
185186
check=False,
186187
capture_output=True,
187188
env=ENV,
188189
)
189190

190191
if (tmp_module := module) in network_acls or (
191-
tmp_module := f"{module}-default"
192+
tmp_module := f"{module.name}-default"
192193
) in network_acls:
193-
LOG.warning(msg=f"The network ACL {tmp_module} was not destroyed properly.")
194+
LOG.warning(msg=f"The network ACL {tmp_module.name} was not destroyed properly.")
194195
if (
195196
force
196197
or (input("Do you want to destroy it? [Y/n] ").lower() or "y") == "y"
197198
):
198199
subprocess.run(
199-
args=["incus", "network", "acl", "delete", tmp_module],
200+
args=["incus", "network", "acl", "delete", tmp_module.name],
200201
check=False,
201202
capture_output=True,
202203
env=ENV,

ctf/flags.py

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,19 @@
22
import io
33
import json
44
import os
5-
from enum import StrEnum, unique
65

76
import rich
87
import typer
98
import yaml
109
from typing_extensions import Annotated
1110

1211
from ctf.logger import LOG
12+
from ctf.models import OutputFormat, Track
1313
from ctf.utils import find_ctf_root_directory, parse_track_yaml
1414

1515
app = typer.Typer()
1616

1717

18-
@unique
19-
class OutputFormat(StrEnum):
20-
JSON = "json"
21-
CSV = "csv"
22-
YAML = "yaml"
23-
24-
2518
@app.command(help="Get flags from tracks")
2619
def flags(
2720
tracks: Annotated[
@@ -37,7 +30,7 @@ def flags(
3730
typer.Option("--format", help="Output format", prompt="Output format"),
3831
] = OutputFormat.JSON,
3932
) -> None:
40-
distinct_tracks: set[str] = set()
33+
distinct_tracks: set[Track] = set()
4134

4235
for entry in os.listdir(
4336
path=(
@@ -50,17 +43,17 @@ def flags(
5043
s=(track_directory := os.path.join(challenges_directory, entry))
5144
) and os.path.exists(path=os.path.join(track_directory, "track.yaml")):
5245
if not tracks:
53-
distinct_tracks.add(entry)
46+
distinct_tracks.add(Track(name=entry))
5447
elif entry in tracks:
55-
distinct_tracks.add(entry)
48+
distinct_tracks.add(Track(name=entry))
5649

5750
flags = []
5851
for track in distinct_tracks:
59-
LOG.debug(msg=f"Parsing track.yaml for track {track}")
60-
track_yaml = parse_track_yaml(track_name=track)
52+
LOG.debug(msg=f"Parsing track.yaml for track {track.name}")
53+
track_yaml = parse_track_yaml(track_name=track.name)
6154

6255
if len(track_yaml["flags"]) == 0:
63-
LOG.debug(msg=f"No flag in track {track}. Skipping...")
56+
LOG.debug(msg=f"No flag in track {track.name}. Skipping...")
6457
continue
6558

6659
flags.extend(track_yaml["flags"])

ctf/generate.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@
66

77
from ctf import ENV
88
from ctf.logger import LOG
9+
from ctf.models import Track
910
from ctf.utils import (
1011
add_tracks_to_terraform_modules,
1112
create_terraform_modules_file,
13+
does_track_require_build_container,
1214
find_ctf_root_directory,
1315
get_all_available_tracks,
14-
load_yaml_file,
1516
terraform_binary,
1617
validate_track_can_be_deployed,
1718
)
@@ -41,10 +42,10 @@ def generate(
4142
remote: Annotated[
4243
str, typer.Option("--remote", help="Incus remote to deploy to")
4344
] = "local",
44-
) -> set[str]:
45+
) -> set[Track]:
4546
ENV["INCUS_REMOTE"] = remote
4647
# Get the list of tracks.
47-
distinct_tracks = set(
48+
distinct_tracks: set[Track] = set(
4849
track
4950
for track in get_all_available_tracks()
5051
if validate_track_can_be_deployed(track=track)
@@ -56,18 +57,17 @@ def generate(
5657
# Generate the Terraform modules file.
5758
create_terraform_modules_file(remote=remote, production=production)
5859

60+
tmp_tracks: set[Track] = set()
5961
for track in distinct_tracks:
60-
if os.path.isfile(
61-
build_yaml_file_path := os.path.join(
62-
find_ctf_root_directory(),
63-
"challenges",
64-
track,
65-
"ansible",
66-
"build.yaml",
62+
tmp_tracks.add(
63+
Track(
64+
name=track.name,
65+
remote=track.remote,
66+
production=track.production,
67+
require_build_container=does_track_require_build_container(track),
6768
)
68-
) and (build_yaml_file := load_yaml_file(build_yaml_file_path)) and build_yaml_file:
69-
#TODO: set build for track
70-
pass
69+
)
70+
distinct_tracks = tmp_tracks
7171

7272
add_tracks_to_terraform_modules(
7373
tracks=distinct_tracks,
@@ -80,7 +80,7 @@ def generate(
8080
os.path.join(find_ctf_root_directory(), ".deploy", "common"),
8181
(
8282
terraform_directory := os.path.join(
83-
find_ctf_root_directory(), "challenges", track, "terraform"
83+
find_ctf_root_directory(), "challenges", track.name, "terraform"
8484
)
8585
),
8686
)

0 commit comments

Comments
 (0)