Skip to content
This repository was archived by the owner on Jul 18, 2025. It is now read-only.

Commit a14ddbd

Browse files
authored
Merge pull request #564 from silvin-lubecki/fix-push-bundle
Fix pushing from bundle store
2 parents a804fb0 + dfb79ad commit a14ddbd

File tree

4 files changed

+88
-23
lines changed

4 files changed

+88
-23
lines changed

e2e/pushpull_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,27 @@ func TestPushInstallBundle(t *testing.T) {
269269
cmd.Command = dockerCli.Command("service", "ls")
270270
assert.Check(t, cmp.Contains(icmd.RunCmd(cmd).Assert(t, icmd.Success).Combined(), ref2))
271271
})
272+
273+
// push it again using an app pre-bundled and tagged in the bundle store and install it to check it is also available
274+
t.Run("push-bundleref", func(t *testing.T) {
275+
name := strings.Replace(t.Name(), "/", "_", 1)
276+
ref2 := ref + ":v0.42"
277+
// Create a new command so the bundle store can be trashed before installing the app
278+
cmd2, cleanup2 := dockerCli.createTestCmd()
279+
// bundle the app again but this time with a tag to store it into the bundle store
280+
cmd2.Command = dockerCli.Command("app", "bundle", "--tag", ref2, "-o", bundleFile, filepath.Join("testdata", "push-pull", "push-pull.dockerapp"))
281+
icmd.RunCmd(cmd2).Assert(t, icmd.Success)
282+
// Push the app without tagging it explicitly
283+
cmd2.Command = dockerCli.Command("app", "push", "--insecure-registries="+info.registryAddress, ref2)
284+
icmd.RunCmd(cmd2).Assert(t, icmd.Success)
285+
// remove the bundle from the bundle store to be sure it won't be used instead of registry
286+
cleanup2()
287+
// install from the registry
288+
cmd.Command = dockerCli.Command("app", "install", "--insecure-registries="+info.registryAddress, ref2, "--name", name)
289+
icmd.RunCmd(cmd).Assert(t, icmd.Success)
290+
cmd.Command = dockerCli.Command("service", "ls")
291+
assert.Check(t, cmp.Contains(icmd.RunCmd(cmd).Assert(t, icmd.Success).Combined(), ref))
292+
})
272293
})
273294
}
274295

internal/commands/cnab.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,9 @@ func extractAndLoadAppBasedBundle(dockerCli command.Cli, name string) (*bundle.B
251251
return bndl, "", err
252252
}
253253

254+
//resolveBundle looks for a CNAB bundle which can be in a Docker App Package format or
255+
// a bundle stored locally or in the bundle store. It returns a built or found bundle,
256+
// a reference to the bundle if it is found in the bundlestore, and an error.
254257
func resolveBundle(dockerCli command.Cli, bundleStore appstore.BundleStore, name string, pullRef bool, insecureRegistries []string) (*bundle.Bundle, string, error) {
255258
// resolution logic:
256259
// - if there is a docker-app package in working directory, or an http:// / https:// prefix, use packager.Extract result

internal/commands/push.go

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -72,32 +72,46 @@ func pushCmd(dockerCli command.Cli) *cobra.Command {
7272

7373
func runPush(dockerCli command.Cli, name string, opts pushOptions) error {
7474
defer muteDockerCli(dockerCli)()
75-
76-
bundleStore, err := prepareBundleStore()
75+
// Get the bundle
76+
bndl, ref, err := resolveReferenceAndBundle(dockerCli, name)
7777
if err != nil {
7878
return err
7979
}
80-
81-
bndl, _, err := resolveBundle(dockerCli, bundleStore, name, false, nil)
80+
// Retag invocation image if needed
81+
retag, err := shouldRetagInvocationImage(metadata.FromBundle(bndl), bndl, opts.tag, ref)
8282
if err != nil {
8383
return err
8484
}
85-
if err := bndl.Validate(); err != nil {
85+
if retag.shouldRetag {
86+
if err := retagInvocationImage(dockerCli, bndl, retag.invocationImageRef.String()); err != nil {
87+
return err
88+
}
89+
}
90+
// Push the invocation image
91+
if err := pushInvocationImage(dockerCli, retag); err != nil {
8692
return err
8793
}
94+
// Push the bundle
95+
return pushBundle(dockerCli, opts, bndl, retag)
96+
}
8897

89-
retag, err := shouldRetagInvocationImage(metadata.FromBundle(bndl), bndl, opts.tag)
98+
func resolveReferenceAndBundle(dockerCli command.Cli, name string) (*bundle.Bundle, string, error) {
99+
bundleStore, err := prepareBundleStore()
90100
if err != nil {
91-
return err
101+
return nil, "", err
92102
}
93-
if retag.shouldRetag {
94-
err := retagInvocationImage(dockerCli, bndl, retag.invocationImageRef.String())
95-
if err != nil {
96-
return err
97-
}
103+
104+
bndl, ref, err := resolveBundle(dockerCli, bundleStore, name, false, nil)
105+
if err != nil {
106+
return nil, "", err
107+
}
108+
if err := bndl.Validate(); err != nil {
109+
return nil, "", err
98110
}
111+
return bndl, ref, err
112+
}
99113

100-
// pushing invocation image
114+
func pushInvocationImage(dockerCli command.Cli, retag retagResult) error {
101115
repoInfo, err := registry.ParseRepositoryInfo(retag.invocationImageRef)
102116
if err != nil {
103117
return err
@@ -113,10 +127,13 @@ func runPush(dockerCli command.Cli, name string, opts pushOptions) error {
113127
return errors.Wrapf(err, "starting push of %q", retag.invocationImageRef.String())
114128
}
115129
defer reader.Close()
116-
if err = jsonmessage.DisplayJSONMessagesStream(reader, ioutil.Discard, 0, false, nil); err != nil {
130+
if err := jsonmessage.DisplayJSONMessagesStream(reader, ioutil.Discard, 0, false, nil); err != nil {
117131
return errors.Wrapf(err, "pushing to %q", retag.invocationImageRef.String())
118132
}
133+
return nil
134+
}
119135

136+
func pushBundle(dockerCli command.Cli, opts pushOptions, bndl *bundle.Bundle, retag retagResult) error {
120137
resolver := remotes.CreateResolver(dockerCli.ConfigFile(), opts.registry.insecureRegistries...)
121138
var display fixupDisplay = &plainDisplay{out: os.Stdout}
122139
if term.IsTerminal(os.Stdout.Fd()) {
@@ -129,9 +146,7 @@ func runPush(dockerCli command.Cli, name string, opts pushOptions) error {
129146
fixupOptions = append(fixupOptions, remotes.WithComponentImagePlatforms(platforms))
130147
}
131148
// bundle fixup
132-
err = remotes.FixupBundle(context.Background(), bndl, retag.cnabRef, resolver, fixupOptions...)
133-
134-
if err != nil {
149+
if err := remotes.FixupBundle(context.Background(), bndl, retag.cnabRef, resolver, fixupOptions...); err != nil {
135150
return errors.Wrapf(err, "fixing up %q for push", retag.cnabRef)
136151
}
137152
// push bundle manifest
@@ -181,7 +196,11 @@ type retagResult struct {
181196
invocationImageRef reference.Named
182197
}
183198

184-
func shouldRetagInvocationImage(meta metadata.AppMetadata, bndl *bundle.Bundle, tagOverride string) (retagResult, error) {
199+
func shouldRetagInvocationImage(meta metadata.AppMetadata, bndl *bundle.Bundle, tagOverride, bundleRef string) (retagResult, error) {
200+
// Use the bundle reference as a tag override
201+
if tagOverride == "" && bundleRef != "" {
202+
tagOverride = bundleRef
203+
}
185204
imgName := tagOverride
186205
var err error
187206
if imgName == "" {

internal/commands/push_test.go

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ type retagTestCase struct {
1515
metaVersion string
1616
invocationImageName string
1717
tag string
18+
bundleRef string
1819
expectedImageRef reference.Named
1920
expectedCnabRef reference.Named
2021
shouldRetag bool
@@ -40,7 +41,7 @@ func parseRefOrDie(t *testing.T, name string) reference.Named {
4041
func TestInvocationImageRetag(t *testing.T) {
4142
cases := []retagTestCase{
4243
{
43-
name: "no-tag-aligned-names",
44+
name: "no-tag-override-should-not-retag",
4445
metaName: "app",
4546
metaVersion: "0.1.0",
4647
invocationImageName: "app:0.1.0-invoc",
@@ -50,7 +51,7 @@ func TestInvocationImageRetag(t *testing.T) {
5051
shouldRetag: false,
5152
},
5253
{
53-
name: "tag-aligned-names-untagged-ref",
54+
name: "name-override-should-retag",
5455
metaName: "app",
5556
metaVersion: "0.1.0",
5657
invocationImageName: "app:0.1.0-invoc",
@@ -60,7 +61,7 @@ func TestInvocationImageRetag(t *testing.T) {
6061
shouldRetag: true,
6162
},
6263
{
63-
name: "tag-aligned-names-tagged-ref",
64+
name: "tag-override-should-retag",
6465
metaName: "app",
6566
metaVersion: "0.1.0",
6667
invocationImageName: "app:0.1.0-invoc",
@@ -69,6 +70,27 @@ func TestInvocationImageRetag(t *testing.T) {
6970
expectedCnabRef: parseRefOrDie(t, "some-app:test"),
7071
shouldRetag: true,
7172
},
73+
{
74+
name: "bundle-ref-should-retag",
75+
metaName: "app",
76+
metaVersion: "0.1.0",
77+
invocationImageName: "app:0.1.0-invoc",
78+
bundleRef: "some-app:test",
79+
expectedImageRef: parseRefOrDie(t, "some-app:test-invoc"),
80+
expectedCnabRef: parseRefOrDie(t, "some-app:test"),
81+
shouldRetag: true,
82+
},
83+
{
84+
name: "tag-overrides-bundle-ref",
85+
metaName: "app",
86+
metaVersion: "0.1.0",
87+
invocationImageName: "app:0.1.0-invoc",
88+
tag: "some-app:test",
89+
bundleRef: "other-app:other-test",
90+
expectedImageRef: parseRefOrDie(t, "some-app:test-invoc"),
91+
expectedCnabRef: parseRefOrDie(t, "some-app:test"),
92+
shouldRetag: true,
93+
},
7294
{
7395
name: "parsing-error",
7496
metaName: "app",
@@ -78,7 +100,7 @@ func TestInvocationImageRetag(t *testing.T) {
78100
errorMessage: "some-App:test: invalid reference format: repository name must be lowercase",
79101
},
80102
{
81-
name: "no-digest",
103+
name: "error-no-digest",
82104
metaName: "app",
83105
metaVersion: "0.1.0",
84106
invocationImageName: "app:0.1.0-invoc",
@@ -90,7 +112,7 @@ func TestInvocationImageRetag(t *testing.T) {
90112
for _, c := range cases {
91113
t.Run(c.name, func(t *testing.T) {
92114
p, b := c.buildPackageMetaAndBundle()
93-
retag, err := shouldRetagInvocationImage(p, b, c.tag)
115+
retag, err := shouldRetagInvocationImage(p, b, c.tag, c.bundleRef)
94116
if c.errorMessage == "" {
95117
assert.NilError(t, err)
96118
assert.Equal(t, retag.shouldRetag, c.shouldRetag)

0 commit comments

Comments
 (0)