Skip to content

Commit ed453ce

Browse files
authored
Use latest upstream instead of k0s images (#936)
* Use latest images instead of k0s images
1 parent 6738f3b commit ed453ce

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+540
-938
lines changed

.github/workflows/ci.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -222,9 +222,9 @@ jobs:
222222
chmod +x ./output/bin/embedded-cluster
223223
./output/bin/embedded-cluster version metadata > version-metadata.json
224224
./output/bin/embedded-cluster version list-images > expected.txt
225-
echo "Found $(wc -l < expected.txt) images"
225+
printf "Expected images:\n$(cat expected.txt)\n"
226226
./output/bin/buildtools metadata extract-helm-chart-images --metadata-path version-metadata.json > images.txt
227-
echo "Found $(wc -l < images.txt) images"
227+
printf "Found images:\n$(cat images.txt)\n"
228228
missing_images=0
229229
while read img; do
230230
grep -q "$img" expected.txt || { echo "Missing image: $img" && missing_images=$((missing_images+1)) ; }

chainguard.mk

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,15 @@ apko-login:
6363
login -u "${USERNAME}" \
6464
--password "${PASSWORD}" "${REGISTRY}"
6565

66+
.PHONY: apko-print-pkg-version
67+
apko-print-pkg-version: ARCHS ?= amd64
68+
apko-print-pkg-version: apko-template check-env-PACKAGE_NAME
69+
cd build && \
70+
${APKO_CMD} show-packages apko.yaml --arch=${ARCHS} | \
71+
grep ${PACKAGE_NAME} | \
72+
cut -s -d" " -f2 | \
73+
head -n1
74+
6675
.PHONY: apko-output-image
6776
apko-output-image:
6877
@digest=$$(cut -s -d'@' -f2 build/digest); \
@@ -94,7 +103,7 @@ melange-template: check-env-MELANGE_CONFIG check-env-PACKAGE_VERSION
94103
.PHONY: apko-template
95104
apko-template: check-env-APKO_CONFIG check-env-PACKAGE_VERSION
96105
mkdir -p build
97-
envsubst '$${PACKAGE_NAME} $${PACKAGE_VERSION} $${UPSTREAM_VERSION}' < ${APKO_CONFIG} > build/apko.yaml
106+
envsubst '$${PACKAGE_VERSION}' < ${APKO_CONFIG} > build/apko.yaml
98107

99108
check-env-%:
100109
@ if [ "${${*}}" = "" ]; then \

cmd/buildtools/addon.go

Lines changed: 102 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,114 @@
11
package main
22

33
import (
4+
"context"
45
"fmt"
6+
"os"
57
"strings"
68

79
"github.com/Masterminds/semver/v3"
10+
"github.com/sirupsen/logrus"
811
)
912

1013
type addonComponent struct {
11-
getWolfiPackageName func(opts addonComponentOptions) string
12-
getWolfiPackageVersionComparison func(opts addonComponentOptions) string
13-
upstreamVersionInputOverride string
14-
useUpstreamImage bool
14+
name string
15+
getCustomImageName func(opts addonComponentOptions) (string, error)
16+
getWolfiPackageName func(opts addonComponentOptions) string
17+
getWolfiPackageVersion func(opts addonComponentOptions) string
18+
upstreamVersionInputOverride string
19+
useUpstreamImage bool
1520
}
1621

1722
type addonComponentOptions struct {
23+
ctx context.Context
1824
k0sVersion *semver.Version
1925
upstreamVersion *semver.Version
2026
latestK8sVersion *semver.Version
2127
}
2228

23-
func (c *addonComponent) getPackageNameAndVersion(wolfiAPKIndex []byte, upstreamVersion string) (string, string, error) {
29+
func (c *addonComponent) resolveImageRepoAndTag(ctx context.Context, image string) (string, string, error) {
30+
if c.useUpstreamImage {
31+
return c.resolveUpstreamImageRepoAndTag(ctx, image)
32+
}
33+
if c.getCustomImageName != nil {
34+
return c.resolveCustomImageRepoAndTag(ctx, c.getUpstreamVersion(image))
35+
}
36+
return c.resolveApkoImageRepoAndTag(ctx, c.getUpstreamVersion(image))
37+
}
38+
39+
func (c *addonComponent) getUpstreamVersion(image string) string {
40+
if c.upstreamVersionInputOverride != "" {
41+
if uv := os.Getenv(c.upstreamVersionInputOverride); uv != "" {
42+
logrus.Infof("using input override from %s: %s", c.upstreamVersionInputOverride, uv)
43+
return uv
44+
}
45+
}
46+
return TagFromImage(image)
47+
}
48+
49+
func (c *addonComponent) resolveUpstreamImageRepoAndTag(ctx context.Context, image string) (string, string, error) {
50+
digest, err := GetImageDigest(ctx, image)
51+
if err != nil {
52+
return "", "", fmt.Errorf("failed to get image %s digest: %w", image, err)
53+
}
54+
tag := fmt.Sprintf("%s@%s", TagFromImage(image), digest)
55+
repo := fmt.Sprintf("proxy.replicated.com/anonymous/%s", FamiliarImageName(RemoveTagFromImage(image)))
56+
return repo, tag, nil
57+
}
58+
59+
func (c *addonComponent) resolveCustomImageRepoAndTag(ctx context.Context, upstreamVersion string) (string, string, error) {
60+
k0sVersion, err := getK0sVersion()
61+
if err != nil {
62+
return "", "", fmt.Errorf("get k0s version: %w", err)
63+
}
64+
latestK8sVersion, err := GetLatestKubernetesVersion()
65+
if err != nil {
66+
return "", "", fmt.Errorf("get latest k8s version: %w", err)
67+
}
68+
customImage, err := c.getCustomImageName(addonComponentOptions{
69+
ctx: ctx,
70+
k0sVersion: k0sVersion,
71+
upstreamVersion: semver.MustParse(upstreamVersion),
72+
latestK8sVersion: latestK8sVersion,
73+
})
74+
if err != nil {
75+
return "", "", fmt.Errorf("failed to get image name for %s: %w", c.name, err)
76+
}
77+
digest, err := GetImageDigest(ctx, customImage)
78+
if err != nil {
79+
return "", "", fmt.Errorf("failed to get image %s digest: %w", customImage, err)
80+
}
81+
tag := fmt.Sprintf("%s@%s", TagFromImage(customImage), digest)
82+
repo := fmt.Sprintf("proxy.replicated.com/anonymous/%s", FamiliarImageName(RemoveTagFromImage(customImage)))
83+
return repo, tag, nil
84+
}
85+
86+
func (c *addonComponent) resolveApkoImageRepoAndTag(ctx context.Context, upstreamVersion string) (string, string, error) {
87+
packageName, packageVersion, err := c.getPackageNameAndVersion(ctx, upstreamVersion)
88+
if err != nil {
89+
return "", "", fmt.Errorf("failed to get package name and version constraint for %s: %w", c.name, err)
90+
}
91+
92+
logrus.Infof("building and publishing %s", c.name)
93+
94+
if err := ApkoBuildAndPublish(c.name, packageName, packageVersion); err != nil {
95+
return "", "", fmt.Errorf("failed to apko build and publish for %s: %w", c.name, err)
96+
}
97+
98+
builtImage, err := GetImageNameFromBuildFile()
99+
if err != nil {
100+
return "", "", fmt.Errorf("failed to get digest from build file: %w", err)
101+
}
102+
103+
parts := strings.SplitN(builtImage, ":", 2)
104+
if len(parts) != 2 {
105+
return "", "", fmt.Errorf("invalid image name: %s", builtImage)
106+
}
107+
108+
return fmt.Sprintf("proxy.replicated.com/anonymous/%s", FamiliarImageName(parts[0])), parts[1], nil
109+
}
110+
111+
func (c *addonComponent) getPackageNameAndVersion(ctx context.Context, upstreamVersion string) (string, string, error) {
24112
packageName := ""
25113
if c.getWolfiPackageName == nil {
26114
return packageName, strings.TrimPrefix(upstreamVersion, "v"), nil
@@ -38,29 +126,26 @@ func (c *addonComponent) getPackageNameAndVersion(wolfiAPKIndex []byte, upstream
38126

39127
if c.getWolfiPackageName != nil {
40128
packageName = c.getWolfiPackageName(addonComponentOptions{
129+
ctx: ctx,
41130
k0sVersion: k0sVersion,
42131
upstreamVersion: semver.MustParse(upstreamVersion),
43132
latestK8sVersion: latestK8sVersion,
44133
})
45134
}
46135

47-
comparison := latestPatchComparison(semver.MustParse(upstreamVersion))
48-
if c.getWolfiPackageVersionComparison != nil {
49-
comparison = c.getWolfiPackageVersionComparison(addonComponentOptions{
136+
packageVersion := latestPatchVersion(semver.MustParse(upstreamVersion))
137+
if c.getWolfiPackageVersion != nil {
138+
packageVersion = c.getWolfiPackageVersion(addonComponentOptions{
139+
ctx: ctx,
50140
k0sVersion: k0sVersion,
51141
upstreamVersion: semver.MustParse(upstreamVersion),
52142
latestK8sVersion: latestK8sVersion,
53143
})
54144
}
55-
constraints, err := semver.NewConstraint(comparison)
56-
if err != nil {
57-
return "", "", fmt.Errorf("failed to parse version constraint: %w", err)
58-
}
59-
60-
packageVersion, err := FindWolfiPackageVersion(wolfiAPKIndex, packageName, constraints)
61-
if err != nil {
62-
return "", "", fmt.Errorf("failed to find wolfi package version for %s=%s: %w", packageName, upstreamVersion, err)
63-
}
64145

65146
return packageName, packageVersion, nil
66147
}
148+
149+
func latestPatchVersion(s *semver.Version) string {
150+
return fmt.Sprintf("%d.%d", s.Major(), s.Minor())
151+
}

cmd/buildtools/adminconsole.go

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,25 @@ import (
1010
"github.com/urfave/cli/v2"
1111
)
1212

13+
var adminconsoleImageComponents = map[string]addonComponent{
14+
"docker.io/kotsadm/kotsadm": {
15+
name: "kotsadm",
16+
useUpstreamImage: true,
17+
},
18+
"docker.io/kotsadm/kotsadm-migrations": {
19+
name: "kotsadm-migrations",
20+
useUpstreamImage: true,
21+
},
22+
"docker.io/kotsadm/kurl-proxy": {
23+
name: "kurl-proxy",
24+
useUpstreamImage: true,
25+
},
26+
"docker.io/kotsadm/rqlite": {
27+
name: "rqlite",
28+
useUpstreamImage: true,
29+
},
30+
}
31+
1332
var updateAdminConsoleAddonCommand = &cli.Command{
1433
Name: "adminconsole",
1534
Usage: "Updates the Admin Console addon",
@@ -35,7 +54,7 @@ var updateAdminConsoleAddonCommand = &cli.Command{
3554
newmeta := release.AddonMetadata{
3655
Version: latest,
3756
Location: fmt.Sprintf("oci://proxy.replicated.com/anonymous/%s", upstream),
38-
Images: make(map[string]string),
57+
Images: make(map[string]release.AddonImage),
3958
}
4059

4160
values, err := release.GetValuesWithOriginalImages("adminconsole")
@@ -50,16 +69,19 @@ var updateAdminConsoleAddonCommand = &cli.Command{
5069
return fmt.Errorf("failed to get images from admin console chart: %w", err)
5170
}
5271

53-
logrus.Infof("fetching digest for images")
5472
for _, image := range images {
55-
sha, err := GetImageDigest(c.Context, image)
73+
component, ok := adminconsoleImageComponents[RemoveTagFromImage(image)]
74+
if !ok {
75+
return fmt.Errorf("no component found for image %s", image)
76+
}
77+
repo, tag, err := component.resolveImageRepoAndTag(c.Context, image)
5678
if err != nil {
57-
return fmt.Errorf("failed to get image %s digest: %w", image, err)
79+
return fmt.Errorf("failed to resolve image and tag for %s: %w", image, err)
80+
}
81+
newmeta.Images[component.name] = release.AddonImage{
82+
Repo: repo,
83+
Tag: tag,
5884
}
59-
logrus.Infof("image %s digest: %s", image, sha)
60-
tag := TagFromImage(image)
61-
image = RemoveTagFromImage(image)
62-
newmeta.Images[FamiliarImageName(image)] = fmt.Sprintf("%s@%s", tag, sha)
6385
}
6486

6587
logrus.Infof("saving addon manifest")

cmd/buildtools/embeddedclusteroperator.go

Lines changed: 14 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,14 @@ import (
1313
"github.com/urfave/cli/v2"
1414
)
1515

16-
var operatorImageComponents = map[string]string{
17-
"docker.io/replicated/embedded-cluster-operator-image": "embedded-cluster-operator",
18-
"docker.io/library/busybox": "utils",
19-
}
20-
21-
var operatorComponents = map[string]addonComponent{
22-
"embedded-cluster-operator": {
16+
var operatorImageComponents = map[string]addonComponent{
17+
"docker.io/replicated/embedded-cluster-operator-image": {
18+
name: "embedded-cluster-operator",
2319
useUpstreamImage: true,
2420
},
25-
"utils": {},
21+
"docker.io/library/busybox": {
22+
name: "utils",
23+
},
2624
}
2725

2826
var updateOperatorAddonCommand = &cli.Command{
@@ -91,13 +89,7 @@ func updateOperatorAddonImages(ctx context.Context, chartURL string, chartVersio
9189
newmeta := release.AddonMetadata{
9290
Version: chartVersion,
9391
Location: chartURL,
94-
Images: make(map[string]string),
95-
}
96-
97-
logrus.Infof("fetching wolfi apk index")
98-
wolfiAPKIndex, err := GetWolfiAPKIndex()
99-
if err != nil {
100-
return fmt.Errorf("failed to get APK index: %w", err)
92+
Images: make(map[string]release.AddonImage),
10193
}
10294

10395
values, err := release.GetValuesWithOriginalImages("embeddedclusteroperator")
@@ -120,59 +112,18 @@ func updateOperatorAddonImages(ctx context.Context, chartURL string, chartVersio
120112
}
121113

122114
for _, image := range images {
123-
logrus.Infof("updating image %s", image)
124-
125-
upstreamVersion := TagFromImage(image)
126-
imageNoTag := RemoveTagFromImage(image)
127-
128-
componentName, ok := operatorImageComponents[imageNoTag]
129-
if !ok {
130-
return fmt.Errorf("no component found for image %s", imageNoTag)
131-
}
132-
133-
component, ok := operatorComponents[componentName]
115+
component, ok := operatorImageComponents[RemoveTagFromImage(image)]
134116
if !ok {
135-
return fmt.Errorf("no component found for component name %s", componentName)
117+
return fmt.Errorf("no component found for image %s", image)
136118
}
137-
138-
if component.useUpstreamImage {
139-
logrus.Infof("fetching digest for image %s", image)
140-
sha, err := GetImageDigest(ctx, image)
141-
if err != nil {
142-
return fmt.Errorf("failed to get image %s digest: %w", image, err)
143-
}
144-
logrus.Infof("image %s digest: %s", image, sha)
145-
tag := TagFromImage(image)
146-
image = RemoveTagFromImage(image)
147-
newmeta.Images[FamiliarImageName(image)] = fmt.Sprintf("%s@%s", tag, sha)
148-
continue
149-
}
150-
151-
if component.upstreamVersionInputOverride != "" {
152-
v := os.Getenv(component.upstreamVersionInputOverride)
153-
if v != "" {
154-
logrus.Infof("using input override from %s: %s", component.upstreamVersionInputOverride, v)
155-
upstreamVersion = v
156-
}
157-
}
158-
159-
packageName, packageVersion, err := component.getPackageNameAndVersion(wolfiAPKIndex, upstreamVersion)
119+
repo, tag, err := component.resolveImageRepoAndTag(ctx, image)
160120
if err != nil {
161-
return fmt.Errorf("failed to get package name and version for %s: %w", componentName, err)
121+
return fmt.Errorf("failed to resolve image and tag for %s: %w", image, err)
162122
}
163-
164-
logrus.Infof("building and publishing %s, %s=%s", componentName, packageName, packageVersion)
165-
166-
if err := ApkoBuildAndPublish(componentName, packageName, packageVersion, upstreamVersion); err != nil {
167-
return fmt.Errorf("failed to apko build and publish for %s: %w", componentName, err)
168-
}
169-
170-
digest, err := GetDigestFromBuildFile()
171-
if err != nil {
172-
return fmt.Errorf("failed to get digest from build file: %w", err)
123+
newmeta.Images[component.name] = release.AddonImage{
124+
Repo: repo,
125+
Tag: tag,
173126
}
174-
175-
newmeta.Images[componentName] = fmt.Sprintf("%s@%s", packageVersion, digest)
176127
}
177128

178129
logrus.Infof("saving addon manifest")

0 commit comments

Comments
 (0)