-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathimageupdater.go
More file actions
85 lines (79 loc) · 2.69 KB
/
imageupdater.go
File metadata and controls
85 lines (79 loc) · 2.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
// SPDX-FileCopyrightText: 2025 SAP SE or an SAP affiliate company
// SPDX-License-Identifier: Apache-2.0
package cloudprofilesync
import (
"cmp"
"context"
"fmt"
"slices"
"github.com/blang/semver/v4"
gardenerv1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
"github.com/go-logr/logr"
)
func filterImages(log logr.Logger, versions []SourceImage) []SourceImage {
filtered := make([]SourceImage, 0, len(versions))
for _, version := range versions {
_, err := semver.Parse(version.Version)
if err != nil {
log.V(1).Info("skipping invalid version", "version", version.Version)
continue
}
if len(version.Architectures) == 0 {
log.V(1).Info("skipping version with no architectures", "version", version.Version)
continue
}
filtered = append(filtered, version)
}
return filtered
}
type ImageUpdater struct {
Log logr.Logger
Source Source
Provider Provider
ImageName string
}
func (iu *ImageUpdater) Update(ctx context.Context, cpSpec *gardenerv1beta1.CloudProfileSpec) error {
iu.Log.Info("checking source", "image", iu.ImageName)
sourceImages, err := iu.Source.GetVersions(ctx)
if err != nil {
return fmt.Errorf("failed to retrieve images version from oci registry: %w", err)
}
iu.Log.Info("checked source", "image", iu.ImageName)
sourceImages = filterImages(iu.Log, sourceImages)
// Images from a source arrive in no guaranteed order. A changed order
// in the source images may lead to a changed order in the CloudProfile,
// causing unnecesscary reconciliations.
slices.SortFunc(sourceImages, func(a, b SourceImage) int {
return cmp.Compare(a.Version, b.Version)
})
imageIndex := slices.IndexFunc(cpSpec.MachineImages, func(img gardenerv1beta1.MachineImage) bool {
return img.Name == iu.ImageName
})
if imageIndex == -1 {
cpSpec.MachineImages = append(cpSpec.MachineImages, gardenerv1beta1.MachineImage{Name: iu.ImageName})
imageIndex = len(cpSpec.MachineImages) - 1
}
image := &cpSpec.MachineImages[imageIndex]
existingVersions := make(map[string]int, len(image.Versions))
for idx, version := range image.Versions {
existingVersions[version.Version] = idx
}
for _, sourceImage := range sourceImages {
if idx, exists := existingVersions[sourceImage.Version]; exists {
image.Versions[idx].Architectures = sourceImage.Architectures
} else {
image.Versions = append(image.Versions, gardenerv1beta1.MachineImageVersion{
ExpirableVersion: gardenerv1beta1.ExpirableVersion{
Version: sourceImage.Version,
},
Architectures: sourceImage.Architectures,
})
}
}
if iu.Provider != nil {
if err := iu.Provider.Configure(cpSpec, sourceImages); err != nil {
return fmt.Errorf("failed to invoke provider: %w", err)
}
}
return nil
}