Skip to content

Commit 8fb6845

Browse files
authored
Merge pull request #111 from deckhouse/feature/tagged-release-channel-propagation
[mirror] for `--deckhouse-tag` bundles, add release channels pointing to the tagged release to the bundle if possible
2 parents da0dae9 + f3fbc1d commit 8fb6845

File tree

7 files changed

+100
-19
lines changed

7 files changed

+100
-19
lines changed

internal/mirror/cmd/pull/flags.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ func addFlags(flagSet *pflag.FlagSet) {
6565
&DeckhouseTag,
6666
"deckhouse-tag",
6767
"",
68-
"Specific Deckhouse build tag to pull. Conflicts with --since-version. WARNING!: Clusters installed with this option will not be able to automatically update due to lack of release-channels information in bundle and, as such, will require special attention and manual intervention during updates.",
68+
"Specific Deckhouse build tag to pull. Conflicts with --since-version. If registry contains release channel image for specified tag, all release channels in the bundle will be pointed to it.",
6969
)
7070
flagSet.StringArrayVarP(
7171
&ModulesWhitelist,

internal/mirror/cmd/push/push.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,11 @@ func pushModules(pushParams *params.PushParams, logger params.Logger) error {
139139
logger.WarnLn(err)
140140
}
141141
}
142-
logger.InfoF("Modules pushed: %v", strings.Join(successfullyPushedModules, ", "))
142+
143+
if len(successfullyPushedModules) > 0 {
144+
logger.InfoF("Modules pushed: %v", strings.Join(successfullyPushedModules, ", "))
145+
}
146+
143147
return nil
144148
}
145149

internal/mirror/operations/pull_dkp.go

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package operations
1818

1919
import (
2020
"context"
21+
"errors"
2122
"fmt"
2223
"io"
2324
"maps"
@@ -65,7 +66,7 @@ func PullDeckhousePlatform(pullParams *params.PullParams, tagsToMirror []string)
6566
return err
6667
}
6768

68-
// We should not generate deckhousereleases.yaml manifest for bundles that don't have release channels
69+
// We should not generate deckhousereleases.yaml manifest for tag-based pulls
6970
if pullParams.DeckhouseTag == "" {
7071
if err = generateDeckhouseReleaseManifests(pullParams, tagsToMirror, imageLayouts, logger); err != nil {
7172
return err
@@ -88,12 +89,36 @@ func PullDeckhousePlatform(pullParams *params.PullParams, tagsToMirror []string)
8889
return fmt.Errorf("Pull Deckhouse images: %w", err)
8990
}
9091

91-
logger.InfoLn("Processing image indexes")
92-
for _, l := range imageLayouts.Layouts() {
93-
err = layouts.SortIndexManifests(l)
94-
if err != nil {
95-
return fmt.Errorf("Sorting index manifests of %s: %w", l, err)
92+
err = logger.Process("Processing image indexes", func() error {
93+
if pullParams.DeckhouseTag != "" {
94+
// If we are pulling some build by tag, propagate release channel image of it to all channels if it exists.
95+
releaseChannel, err := layouts.FindImageDescriptorByTag(imageLayouts.ReleaseChannel, pullParams.DeckhouseTag)
96+
switch {
97+
case errors.Is(err, layouts.ErrImageNotFound):
98+
logger.WarnLn("Registry does not contain release channels, release channels images will not be added to bundle")
99+
goto sortManifests
100+
case err != nil:
101+
return fmt.Errorf("Find release-%s channel descriptor: %w", pullParams.DeckhouseTag, err)
102+
}
103+
104+
for _, channel := range []string{"alpha", "beta", "early-access", "stable", "rock-solid"} {
105+
if err = layouts.TagImage(imageLayouts.ReleaseChannel, releaseChannel.Digest, channel); err != nil {
106+
return fmt.Errorf("tag release channel: %w", err)
107+
}
108+
}
109+
}
110+
111+
sortManifests:
112+
for _, l := range imageLayouts.AsList() {
113+
err = layouts.SortIndexManifests(l)
114+
if err != nil {
115+
return fmt.Errorf("Sorting index manifests of %s: %w", l, err)
116+
}
96117
}
118+
return nil
119+
})
120+
if err != nil {
121+
return fmt.Errorf("Processing image indexes: %w", err)
97122
}
98123

99124
if err = logger.Process("Pack Deckhouse images into platform.tar", func() error {

internal/mirror/operations/pull_modules.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ func PullModules(pullParams *params.PullParams, filter *modules.Filter) error {
8989
}
9090

9191
logger.InfoLn("Processing image indexes")
92-
for _, l := range imageLayouts.Layouts() {
92+
for _, l := range imageLayouts.AsList() {
9393
err = layouts.SortIndexManifests(l)
9494
if err != nil {
9595
return fmt.Errorf("Sorting index manifests of %s: %w", l, err)

internal/mirror/operations/pull_security.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ func PullSecurityDatabases(pullParams *params.PullParams) error {
5757
}
5858

5959
logger.InfoLn("Processing image indexes")
60-
for _, l := range imageLayouts.Layouts() {
60+
for _, l := range imageLayouts.AsList() {
6161
err = layouts.SortIndexManifests(l)
6262
if err != nil {
6363
return fmt.Errorf("Sorting index manifests of %s: %w", l, err)

pkg/libmirror/layouts/layouts.go

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package layouts
1818

1919
import (
2020
"encoding/json"
21+
"errors"
2122
"fmt"
2223
"os"
2324
"path"
@@ -75,8 +76,8 @@ func NewImageLayouts() *ImageLayouts {
7576
}
7677
}
7778

78-
// Layouts returns a list of layout.Path's in it. Undefined path's are not included in the list.
79-
func (l *ImageLayouts) Layouts() []layout.Path {
79+
// AsList returns a list of layout.Path's in it. Undefined path's are not included in the list.
80+
func (l *ImageLayouts) AsList() []layout.Path {
8081
layoutsValue := reflect.ValueOf(l).Elem()
8182
layoutPathType := reflect.TypeOf(layout.Path(""))
8283

@@ -284,7 +285,7 @@ func FindDeckhouseModulesImages(
284285
maps.Copy(moduleImageLayouts.ReleaseImages, releaseImages)
285286

286287
if len(moduleImageLayouts.ModuleImages) == 0 {
287-
return fmt.Errorf("found no releases matching filter for %s", module.Name)
288+
return fmt.Errorf("found no releases for %s", module.Name)
288289
}
289290

290291
layouts.Modules[module.Name] = moduleImageLayouts
@@ -293,6 +294,8 @@ func FindDeckhouseModulesImages(
293294
return nil
294295
}
295296

297+
var ErrImageNotFound = errors.New("image not found")
298+
296299
func FindImageByTag(l layout.Path, tag string) (v1.Image, error) {
297300
index, err := l.ImageIndex()
298301
if err != nil {
@@ -303,13 +306,62 @@ func FindImageByTag(l layout.Path, tag string) (v1.Image, error) {
303306
return nil, err
304307
}
305308

306-
for _, imageManifest := range indexManifest.Manifests {
307-
for key, value := range imageManifest.Annotations {
309+
for _, imageDescriptor := range indexManifest.Manifests {
310+
for key, value := range imageDescriptor.Annotations {
311+
if key == "org.opencontainers.image.ref.name" && strings.HasSuffix(value, ":"+tag) {
312+
return index.Image(imageDescriptor.Digest)
313+
}
314+
}
315+
}
316+
317+
return nil, ErrImageNotFound
318+
}
319+
320+
func FindImageDescriptorByTag(l layout.Path, tag string) (v1.Descriptor, error) {
321+
index, err := l.ImageIndex()
322+
if err != nil {
323+
return v1.Descriptor{}, err
324+
}
325+
indexManifest, err := index.IndexManifest()
326+
if err != nil {
327+
return v1.Descriptor{}, err
328+
}
329+
330+
for _, imageDescriptor := range indexManifest.Manifests {
331+
for key, value := range imageDescriptor.Annotations {
308332
if key == "org.opencontainers.image.ref.name" && strings.HasSuffix(value, ":"+tag) {
309-
return index.Image(imageManifest.Digest)
333+
return imageDescriptor, nil
334+
}
335+
}
336+
}
337+
338+
return v1.Descriptor{}, ErrImageNotFound
339+
}
340+
341+
func TagImage(l layout.Path, imageDigest v1.Hash, tag string) error {
342+
index, err := l.ImageIndex()
343+
if err != nil {
344+
return err
345+
}
346+
indexManifest, err := index.IndexManifest()
347+
if err != nil {
348+
return err
349+
}
350+
351+
for _, imageDescriptor := range indexManifest.Manifests {
352+
if imageDescriptor.Digest == imageDigest {
353+
imageRepo, _, found := strings.Cut(imageDescriptor.Annotations["org.opencontainers.image.ref.name"], ":")
354+
// If there is no ":" symbol in the image reference, then it must be a reference by digest and those are fine as is
355+
if found {
356+
imageDescriptor.Annotations["org.opencontainers.image.ref.name"] = imageRepo + ":" + tag
357+
}
358+
imageDescriptor.Annotations["io.deckhouse.image.short_tag"] = tag
359+
if err = l.AppendDescriptor(imageDescriptor); err != nil {
360+
return fmt.Errorf("append descriptor %s: %w", tag, err)
310361
}
362+
return nil
311363
}
312364
}
313365

314-
return nil, nil
366+
return ErrImageNotFound
315367
}

pkg/libmirror/layouts/layouts_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ func TestImagesLayoutsAllLayouts(t *testing.T) {
4949
},
5050
}
5151

52-
layouts := il.Layouts()
53-
require.Len(t, layouts, 7, "Layouts should return exactly the number of non-empty layouts defined within it")
52+
layouts := il.AsList()
53+
require.Len(t, layouts, 7, "AsList should return exactly the number of non-empty layouts defined within it")
5454
require.Contains(t, layouts, il.Deckhouse, "All non-empty layouts should be returned")
5555
require.Contains(t, layouts, il.ReleaseChannel, "All non-empty layouts should be returned")
5656
require.Contains(t, layouts, il.InstallStandalone, "All non-empty layouts should be returned")

0 commit comments

Comments
 (0)