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

Commit b953958

Browse files
Merge pull request #529 from ijc/push-from-bundle
Push directly from bundle
2 parents 368989a + ced138b commit b953958

File tree

5 files changed

+100
-17
lines changed

5 files changed

+100
-17
lines changed

e2e/commands_test.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,15 @@ func testRenderApp(appPath string, env ...string) func(*testing.T) {
6666
}
6767
cmd.Command = args
6868
cmd.Env = append(cmd.Env, env...)
69-
// Check rendering to stdout
70-
result := icmd.RunCmd(cmd).Assert(t, icmd.Success)
71-
assert.Assert(t, is.Equal(readFile(t, filepath.Join(appPath, "expected.txt")), result.Stdout()), "rendering mismatch")
72-
// Checks rendering to a file
73-
cmd.Command = append(cmd.Command, "--output="+dir.Join("actual.yaml"))
74-
icmd.RunCmd(cmd).Assert(t, icmd.Success)
75-
76-
assert.Assert(t, is.Equal(readFile(t, filepath.Join(appPath, "expected.txt")), readFile(t, dir.Join("actual.yaml"))), "rendering mismatch")
69+
t.Run("stdout", func(t *testing.T) {
70+
result := icmd.RunCmd(cmd).Assert(t, icmd.Success)
71+
assert.Assert(t, is.Equal(readFile(t, filepath.Join(appPath, "expected.txt")), result.Stdout()), "rendering mismatch")
72+
})
73+
t.Run("file", func(t *testing.T) {
74+
cmd.Command = append(cmd.Command, "--output="+dir.Join("actual.yaml"))
75+
icmd.RunCmd(cmd).Assert(t, icmd.Success)
76+
assert.Assert(t, is.Equal(readFile(t, filepath.Join(appPath, "expected.txt")), readFile(t, dir.Join("actual.yaml"))), "rendering mismatch")
77+
})
7778
}
7879
}
7980

e2e/pushpull_test.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"net"
77
"path/filepath"
88
"strconv"
9+
"strings"
910
"testing"
1011
"time"
1112

@@ -132,6 +133,53 @@ func TestPushPullInstall(t *testing.T) {
132133
})
133134
}
134135

136+
func TestPushInstallBundle(t *testing.T) {
137+
runWithDindSwarmAndRegistry(t, func(info dindSwarmAndRegistryInfo) {
138+
cmd := info.configuredCmd
139+
ref := info.registryAddress + "/test/push-bundle"
140+
141+
tmpDir := fs.NewDir(t, t.Name())
142+
defer tmpDir.Remove()
143+
bundleFile := tmpDir.Join("bundle.json")
144+
145+
// render the app to a bundle, we use the app from the push pull test above.
146+
cmd.Command = dockerCli.Command("app", "bundle", "-o", bundleFile, filepath.Join("testdata", "push-pull", "push-pull.dockerapp"))
147+
icmd.RunCmd(cmd).Assert(t, icmd.Success)
148+
149+
// push it and install to check it is available
150+
t.Run("push-bundle", func(t *testing.T) {
151+
name := strings.Replace(t.Name(), "/", "_", 1)
152+
cmd.Command = dockerCli.Command("app", "push", "--insecure-registries="+info.registryAddress, "--tag", ref, bundleFile)
153+
icmd.RunCmd(cmd).Assert(t, icmd.Success)
154+
155+
cmd.Command = dockerCli.Command("app", "install", "--insecure-registries="+info.registryAddress, ref, "--name", name)
156+
icmd.RunCmd(cmd).Assert(t, icmd.Success)
157+
cmd.Command = dockerCli.Command("service", "ls")
158+
assert.Check(t, cmp.Contains(icmd.RunCmd(cmd).Assert(t, icmd.Success).Combined(), ref))
159+
160+
// ensure it doesn't confuse the next test
161+
cmd.Command = dockerCli.Command("app", "uninstall", name)
162+
icmd.RunCmd(cmd).Assert(t, icmd.Success)
163+
164+
cmd.Command = dockerCli.Command("service", "ls")
165+
assert.Check(t, !strings.Contains(icmd.RunCmd(cmd).Assert(t, icmd.Success).Combined(), ref))
166+
})
167+
168+
// push it again using the first ref and install from the new ref to check it is also available
169+
t.Run("push-ref", func(t *testing.T) {
170+
name := strings.Replace(t.Name(), "/", "_", 1)
171+
ref2 := info.registryAddress + "/test/push-ref"
172+
cmd.Command = dockerCli.Command("app", "push", "--insecure-registries="+info.registryAddress, "--tag", ref2, ref+":latest")
173+
icmd.RunCmd(cmd).Assert(t, icmd.Success)
174+
175+
cmd.Command = dockerCli.Command("app", "install", "--insecure-registries="+info.registryAddress, ref2, "--name", name)
176+
icmd.RunCmd(cmd).Assert(t, icmd.Success)
177+
cmd.Command = dockerCli.Command("service", "ls")
178+
assert.Check(t, cmp.Contains(icmd.RunCmd(cmd).Assert(t, icmd.Success).Combined(), ref2))
179+
})
180+
})
181+
}
182+
135183
func findAvailablePort() int {
136184
rand.Seed(time.Now().UnixNano())
137185
for {

internal/commands/push.go

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111

1212
"github.com/containerd/containerd/platforms"
1313
"github.com/deislabs/cnab-go/bundle"
14-
"github.com/docker/app/internal/packager"
1514
"github.com/docker/app/types/metadata"
1615
"github.com/docker/cli/cli"
1716
"github.com/docker/cli/cli/command"
@@ -52,16 +51,21 @@ func pushCmd(dockerCli command.Cli) *cobra.Command {
5251

5352
func runPush(dockerCli command.Cli, name string, opts pushOptions) error {
5453
defer muteDockerCli(dockerCli)()
55-
app, err := packager.Extract(name)
54+
55+
bundleStore, err := prepareBundleStore()
5656
if err != nil {
5757
return err
5858
}
59-
defer app.Cleanup()
60-
bndl, err := makeBundleFromApp(dockerCli, app, nil)
59+
60+
bndl, _, err := resolveBundle(dockerCli, bundleStore, name, false, nil)
6161
if err != nil {
6262
return err
6363
}
64-
retag, err := shouldRetagInvocationImage(app.Metadata(), bndl, opts.tag)
64+
if err := bndl.Validate(); err != nil {
65+
return err
66+
}
67+
68+
retag, err := shouldRetagInvocationImage(metadata.FromBundle(bndl), bndl, opts.tag)
6569
if err != nil {
6670
return err
6771
}
@@ -85,11 +89,11 @@ func runPush(dockerCli command.Cli, name string, opts pushOptions) error {
8589
RegistryAuth: encodedAuth,
8690
})
8791
if err != nil {
88-
return err
92+
return errors.Wrapf(err, "starting push of %q", retag.invocationImageRef.String())
8993
}
9094
defer reader.Close()
9195
if err = jsonmessage.DisplayJSONMessagesStream(reader, ioutil.Discard, 0, false, nil); err != nil {
92-
return err
96+
return errors.Wrapf(err, "pushing to %q", retag.invocationImageRef.String())
9397
}
9498

9599
resolverConfig := remotes.NewResolverConfigFromDockerConfigFile(dockerCli.ConfigFile(), opts.registry.insecureRegistries...)
@@ -107,12 +111,12 @@ func runPush(dockerCli command.Cli, name string, opts pushOptions) error {
107111
err = remotes.FixupBundle(context.Background(), bndl, retag.cnabRef, resolverConfig, fixupOptions...)
108112

109113
if err != nil {
110-
return err
114+
return errors.Wrapf(err, "fixing up %q for push", retag.cnabRef)
111115
}
112116
// push bundle manifest
113117
descriptor, err := remotes.Push(context.Background(), bndl, retag.cnabRef, resolverConfig.Resolver, true)
114118
if err != nil {
115-
return err
119+
return errors.Wrapf(err, "pushing to %q", retag.cnabRef)
116120
}
117121
fmt.Printf("Successfully pushed bundle to %s. Digest is %s.\n", retag.cnabRef.String(), descriptor.Digest)
118122
return nil

internal/commands/root.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,18 @@ func prepareStores(targetContext string) (store.BundleStore, store.InstallationS
7878
return bundleStore, installationStore, credentialStore, nil
7979
}
8080

81+
func prepareBundleStore() (store.BundleStore, error) {
82+
appstore, err := store.NewApplicationStore(config.Dir())
83+
if err != nil {
84+
return nil, err
85+
}
86+
bundleStore, err := appstore.BundleStore()
87+
if err != nil {
88+
return nil, err
89+
}
90+
return bundleStore, nil
91+
}
92+
8193
type parametersOptions struct {
8294
parametersFiles []string
8395
overrides []string

types/metadata/metadata.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package metadata
22

33
import (
44
"strings"
5+
6+
"github.com/deislabs/cnab-go/bundle"
57
)
68

79
// Maintainer represents one of the apps's maintainers
@@ -38,3 +40,19 @@ type AppMetadata struct {
3840
Description string `json:"description,omitempty"`
3941
Maintainers Maintainers `json:"maintainers,omitempty"`
4042
}
43+
44+
// Metadata extracts the docker-app metadata from the bundle
45+
func FromBundle(bndl *bundle.Bundle) AppMetadata {
46+
meta := AppMetadata{
47+
Name: bndl.Name,
48+
Version: bndl.Version,
49+
Description: bndl.Description,
50+
}
51+
for _, m := range bndl.Maintainers {
52+
meta.Maintainers = append(meta.Maintainers, Maintainer{
53+
Name: m.Name,
54+
Email: m.Email,
55+
})
56+
}
57+
return meta
58+
}

0 commit comments

Comments
 (0)