Skip to content

Commit 50f8896

Browse files
authored
build: Include Calico images in image list (#903)
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 Depends on #822.
1 parent 700ea07 commit 50f8896

File tree

3 files changed

+102
-44
lines changed

3 files changed

+102
-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: 97 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,53 @@ 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, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&clusterv1.Cluster{})
246+
if err != nil {
247+
return "", fmt.Errorf("failed to convert cluster to unstructured %w", err)
248+
}
249+
250+
templateInput := struct {
251+
Cluster map[string]interface{}
252+
}{
253+
Cluster: c,
254+
}
255+
256+
err = template.Must(template.New(defaultHelmAddonFilename).ParseFiles(f)).Execute(tempFile, &templateInput)
257+
if err != nil {
258+
return "", fmt.Errorf("failed to execute helm values template %w", err)
259+
}
260+
261+
return tempFile.Name(), nil
208262
// this uses the values from kustomize because the file at addons/cluster-autoscaler/values-template.yaml
209263
// is a file that is templated
210264
case "cluster-autoscaler":
211-
f := path.Join(carenChartDirectory, "addons", "cluster-autoscaler", defaultHelmAddonFilename)
212-
tempFile, _ := os.CreateTemp("", "")
265+
f := filepath.Join(carenChartDirectory, "addons", "cluster-autoscaler", defaultHelmAddonFilename)
266+
tempFile, err := os.CreateTemp("", "")
267+
if err != nil {
268+
return "", fmt.Errorf("failed to create temp file: %w", err)
269+
}
270+
213271
c := clusterv1.Cluster{
214272
ObjectMeta: metav1.ObjectMeta{
215273
Name: "tmplCluster",
@@ -227,25 +285,26 @@ func getValuesFileForChartIfNeeded(chartName, carenChartDirectory string) string
227285
Cluster: &c,
228286
}
229287

230-
template.Must(template.New(defaultHelmAddonFilename).ParseFiles(f)).Execute(tempFile, &templateInput)
231-
return tempFile.Name()
288+
err = template.Must(template.New(defaultHelmAddonFilename).ParseFiles(f)).Execute(tempFile, &templateInput)
289+
if err != nil {
290+
return "", fmt.Errorf("failed to execute helm values template %w", err)
291+
}
292+
293+
return tempFile.Name(), nil
232294
default:
233-
return ""
295+
return "", nil
234296
}
235297
}
236298

237299
func getImagesForChart(info *ChartInfo) ([]string, error) {
238300
images := pkg.Images{}
239301
images.SetChart(info.name)
240-
if info.repo != "" {
241-
images.RepoURL = info.repo
242-
}
302+
images.RepoURL = info.repo
243303
if info.valuesFile != "" {
244-
images.ValueFiles.Set(info.valuesFile)
245-
}
246-
if len(info.stringValues) > 0 {
247-
images.StringValues = info.stringValues
304+
_ = images.ValueFiles.Set(info.valuesFile)
248305
}
306+
images.StringValues = info.stringValues
307+
images.ExtraImagesFiles = info.extraImagesFiles
249308
// kubeVersion needs to be set for some addons
250309
images.KubeVersion = "v1.29.0"
251310
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)