Skip to content

Commit 0fe0c98

Browse files
committed
build: Include Calico images in image list
Calico images are deployed by the tigera-operator and as such are not discoverable by the helm list images plugin. Using the extra images file functionality of the helm list images plugin allows for adding these images as templated strings that will adapt with the chart version as it is updated in future. This commit also fixes up some other things: - Use `filepath` instead of `path` for portabiity - Output the image list to stdout from make to allow user to decide where to redirect list to - Omit changing dir from image list when running as goreleaser hook - Slightly more defensive when checkinbg errors
1 parent d5f53bd commit 0fe0c98

File tree

3 files changed

+99
-44
lines changed

3 files changed

+99
-44
lines changed

.goreleaser.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ before:
5656
- make template-helm-repository
5757
- |
5858
sh -ec 'if [ {{ .IsSnapshot }} == false ] ; then
59-
env CAREN_VERSION=v{{ trimprefix .Version "v" }} make list-images
59+
make --no-print-directory CAREN_VERSION=v{{ trimprefix .Version "v" }} list-images >caren-images.txt
6060
fi'
6161
6262
builds:

hack/tools/fetch-images/main.go

Lines changed: 94 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
"fmt"
1010
"io"
1111
"os"
12-
"path"
12+
"path/filepath"
1313
"slices"
1414
"strings"
1515
"text/template"
@@ -20,6 +20,7 @@ import (
2020
corev1 "k8s.io/api/core/v1"
2121
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2222
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
23+
"k8s.io/apimachinery/pkg/runtime"
2324
"k8s.io/apimachinery/pkg/util/yaml"
2425
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
2526
)
@@ -30,10 +31,11 @@ const (
3031
)
3132

3233
type ChartInfo struct {
33-
repo string
34-
name string
35-
valuesFile string
36-
stringValues []string
34+
repo string
35+
name string
36+
valuesFile string
37+
stringValues []string
38+
extraImagesFiles []string
3739
}
3840

3941
func main() {
@@ -47,9 +49,9 @@ func main() {
4749
flagSet.StringVar(&chartDirectory, "chart-directory", "",
4850
"path to chart directory for CAREN")
4951
flagSet.StringVar(&helmChartConfigMap, "helm-chart-configmap", "",
50-
"path to chart directory for CAREN")
52+
"path to helm chart configmap for CAREN")
5153
flagSet.StringVar(&carenVersion, "caren-version", "",
52-
"caren version for images override")
54+
"CAREN version for images override")
5355
err := flagSet.Parse(args[1:])
5456
if err != nil {
5557
fmt.Println("failed to parse args", err.Error())
@@ -66,7 +68,7 @@ func main() {
6668
os.Exit(1)
6769
}
6870
if chartDirectory == "" || helmChartConfigMap == "" {
69-
fmt.Println("chart-directory helm-chart-configmap must be set")
71+
fmt.Println("chart-directory and helm-chart-configmap must be set")
7072
os.Exit(1)
7173
}
7274
i := &ChartInfo{
@@ -97,15 +99,10 @@ func main() {
9799
}
98100

99101
func EnsureFullPath(filename string) (string, error) {
100-
if path.IsAbs(filename) {
101-
return filename, nil
102-
}
103-
wd, err := os.Getwd()
102+
fullPath, err := filepath.Abs(filename)
104103
if err != nil {
105-
return "", fmt.Errorf("failed to get wd: %w", err)
104+
return "", err
106105
}
107-
fullPath := path.Join(wd, filename)
108-
fullPath = path.Clean(fullPath)
109106
_, err = os.Stat(fullPath)
110107
if err != nil {
111108
return "", err
@@ -129,7 +126,7 @@ func getImagesForAddons(helmChartConfigMap, carenChartDirectory string) ([]strin
129126
if err != nil {
130127
return nil, fmt.Errorf("failed to unmarshal configmap to object %w", err)
131128
}
132-
images := []string{}
129+
var images []string
133130
for _, chartInfoRaw := range cm.Data {
134131
var settings HelmChartFromConfigMap
135132
err = yamlv2.Unmarshal([]byte(chartInfoRaw), &settings)
@@ -140,19 +137,24 @@ func getImagesForAddons(helmChartConfigMap, carenChartDirectory string) ([]strin
140137
name: settings.ChartName,
141138
repo: settings.Repository,
142139
}
143-
valuesFile := getValuesFileForChartIfNeeded(settings.ChartName, carenChartDirectory)
140+
valuesFile, err := getValuesFileForChartIfNeeded(settings.ChartName, carenChartDirectory)
141+
if err != nil {
142+
return nil, fmt.Errorf("failed to get values file for %s: %w", settings.ChartName, err)
143+
}
144144
if valuesFile != "" {
145145
info.valuesFile = valuesFile
146146
}
147-
if settings.ChartName == "aws-cloud-controller-manager" {
147+
148+
switch settings.ChartName {
149+
case "aws-cloud-controller-manager":
148150
values, err := getHelmValues(carenChartDirectory)
149151
if err != nil {
150152
return nil, err
151153
}
152154
awsImages, found, err := unstructured.NestedStringMap(values, "hooks", "ccm", "aws", "k8sMinorVersionToCCMVersion")
153155
if !found {
154156
return images, fmt.Errorf("failed to find k8sMinorVersionToCCMVersion from file %s",
155-
path.Join(carenChartDirectory, "values.yaml"))
157+
filepath.Join(carenChartDirectory, "values.yaml"))
156158
}
157159
if err != nil {
158160
return images, fmt.Errorf("failed to get map k8sMinorVersionToCCMVersion with error %w",
@@ -168,9 +170,33 @@ func getImagesForAddons(helmChartConfigMap, carenChartDirectory string) ([]strin
168170
}
169171
images = append(images, chartImages...)
170172
}
171-
// skip the to next addon because we got what we needed
173+
// skip to the next addon because we got what we needed
172174
continue
175+
case "tigera-operator":
176+
extraImagesFile, err := os.CreateTemp("", "")
177+
if err != nil {
178+
return nil, fmt.Errorf("failed to create temp file for extra Calico images: %w", err)
179+
}
180+
defer os.Remove(extraImagesFile.Name()) //nolint:gocritic // Won't be leaked.
181+
_, err = extraImagesFile.WriteString(`
182+
{{default "docker.io/" .Values.installation.registry }}calico/cni:{{ .Chart.Version }}
183+
{{default "docker.io/" .Values.installation.registry }}calico/kube-controllers:{{ .Chart.Version }}
184+
{{default "docker.io/" .Values.installation.registry }}calico/node:{{ .Chart.Version }}
185+
{{default "docker.io/" .Values.installation.registry }}calico/apiserver:{{ .Chart.Version }}
186+
{{default "docker.io/" .Values.installation.registry }}calico/pod2daemon-flexvol:{{ .Chart.Version }}
187+
{{default "docker.io/" .Values.installation.registry }}calico/typha:{{ .Chart.Version }}
188+
{{default "docker.io/" .Values.installation.registry }}calico/csi:{{ .Chart.Version }}
189+
{{default "docker.io/" .Values.installation.registry }}calico/node-driver-registrar:{{ .Chart.Version }}
190+
{{default "docker.io/" .Values.installation.registry }}calico/ctl:{{ .Chart.Version }}
191+
`)
192+
_ = extraImagesFile.Close()
193+
if err != nil {
194+
return nil, fmt.Errorf("failed to write to temp file for extra Calico images: %w", err)
195+
}
196+
197+
info.extraImagesFiles = append(info.extraImagesFiles, extraImagesFile.Name())
173198
}
199+
174200
chartImages, err := getImagesForChart(info)
175201
if err != nil {
176202
return nil, fmt.Errorf("failed to get images for %s with error %w", info.name, err)
@@ -181,7 +207,7 @@ func getImagesForAddons(helmChartConfigMap, carenChartDirectory string) ([]strin
181207
}
182208

183209
func getHelmValues(carenChartDirectory string) (map[string]interface{}, error) {
184-
values := path.Join(carenChartDirectory, "values.yaml")
210+
values := filepath.Join(carenChartDirectory, "values.yaml")
185211
valuesFile, err := os.Open(values)
186212
if err != nil {
187213
return nil, fmt.Errorf("failed to open file %s with %w", values, err)
@@ -195,21 +221,50 @@ func getHelmValues(carenChartDirectory string) (map[string]interface{}, error) {
195221
return m, nil
196222
}
197223

198-
func getValuesFileForChartIfNeeded(chartName, carenChartDirectory string) string {
224+
func getValuesFileForChartIfNeeded(chartName, carenChartDirectory string) (string, error) {
199225
switch chartName {
200226
case "nutanix-csi-storage":
201-
return path.Join(carenChartDirectory, "addons", "csi", "nutanix", defaultHelmAddonFilename)
227+
return filepath.Join(carenChartDirectory, "addons", "csi", "nutanix", defaultHelmAddonFilename), nil
202228
case "node-feature-discovery":
203-
return path.Join(carenChartDirectory, "addons", "nfd", defaultHelmAddonFilename)
229+
return filepath.Join(carenChartDirectory, "addons", "nfd", defaultHelmAddonFilename), nil
204230
case "snapshot-controller":
205-
return path.Join(carenChartDirectory, "addons", "csi", "snapshot-controller", defaultHelmAddonFilename)
231+
return filepath.Join(carenChartDirectory, "addons", "csi", "snapshot-controller", defaultHelmAddonFilename), nil
206232
case "cilium":
207-
return path.Join(carenChartDirectory, "addons", "cni", "cilium", defaultHelmAddonFilename)
233+
return filepath.Join(carenChartDirectory, "addons", "cni", "cilium", defaultHelmAddonFilename), nil
234+
// Calico values differ slightly per provider, but that does not have a material imapct on the images required
235+
// so we can use the default values file for AWS provider.
236+
case "tigera-operator":
237+
f := filepath.Join(carenChartDirectory, "addons", "cni", "calico", "aws", defaultHelmAddonFilename)
238+
tempFile, err := os.CreateTemp("", "")
239+
if err != nil {
240+
return "", fmt.Errorf("failed to create temp file: %w", err)
241+
}
242+
243+
// CAAPH uses unstructured internally, so we need to create an unstructured copy of a cluster
244+
// to pass to the CAAPH values template.
245+
c, _ := runtime.DefaultUnstructuredConverter.ToUnstructured(&clusterv1.Cluster{})
246+
247+
templateInput := struct {
248+
Cluster map[string]interface{}
249+
}{
250+
Cluster: c,
251+
}
252+
253+
err = template.Must(template.New(defaultHelmAddonFilename).ParseFiles(f)).Execute(tempFile, &templateInput)
254+
if err != nil {
255+
return "", fmt.Errorf("failed to execute helm values template %w", err)
256+
}
257+
258+
return tempFile.Name(), nil
208259
// this uses the values from kustomize because the file at addons/cluster-autoscaler/values-template.yaml
209260
// is a file that is templated
210261
case "cluster-autoscaler":
211-
f := path.Join(carenChartDirectory, "addons", "cluster-autoscaler", defaultHelmAddonFilename)
212-
tempFile, _ := os.CreateTemp("", "")
262+
f := filepath.Join(carenChartDirectory, "addons", "cluster-autoscaler", defaultHelmAddonFilename)
263+
tempFile, err := os.CreateTemp("", "")
264+
if err != nil {
265+
return "", fmt.Errorf("failed to create temp file: %w", err)
266+
}
267+
213268
c := clusterv1.Cluster{
214269
ObjectMeta: metav1.ObjectMeta{
215270
Name: "tmplCluster",
@@ -227,25 +282,26 @@ func getValuesFileForChartIfNeeded(chartName, carenChartDirectory string) string
227282
Cluster: &c,
228283
}
229284

230-
template.Must(template.New(defaultHelmAddonFilename).ParseFiles(f)).Execute(tempFile, &templateInput)
231-
return tempFile.Name()
285+
err = template.Must(template.New(defaultHelmAddonFilename).ParseFiles(f)).Execute(tempFile, &templateInput)
286+
if err != nil {
287+
return "", fmt.Errorf("failed to execute helm values template %w", err)
288+
}
289+
290+
return tempFile.Name(), nil
232291
default:
233-
return ""
292+
return "", nil
234293
}
235294
}
236295

237296
func getImagesForChart(info *ChartInfo) ([]string, error) {
238297
images := pkg.Images{}
239298
images.SetChart(info.name)
240-
if info.repo != "" {
241-
images.RepoURL = info.repo
242-
}
299+
images.RepoURL = info.repo
243300
if info.valuesFile != "" {
244-
images.ValueFiles.Set(info.valuesFile)
245-
}
246-
if len(info.stringValues) > 0 {
247-
images.StringValues = info.stringValues
301+
_ = images.ValueFiles.Set(info.valuesFile)
248302
}
303+
images.StringValues = info.stringValues
304+
images.ExtraImagesFiles = info.extraImagesFiles
249305
// kubeVersion needs to be set for some addons
250306
images.KubeVersion = "v1.29.0"
251307
images.SetRelease("sample")

make/addons.mk

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,7 @@ template-helm-repository: generate-mindthegap-repofile ## this is used by goreal
8787

8888
.PHONY: list-images
8989
list-images:
90-
cd hack/tools/fetch-images && go build
91-
./hack/tools/fetch-images/fetch-images \
92-
-chart-directory=./charts/cluster-api-runtime-extensions-nutanix/ \
93-
-helm-chart-configmap=./charts/cluster-api-runtime-extensions-nutanix/templates/helm-config.yaml \
94-
-caren-version=$(CAREN_VERSION) >> caren-images.txt
90+
cd hack/tools/fetch-images && go run . \
91+
-chart-directory=$(PWD)/charts/cluster-api-runtime-extensions-nutanix/ \
92+
-helm-chart-configmap=$(PWD)/charts/cluster-api-runtime-extensions-nutanix/templates/helm-config.yaml \
93+
-caren-version=$(CAREN_VERSION)

0 commit comments

Comments
 (0)