Skip to content

Commit 9929d16

Browse files
Add generic addon deployment config to tilt
Signed-off-by: killianmuldoon <[email protected]>
1 parent a661c90 commit 9929d16

File tree

8 files changed

+352
-114
lines changed

8 files changed

+352
-114
lines changed

Tiltfile

Lines changed: 172 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,22 @@ COPY --from=tilt-helper /usr/bin/kubectl /usr/bin/kubectl
113113
},
114114
}
115115

116+
# Create a data structure to hold information about addons.
117+
addons = {
118+
"test-extension": {
119+
"context": "./test/extension",
120+
"image": "gcr.io/k8s-staging-cluster-api/test-extension",
121+
"container_name": "extension",
122+
"live_reload_deps": ["main.go", "handlers"],
123+
"label": "test-extension",
124+
"resource_deps": ["capi_controller"],
125+
"additional_resources": [
126+
"config/tilt/extensionconfig.yaml",
127+
"config/tilt/hookresponses-configmap.yaml",
128+
],
129+
},
130+
}
131+
116132
def ensure_clusterctl():
117133
local("make clusterctl")
118134

@@ -128,6 +144,7 @@ def ensure_clusterctl():
128144
# ]
129145
# }
130146
# }
147+
131148
def load_provider_tiltfiles():
132149
provider_repos = settings.get("provider_repos", [])
133150

@@ -145,12 +162,31 @@ def load_provider_tiltfiles():
145162
provider_config["context"] = repo + "/" + provider_config["context"]
146163
else:
147164
provider_config["context"] = repo
148-
if "kustomize_config" not in provider_config:
149-
provider_config["kustomize_config"] = True
150165
if "go_main" not in provider_config:
151166
provider_config["go_main"] = "main.go"
152167
providers[provider_name] = provider_config
153168

169+
# load_addon_tiltfiles looks for tilt-addon.[yaml|json] files in the repositories listed in "addon_repos" in tilt settings and loads their config.
170+
def load_addon_tiltfiles():
171+
addon_repos = settings.get("addon_repos", [])
172+
for repo in addon_repos:
173+
file = repo + "/tilt-addon.yaml" if os.path.exists(repo + "/tilt-addon.yaml") else repo + "/tilt-addon.json"
174+
if not os.path.exists(file):
175+
fail("Failed to load provider. No tilt-addon.{yaml|json} file found in " + repo)
176+
addon_details = read_yaml(file, default = {})
177+
if type(addon_details) != type([]):
178+
addon_details = [addon_details]
179+
for item in addon_details:
180+
addon_name = item["name"]
181+
addon_config = item["config"]
182+
if "context" in addon_config:
183+
addon_config["context"] = repo + "/" + addon_config["context"]
184+
else:
185+
addon_config["context"] = repo
186+
if "go_main" not in addon_config:
187+
addon_config["go_main"] = "main.go"
188+
addons[addon_name] = addon_config
189+
154190
tilt_helper_dockerfile_header = """
155191
# Tilt image
156192
FROM golang:1.18.3 as tilt-helper
@@ -167,30 +203,12 @@ WORKDIR /
167203
COPY --from=tilt-helper /start.sh .
168204
COPY --from=tilt-helper /restart.sh .
169205
COPY --from=tilt-helper /go/bin/dlv .
170-
COPY manager .
206+
COPY $binary_name .
171207
"""
172208

173-
# Configures a provider by doing the following:
174-
#
175-
# 1. Enables a local_resource go build of the provider's manager binary
176-
# 2. Configures a docker build for the provider, with live updating of the manager binary
177-
# 3. Runs kustomize for the provider's config/default and applies it
178-
def enable_provider(name, debug):
179-
p = providers.get(name)
180-
context = p.get("context")
181-
go_main = p.get("go_main", "main.go")
182-
label = p.get("label", name)
183-
debug_port = int(debug.get("port", 0))
184-
185-
# Prefix each live reload dependency with context. For example, for if the context is
186-
# test/infra/docker and main.go is listed as a dep, the result is test/infra/docker/main.go. This adjustment is
187-
# needed so Tilt can watch the correct paths for changes.
188-
live_reload_deps = []
189-
for d in p.get("live_reload_deps", []):
190-
live_reload_deps.append(context + "/" + d)
191-
192-
# Set up a local_resource build of the provider's manager binary. The provider is expected to have a main.go in
193-
# manager_build_path or the main.go must be provided via go_main option. The binary is written to .tiltbuild/bin/manager.
209+
def build_go_binary(context, reload_deps, debug, go_main, binary_name, label):
210+
# Set up a local_resource build of a go binary. The target repo is expected to have a main.go in
211+
# the context path or the main.go must be provided via go_main option. The binary is written to .tiltbuild/bin/{$binary_name}.
194212
# TODO @randomvariable: Race detector mode only currently works on x86-64 Linux.
195213
# Need to switch to building inside Docker when architecture is mismatched
196214
race_detector_enabled = debug.get("race_detector", False)
@@ -205,6 +223,7 @@ def enable_provider(name, debug):
205223
build_options = ""
206224
ldflags = "-extldflags \"-static\""
207225

226+
debug_port = int(debug.get("port", 0))
208227
if debug_port != 0:
209228
# disable optimisations and include line numbers when debugging
210229
gcflags = "all=-N -l"
@@ -215,14 +234,22 @@ def enable_provider(name, debug):
215234
cgo_enabled = cgo_enabled,
216235
arch = os_arch,
217236
)
218-
build_cmd = "{build_env} go build {build_options} -gcflags '{gcflags}' -ldflags '{ldflags}' -o .tiltbuild/bin/manager {go_main}".format(
237+
238+
build_cmd = "{build_env} go build {build_options} -gcflags '{gcflags}' -ldflags '{ldflags}' -o .tiltbuild/bin/{binary_name} {go_main}".format(
219239
build_env = build_env,
220240
build_options = build_options,
221241
gcflags = gcflags,
222242
go_main = go_main,
223243
ldflags = ldflags,
244+
binary_name = binary_name,
224245
)
225246

247+
# Prefix each live reload dependency with context. For example, for if the context is
248+
# test/infra/docker and main.go is listed as a dep, the result is test/infra/docker/main.go. This adjustment is
249+
# needed so Tilt can watch the correct paths for changes.
250+
live_reload_deps = []
251+
for d in reload_deps:
252+
live_reload_deps.append(context + "/" + d)
226253
local_resource(
227254
label.lower() + "_binary",
228255
cmd = "cd {context};mkdir -p .tiltbuild/bin;{build_cmd}".format(
@@ -233,8 +260,8 @@ def enable_provider(name, debug):
233260
labels = [label, "ALL.binaries"],
234261
)
235262

236-
additional_docker_helper_commands = p.get("additional_docker_helper_commands", "")
237-
additional_docker_build_commands = p.get("additional_docker_build_commands", "")
263+
def build_docker_image(image, context, binary_name, additional_docker_build_commands, additional_docker_helper_commands, port_forwards):
264+
links = []
238265

239266
dockerfile_contents = "\n".join([
240267
tilt_helper_dockerfile_header,
@@ -243,9 +270,26 @@ def enable_provider(name, debug):
243270
additional_docker_build_commands,
244271
])
245272

273+
# Set up an image build for the provider. The live update configuration syncs the output from the local_resource
274+
# build into the container.
275+
docker_build(
276+
ref = image,
277+
context = context + "/.tiltbuild/bin/",
278+
dockerfile_contents = dockerfile_contents,
279+
build_args = {"binary_name": binary_name},
280+
target = "tilt",
281+
only = binary_name,
282+
live_update = [
283+
sync(context + "/.tiltbuild/bin/" + binary_name, "/" + binary_name),
284+
run("sh /restart.sh"),
285+
],
286+
)
287+
288+
def get_port_forwards(debug):
246289
port_forwards = []
247290
links = []
248291

292+
debug_port = int(debug.get("port", 0))
249293
if debug_port != 0:
250294
port_forwards.append(port_forward(debug_port, 30000))
251295

@@ -259,22 +303,40 @@ def enable_provider(name, debug):
259303
port_forwards.append(port_forward(profiler_port, 6060))
260304
links.append(link("http://localhost:" + str(profiler_port) + "/debug/pprof", "profiler"))
261305

262-
# Set up an image build for the provider. The live update configuration syncs the output from the local_resource
263-
# build into the container.
264-
docker_build(
265-
ref = p.get("image"),
266-
context = context + "/.tiltbuild/bin/",
267-
dockerfile_contents = dockerfile_contents,
268-
target = "tilt",
269-
only = "manager",
270-
live_update = [
271-
sync(context + "/.tiltbuild/bin/manager", "/manager"),
272-
run("sh /restart.sh"),
273-
],
306+
return port_forwards, links
307+
308+
# Configures a provider by doing the following:
309+
#
310+
# 1. Enables a local_resource go build of the provider's manager binary
311+
# 2. Configures a docker build for the provider, with live updating of the manager binary
312+
# 3. Runs kustomize for the provider's config/default and applies it
313+
def enable_provider(name, debug):
314+
deployment_kind = "provider"
315+
p = providers.get(name)
316+
label = p.get("label")
317+
318+
port_forwards, links = get_port_forwards(debug)
319+
320+
build_go_binary(
321+
context = p.get("context"),
322+
reload_deps = p.get("live_reload_deps"),
323+
debug = debug,
324+
go_main = p.get("go_main", "main.go"),
325+
binary_name = "manager",
326+
label = label,
327+
)
328+
329+
build_docker_image(
330+
image = p.get("image"),
331+
context = p.get("context"),
332+
binary_name = "manager",
333+
additional_docker_helper_commands = p.get("additional_docker_helper_commands", ""),
334+
additional_docker_build_commands = p.get("additional_docker_build_commands", ""),
335+
port_forwards = port_forwards,
274336
)
275337

276338
if p.get("kustomize_config", True):
277-
yaml = read_file("./.tiltbuild/yaml/{}.provider.yaml".format(name))
339+
yaml = read_file("./.tiltbuild/yaml/{}.{}.yaml".format(name, deployment_kind))
278340
k8s_yaml(yaml)
279341
objs = decode_yaml_stream(yaml)
280342
k8s_resource(
@@ -287,6 +349,63 @@ def enable_provider(name, debug):
287349
resource_deps = ["provider_crd"],
288350
)
289351

352+
# Configures an addon by doing the following:
353+
#
354+
# 1. Enables a local_resource go build of the addon's manager binary
355+
# 2. Configures a docker build for the addon, with live updating of the binary
356+
# 3. Runs kustomize for the addons's config/default and applies it
357+
def enable_addon(name, debug):
358+
addon = addons.get(name)
359+
deployment_kind = "addon"
360+
label = addon.get("label")
361+
port_forwards, links = get_port_forwards(debug)
362+
363+
build_go_binary(
364+
context = addon.get("context"),
365+
reload_deps = addon.get("live_reload_deps"),
366+
debug = debug,
367+
go_main = addon.get("go_main", "main.go"),
368+
binary_name = "extension",
369+
label = label,
370+
)
371+
372+
build_docker_image(
373+
image = addon.get("image"),
374+
context = addon.get("context"),
375+
binary_name = "extension",
376+
additional_docker_helper_commands = addon.get("additional_docker_helper_commands", ""),
377+
additional_docker_build_commands = addon.get("additional_docker_build_commands", ""),
378+
port_forwards = port_forwards,
379+
)
380+
381+
additional_objs = []
382+
addon_resources = addon.get("additional_resources", [])
383+
for resource in addon_resources:
384+
k8s_yaml(addon.get("context") + "/" + resource)
385+
additional_objs = additional_objs + decode_yaml_stream(read_file(addon.get("context") + "/" + resource))
386+
387+
if addon.get("kustomize_config", True):
388+
yaml = read_file("./.tiltbuild/yaml/{}.{}.yaml".format(name, deployment_kind))
389+
objs = decode_yaml_stream(yaml)
390+
k8s_yaml(yaml)
391+
k8s_resource(
392+
workload = find_object_name(objs, "Deployment"),
393+
new_name = label.lower() + "_addon",
394+
labels = [label, "ALL.addons"],
395+
port_forwards = port_forwards,
396+
links = links,
397+
objects = find_all_objects_names(additional_objs),
398+
resource_deps = addon.get("resource_deps", {}),
399+
)
400+
401+
def enable_addons():
402+
for name in get_addons():
403+
enable_addon(name, settings.get("debug").get(name, {}))
404+
405+
def get_addons():
406+
user_enable_addons = settings.get("enable_addons", [])
407+
return {k: "" for k in user_enable_addons}.keys()
408+
290409
def find_object_name(objs, kind):
291410
for o in objs:
292411
if o["kind"] == kind:
@@ -299,6 +418,15 @@ def find_object_qualified_name(objs, kind):
299418
return "{}:{}:{}".format(o["metadata"]["name"], kind, o["metadata"]["namespace"])
300419
return ""
301420

421+
def find_all_objects_names(objs):
422+
qualified_names = []
423+
for o in objs:
424+
if "namespace" in o["metadata"] and o["metadata"]["namespace"] != "":
425+
qualified_names = qualified_names + ["{}:{}:{}".format(o["metadata"]["name"], o["kind"], o["metadata"]["namespace"])]
426+
else:
427+
qualified_names = qualified_names + ["{}:{}".format(o["metadata"]["name"], o["kind"])]
428+
return qualified_names
429+
302430
# Users may define their own Tilt customizations in tilt.d. This directory is excluded from git and these files will
303431
# not be checked in to version control.
304432
def include_user_tilt_files():
@@ -503,6 +631,8 @@ include_user_tilt_files()
503631

504632
load_provider_tiltfiles()
505633

634+
load_addon_tiltfiles()
635+
506636
prepare_all()
507637

508638
deploy_provider_crds()
@@ -511,4 +641,6 @@ deploy_observability()
511641

512642
enable_providers()
513643

644+
enable_addons()
645+
514646
cluster_templates()

0 commit comments

Comments
 (0)