Skip to content

Commit 44d1784

Browse files
Add feature flag for GEP-33 Capabilities support (#30)
* GEP-33 feature flag * fix lint * fix coderabbit * fix copilot * fix copilot v2
1 parent 4e0853c commit 44d1784

11 files changed

Lines changed: 801 additions & 401 deletions

File tree

.golangci.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ linters:
135135
# for github.com/sapcc/keppel et al
136136
- github.com/go-gorp/gorp/v3
137137
toolchain-forbidden: true
138-
go-version-pattern: 1\.\d+(\.0)?$
138+
go-version-pattern: 1\.\d+(\.\d+)?$
139139
gosec:
140140
excludes:
141141
# gosec wants us to set a short ReadHeaderTimeout to avoid Slowloris attacks, but doing so would expose us to Keep-Alive race conditions (see https://iximiuz.com/en/posts/reverse-proxy-http-keep-alive-and-502s/

cloudprofilesync/imageupdater.go

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,14 @@ import (
1717
func filterImages(log logr.Logger, versions []SourceImage) []SourceImage {
1818
filtered := make([]SourceImage, 0, len(versions))
1919
for _, version := range versions {
20-
_, err := semver.Parse(version.Version)
20+
versionStr := version.effectiveVersion()
21+
_, err := semver.Parse(versionStr)
2122
if err != nil {
22-
log.V(1).Info("skipping invalid version", "version", version.Version)
23+
log.V(1).Info("skipping invalid version", "version", versionStr)
2324
continue
2425
}
2526
if len(version.Architectures) == 0 {
26-
log.V(1).Info("skipping version with no architectures", "version", version.Version)
27+
log.V(1).Info("skipping version with no architectures", "version", versionStr)
2728
continue
2829
}
2930
filtered = append(filtered, version)
@@ -32,10 +33,11 @@ func filterImages(log logr.Logger, versions []SourceImage) []SourceImage {
3233
}
3334

3435
type ImageUpdater struct {
35-
Log logr.Logger
36-
Source Source
37-
Provider Provider
38-
ImageName string
36+
Log logr.Logger
37+
Source Source
38+
Provider Provider
39+
ImageName string
40+
EnableCapabilities bool
3941
}
4042

4143
func (iu *ImageUpdater) Update(ctx context.Context, cpSpec *gardenerv1beta1.CloudProfileSpec) error {
@@ -48,6 +50,9 @@ func (iu *ImageUpdater) Update(ctx context.Context, cpSpec *gardenerv1beta1.Clou
4850
// in the source images may lead to a changed order in the CloudProfile,
4951
// causing unnecesscary reconciliations.
5052
slices.SortFunc(sourceImages, func(a, b SourceImage) int {
53+
if c := cmp.Compare(a.effectiveVersion(), b.effectiveVersion()); c != 0 {
54+
return c
55+
}
5156
return cmp.Compare(a.Version, b.Version)
5257
})
5358
imageIndex := slices.IndexFunc(cpSpec.MachineImages, func(img gardenerv1beta1.MachineImage) bool {
@@ -62,7 +67,9 @@ func (iu *ImageUpdater) Update(ctx context.Context, cpSpec *gardenerv1beta1.Clou
6267
for idx, version := range image.Versions {
6368
existingVersions[version.Version] = idx
6469
}
70+
6571
for _, sourceImage := range sourceImages {
72+
// Always write the full tag version (legacy path, safe for running Shoots).
6673
if idx, exists := existingVersions[sourceImage.Version]; exists {
6774
image.Versions[idx].Architectures = sourceImage.Architectures
6875
} else {
@@ -72,8 +79,30 @@ func (iu *ImageUpdater) Update(ctx context.Context, cpSpec *gardenerv1beta1.Clou
7279
},
7380
Architectures: sourceImage.Architectures,
7481
})
82+
existingVersions[sourceImage.Version] = len(image.Versions) - 1
83+
}
84+
85+
// When capabilities are enabled, also write the clean version entry.
86+
if iu.EnableCapabilities && sourceImage.CleanVersion != "" && sourceImage.CleanVersion != sourceImage.Version {
87+
if idx, exists := existingVersions[sourceImage.CleanVersion]; exists {
88+
existing := &image.Versions[idx]
89+
for _, arch := range sourceImage.Architectures {
90+
if !slices.Contains(existing.Architectures, arch) {
91+
existing.Architectures = append(existing.Architectures, arch)
92+
}
93+
}
94+
} else {
95+
image.Versions = append(image.Versions, gardenerv1beta1.MachineImageVersion{
96+
ExpirableVersion: gardenerv1beta1.ExpirableVersion{
97+
Version: sourceImage.CleanVersion,
98+
},
99+
Architectures: slices.Clone(sourceImage.Architectures),
100+
})
101+
existingVersions[sourceImage.CleanVersion] = len(image.Versions) - 1
102+
}
75103
}
76104
}
105+
77106
if iu.Provider != nil {
78107
if err := iu.Provider.Configure(cpSpec, sourceImages); err != nil {
79108
return fmt.Errorf("failed to invoke provider: %w", err)

0 commit comments

Comments
 (0)