Skip to content

Commit 5101f01

Browse files
add support for IPAM and Runtime Extension provider in tilt
1 parent aacbbc7 commit 5101f01

File tree

3 files changed

+45
-176
lines changed

3 files changed

+45
-176
lines changed

Tiltfile

Lines changed: 19 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -104,30 +104,30 @@ providers = {
104104
"internal",
105105
"third_party",
106106
],
107+
"label": "CAPD",
108+
# Add kubectl to the docker image, CAPD manager requires it.
107109
"additional_docker_helper_commands": "RUN curl -LO https://dl.k8s.io/release/{KUBE}/bin/linux/{ARCH}/kubectl && chmod +x ./kubectl && mv ./kubectl /usr/bin/kubectl".format(
108110
ARCH = os_arch,
109111
KUBE = kubernetes_version,
110112
),
111113
"additional_docker_build_commands": """
112114
COPY --from=tilt-helper /usr/bin/kubectl /usr/bin/kubectl
113115
""",
114-
"label": "CAPD",
115116
},
116-
}
117-
118-
# Create a data structure to hold information about addons.
119-
addons = {
120117
"test-extension": {
121-
"context": "./test/extension",
118+
"context": "test/extension",
122119
"image": "gcr.io/k8s-staging-cluster-api/test-extension",
123-
"container_name": "extension",
124-
"live_reload_deps": ["main.go", "handlers"],
120+
"live_reload_deps": [
121+
"main.go",
122+
"handlers",
123+
],
125124
"label": "test-extension",
126-
"resource_deps": ["capi_controller"],
125+
# Add the ExtensionConfig for this Runtime extension; given that the ExtensionConfig can be installed only when capi_controller
126+
# are up and running, it is required to set a resource_deps to ensure proper install order.
127127
"additional_resources": [
128128
"config/tilt/extensionconfig.yaml",
129-
"config/tilt/hookresponses-configmap.yaml",
130129
],
130+
"resource_deps": ["capi_controller"],
131131
},
132132
}
133133

@@ -165,27 +165,6 @@ def load_provider_tiltfiles():
165165
provider_config["go_main"] = "main.go"
166166
providers[provider_name] = provider_config
167167

168-
# load_addon_tiltfiles looks for tilt-addon.[yaml|json] files in the repositories listed in "addon_repos" in tilt settings and loads their config.
169-
def load_addon_tiltfiles():
170-
addon_repos = settings.get("addon_repos", [])
171-
for repo in addon_repos:
172-
file = repo + "/tilt-addon.yaml" if os.path.exists(repo + "/tilt-addon.yaml") else repo + "/tilt-addon.json"
173-
if not os.path.exists(file):
174-
fail("Failed to load provider. No tilt-addon.{yaml|json} file found in " + repo)
175-
addon_details = read_yaml(file, default = {})
176-
if type(addon_details) != type([]):
177-
addon_details = [addon_details]
178-
for item in addon_details:
179-
addon_name = item["name"]
180-
addon_config = item["config"]
181-
if "context" in addon_config:
182-
addon_config["context"] = repo + "/" + addon_config["context"]
183-
else:
184-
addon_config["context"] = repo
185-
if "go_main" not in addon_config:
186-
addon_config["go_main"] = "main.go"
187-
addons[addon_name] = addon_config
188-
189168
tilt_helper_dockerfile_header = """
190169
# Tilt image
191170
FROM golang:1.19.0 as tilt-helper
@@ -312,7 +291,6 @@ def get_port_forwards(debug):
312291
# 2. Configures a docker build for the provider, with live updating of the manager binary
313292
# 3. Runs kustomize for the provider's config/default and applies it
314293
def enable_provider(name, debug):
315-
deployment_kind = "provider"
316294
p = providers.get(name)
317295
label = p.get("label")
318296

@@ -336,77 +314,26 @@ def enable_provider(name, debug):
336314
port_forwards = port_forwards,
337315
)
338316

317+
additional_objs = []
318+
p_resources = p.get("additional_resources", [])
319+
for resource in p_resources:
320+
k8s_yaml(p.get("context") + "/" + resource)
321+
additional_objs = additional_objs + decode_yaml_stream(read_file(p.get("context") + "/" + resource))
322+
339323
if p.get("kustomize_config", True):
340-
yaml = read_file("./.tiltbuild/yaml/{}.{}.yaml".format(name, deployment_kind))
324+
yaml = read_file("./.tiltbuild/yaml/{}.provider.yaml".format(name))
341325
k8s_yaml(yaml)
342326
objs = decode_yaml_stream(yaml)
343327
k8s_resource(
344328
workload = find_object_name(objs, "Deployment"),
345-
objects = [find_object_qualified_name(objs, "Provider")],
329+
objects = [find_object_qualified_name(objs, "Provider")] + find_all_objects_names(additional_objs),
346330
new_name = label.lower() + "_controller",
347331
labels = [label, "ALL.controllers"],
348332
port_forwards = port_forwards,
349333
links = links,
350-
resource_deps = ["provider_crd"],
351-
)
352-
353-
# Configures an addon by doing the following:
354-
#
355-
# 1. Enables a local_resource go build of the addon's manager binary
356-
# 2. Configures a docker build for the addon, with live updating of the binary
357-
# 3. Runs kustomize for the addons's config/default and applies it
358-
def enable_addon(name, debug):
359-
addon = addons.get(name)
360-
deployment_kind = "addon"
361-
label = addon.get("label")
362-
port_forwards, links = get_port_forwards(debug)
363-
364-
build_go_binary(
365-
context = addon.get("context"),
366-
reload_deps = addon.get("live_reload_deps"),
367-
debug = debug,
368-
go_main = addon.get("go_main", "main.go"),
369-
binary_name = "extension",
370-
label = label,
371-
)
372-
373-
build_docker_image(
374-
image = addon.get("image"),
375-
context = addon.get("context"),
376-
binary_name = "extension",
377-
additional_docker_helper_commands = addon.get("additional_docker_helper_commands", ""),
378-
additional_docker_build_commands = addon.get("additional_docker_build_commands", ""),
379-
port_forwards = port_forwards,
380-
)
381-
382-
additional_objs = []
383-
addon_resources = addon.get("additional_resources", [])
384-
for resource in addon_resources:
385-
k8s_yaml(addon.get("context") + "/" + resource)
386-
additional_objs = additional_objs + decode_yaml_stream(read_file(addon.get("context") + "/" + resource))
387-
388-
if addon.get("kustomize_config", True):
389-
yaml = read_file("./.tiltbuild/yaml/{}.{}.yaml".format(name, deployment_kind))
390-
objs = decode_yaml_stream(yaml)
391-
k8s_yaml(yaml)
392-
k8s_resource(
393-
workload = find_object_name(objs, "Deployment"),
394-
new_name = label.lower() + "_addon",
395-
labels = [label, "ALL.addons"],
396-
port_forwards = port_forwards,
397-
links = links,
398-
objects = find_all_objects_names(additional_objs),
399-
resource_deps = addon.get("resource_deps", {}),
334+
resource_deps = ["provider_crd"] + p.get("resource_deps", []),
400335
)
401336

402-
def enable_addons():
403-
for name in get_addons():
404-
enable_addon(name, settings.get("debug").get(name, {}))
405-
406-
def get_addons():
407-
user_enable_addons = settings.get("enable_addons", [])
408-
return {k: "" for k in user_enable_addons}.keys()
409-
410337
def find_object_name(objs, kind):
411338
for o in objs:
412339
if o["kind"] == kind:
@@ -634,8 +561,6 @@ include_user_tilt_files()
634561

635562
load_provider_tiltfiles()
636563

637-
load_addon_tiltfiles()
638-
639564
prepare_all()
640565

641566
deploy_provider_crds()
@@ -644,6 +569,4 @@ deploy_observability()
644569

645570
enable_providers()
646571

647-
enable_addons()
648-
649572
cluster_templates()

docs/book/src/developer/tilt.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -338,8 +338,13 @@ you are interested in testing clusterctl workflows, you should refer to the
338338

339339
The following providers are currently defined in the Tiltfile:
340340

341-
* **core**: cluster-api itself (Cluster/Machine/MachineDeployment/MachineSet/KubeadmConfig/KubeadmControlPlane)
342-
* **docker**: Docker provider (DockerCluster/DockerMachine)
341+
* **core**: cluster-api itself
342+
* **kubeadm-bootstrap**: kubeadm bootstrap provider
343+
* **kubeadm-control-plane**: kubeadm control-plane provider
344+
* **docker**: Docker infrastructure provider
345+
* **test-extension**: Runtime extension used by CAPI E2E tests
346+
347+
Additional providers can be added by following the procedure described in following paragraphs:
343348

344349
### tilt-provider configuration
345350

@@ -395,6 +400,12 @@ Set to `false` if your provider does not have a ./config folder or you do not wa
395400
in tilt version >= v0.22.2 (see https://blog.tilt.dev/2021/08/09/resource-grouping.html); as a convention,
396401
provider abbreviation should be used (CAPD, KCP etc.).
397402

403+
**additional_resources** ([]string, default=[]): A list of paths to yaml file to be loaded into the tilt cluster;
404+
e.g. use this to deploy an ExtensionConfig object for a RuntimeExtension provider.
405+
406+
**resource_deps** ([]string, default=[]): A list of tilt resource names to be installed before the current provider;
407+
e.g. set this to ["capi_controller"] to ensure that this provider gets installed after Cluster API.
408+
398409
## Customizing Tilt
399410

400411
If you need to customize Tilt's behavior, you can create files in cluster-api's `tilt.d` directory. This file is ignored

hack/tools/tilt-prepare/main.go

Lines changed: 13 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -77,22 +77,8 @@ type tiltSettings struct {
7777
DeployCertManager *bool `json:"deploy_cert_manager,omitempty"`
7878
DeployObservability []string `json:"deploy_observability,omitempty"`
7979
EnableProviders []string `json:"enable_providers,omitempty"`
80-
EnableAddons []string `json:"enable_addons,omitempty"`
8180
AllowedContexts []string `json:"allowed_contexts,omitempty"`
8281
ProviderRepos []string `json:"provider_repos,omitempty"`
83-
AddonRepos []string `json:"addon_repos,omitempty"`
84-
}
85-
86-
type addonSettings struct {
87-
Name string `json:"name,omitempty"`
88-
Config addonConfig `json:"config,omitempty"`
89-
}
90-
91-
type addonConfig struct {
92-
Image string `json:"image,omitempty"`
93-
ContainerName string `json:"container_name,omitempty"`
94-
BinaryName string `json:"binary_name,omitempty"`
95-
Context *string `json:"context"`
9682
}
9783

9884
type providerSettings struct {
@@ -277,6 +263,7 @@ func tiltResources(ctx context.Context, ts *tiltSettings) error {
277263
"kubeadm-bootstrap": "bootstrap/kubeadm",
278264
"kubeadm-control-plane": "controlplane/kubeadm",
279265
"docker": "test/infrastructure/docker",
266+
"test-extension": "test/extension",
280267
}
281268

282269
// Add all the provider paths to the providerpaths map
@@ -310,69 +297,9 @@ func tiltResources(ctx context.Context, ts *tiltSettings) error {
310297
tasks[providerName] = workloadTask(providerName, "provider", "manager", "manager", ts, fmt.Sprintf("%s/config/default", path), getProviderObj)
311298
}
312299

313-
addonPaths := map[string]string{}
314-
for _, repo := range ts.AddonRepos {
315-
addonContexts, err := loadAddon(repo)
316-
if err != nil {
317-
return err
318-
}
319-
for name, path := range addonContexts {
320-
addonPaths[name] = path
321-
}
322-
}
323-
324-
// Add an addon task for each repo defined using enableAddons in the tilt-settings file.
325-
for _, name := range ts.EnableAddons {
326-
if name == "test-extension" {
327-
tasks[name] = workloadTask(name, "addon", "extension", "extension", ts, fmt.Sprintf("%s/config/default", "./test/extension"), nil)
328-
continue
329-
}
330-
path, ok := addonPaths[name]
331-
if !ok {
332-
return errors.Errorf("failed to obtain path for the addon %s", name)
333-
}
334-
as, err := readAddonSettings(path)
335-
if err != nil {
336-
return err
337-
}
338-
tasks[as.Name] = workloadTask(name, "addon", "extension", as.Config.ContainerName, ts, fmt.Sprintf("%s/config/default", path), nil)
339-
}
340300
return runTaskGroup(ctx, "resources", tasks)
341301
}
342302

343-
func readAddonSettings(path string) (*addonSettings, error) {
344-
path, err := checkWorkloadFileFormat(path, "addon")
345-
if err != nil {
346-
return nil, err
347-
}
348-
content, err := os.ReadFile(path) //nolint:gosec
349-
if err != nil {
350-
return nil, err
351-
}
352-
as := &addonSettings{}
353-
if err := yaml.Unmarshal(content, as); err != nil {
354-
return nil, errors.Wrap(err, "failed to unmarshal tilt-addons content")
355-
}
356-
return as, nil
357-
}
358-
359-
func loadAddon(repo string) (map[string]string, error) {
360-
var contextPath string
361-
addonData, err := readAddonSettings(repo)
362-
if err != nil {
363-
return nil, err
364-
}
365-
addonContexts := map[string]string{}
366-
if addonData.Config.Context != nil {
367-
contextPath = repo + "/" + *addonData.Config.Context
368-
} else {
369-
contextPath = repo
370-
}
371-
addonContexts[addonData.Name] = contextPath
372-
373-
return addonContexts, nil
374-
}
375-
376303
func loadProviders(r string) (map[string]string, error) {
377304
var contextPath string
378305
providerData, err := readProviderSettings(r)
@@ -940,20 +867,28 @@ func getProviderObj(prefix string, objs []unstructured.Unstructured) (*unstructu
940867
clusterv1.ProviderLabelName)
941868
}
942869

943-
providerType := "CoreProvider"
870+
providerType := string(clusterctlv1.CoreProviderType)
944871
providerName := manifestLabel
945872
if strings.HasPrefix(manifestLabel, "infrastructure-") {
946-
providerType = "InfrastructureProvider"
873+
providerType = string(clusterctlv1.InfrastructureProviderType)
947874
providerName = manifestLabel[len("infrastructure-"):]
948875
}
949876
if strings.HasPrefix(manifestLabel, "bootstrap-") {
950-
providerType = "BootstrapProvider"
877+
providerType = string(clusterctlv1.BootstrapProviderType)
951878
providerName = manifestLabel[len("bootstrap-"):]
952879
}
953880
if strings.HasPrefix(manifestLabel, "control-plane-") {
954-
providerType = "ControlPlaneProvider"
881+
providerType = string(clusterctlv1.ControlPlaneProviderType)
955882
providerName = manifestLabel[len("control-plane-"):]
956883
}
884+
if strings.HasPrefix(manifestLabel, "ipam-") {
885+
providerType = string(clusterctlv1.IPAMProviderType)
886+
providerName = manifestLabel[len("ipam-"):]
887+
}
888+
if strings.HasPrefix(manifestLabel, "runtime-extension-") {
889+
providerType = string(clusterctlv1.RuntimeExtensionProviderType)
890+
providerName = manifestLabel[len("runtime-extension-"):]
891+
}
957892

958893
provider := &clusterctlv1.Provider{
959894
TypeMeta: metav1.TypeMeta{

0 commit comments

Comments
 (0)