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

Commit 172ce06

Browse files
getTargetContext now resolves the current context if the target context has not been specified.
Factorize credentialset and target-context flags. Extract all helper functions to their own go file. Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
1 parent 520a7b1 commit 172ce06

5 files changed

Lines changed: 199 additions & 216 deletions

File tree

cmd/docker-app/cnab.go

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"io/ioutil"
6+
"os"
7+
"path/filepath"
8+
"strings"
9+
10+
"github.com/deislabs/duffle/pkg/bundle"
11+
"github.com/deislabs/duffle/pkg/credentials"
12+
"github.com/deislabs/duffle/pkg/driver"
13+
"github.com/deislabs/duffle/pkg/duffle/home"
14+
"github.com/deislabs/duffle/pkg/loader"
15+
"github.com/docker/app/internal"
16+
"github.com/docker/app/internal/packager"
17+
"github.com/docker/app/types/parameters"
18+
"github.com/docker/cli/cli/command"
19+
"github.com/docker/cli/cli/context/store"
20+
cliopts "github.com/docker/cli/opts"
21+
"github.com/pkg/errors"
22+
)
23+
24+
func prepareCredentialSet(contextName string, contextStore store.Store, b *bundle.Bundle, namedCredentialsets []string) (map[string]string, error) {
25+
creds := map[string]string{}
26+
for _, file := range namedCredentialsets {
27+
if _, err := os.Stat(file); err != nil {
28+
file = filepath.Join(duffleHome().Credentials(), file+".yaml")
29+
}
30+
c, err := credentials.Load(file)
31+
if err != nil {
32+
return nil, err
33+
}
34+
values, err := c.Resolve()
35+
if err != nil {
36+
return nil, err
37+
}
38+
for k, v := range values {
39+
if _, ok := creds[k]; ok {
40+
return nil, fmt.Errorf("ambiguous credential resolution: %q is present in multiple credential sets", k)
41+
}
42+
creds[k] = v
43+
}
44+
}
45+
if contextName != "" {
46+
data, err := ioutil.ReadAll(store.Export(contextName, contextStore))
47+
if err != nil {
48+
return nil, err
49+
}
50+
creds["docker.context"] = string(data)
51+
}
52+
_, requiresDockerContext := b.Credentials["docker.context"]
53+
_, hasDockerContext := creds["docker.context"]
54+
if requiresDockerContext && !hasDockerContext {
55+
return nil, errors.New("no target context specified. Use --target-context= or DOCKER_TARGET_CONTEXT= to define it")
56+
}
57+
return creds, nil
58+
}
59+
60+
func getTargetContext(optstargetContext, currentContext string) string {
61+
var targetContext string
62+
switch {
63+
case optstargetContext != "":
64+
targetContext = optstargetContext
65+
case os.Getenv("DOCKER_TARGET_CONTEXT") != "":
66+
targetContext = os.Getenv("DOCKER_TARGET_CONTEXT")
67+
}
68+
if targetContext == "" {
69+
targetContext = currentContext
70+
}
71+
return targetContext
72+
}
73+
74+
func duffleHome() home.Home {
75+
return home.Home(home.DefaultHome())
76+
}
77+
78+
// prepareDriver prepares a driver per the user's request.
79+
func prepareDriver(dockerCli command.Cli) (driver.Driver, error) {
80+
driverImpl, err := driver.Lookup("docker")
81+
if err != nil {
82+
return driverImpl, err
83+
}
84+
if d, ok := driverImpl.(*driver.DockerDriver); ok {
85+
d.SetDockerCli(dockerCli)
86+
}
87+
88+
// Load any driver-specific config out of the environment.
89+
if configurable, ok := driverImpl.(driver.Configurable); ok {
90+
driverCfg := map[string]string{}
91+
for env := range configurable.Config() {
92+
driverCfg[env] = os.Getenv(env)
93+
}
94+
configurable.SetConfig(driverCfg)
95+
}
96+
97+
return driverImpl, err
98+
}
99+
100+
func applyParameterValues(parameterValues map[string]string, parameterDefinitions map[string]bundle.ParameterDefinition, finalValues map[string]interface{}) error {
101+
for k, v := range parameterValues {
102+
pd, ok := parameterDefinitions[k]
103+
if !ok {
104+
return fmt.Errorf("parameter %q is not defined in the bundle", k)
105+
}
106+
value, err := pd.ConvertValue(v)
107+
if err != nil {
108+
return errors.Wrapf(err, "invalid value for parameter %q", k)
109+
}
110+
if err := pd.ValidateParameterValue(value); err != nil {
111+
return errors.Wrapf(err, "invalid value for parameter %q", k)
112+
}
113+
finalValues[k] = value
114+
}
115+
return nil
116+
}
117+
118+
func prepareParameters(opts parametersOptions) (map[string]string, error) {
119+
p, err := parameters.LoadFiles(opts.parametersFiles)
120+
if err != nil {
121+
return nil, err
122+
}
123+
d := cliopts.ConvertKVStringsToMap(opts.env)
124+
overrides, err := parameters.FromFlatten(d)
125+
if err != nil {
126+
return nil, err
127+
}
128+
if p, err = parameters.Merge(p, overrides); err != nil {
129+
return nil, err
130+
}
131+
return p.Flatten(), nil
132+
}
133+
134+
func getAppNameKind(name string) (string, nameKind) {
135+
if name == "" {
136+
return name, nameKindEmpty
137+
}
138+
// name can be a bundle.json or bundle.cnab file, a single dockerapp file, or a dockerapp directory
139+
st, err := os.Stat(name)
140+
if os.IsNotExist(err) {
141+
// try with .dockerapp extension
142+
st, err = os.Stat(name + internal.AppExtension)
143+
if err == nil {
144+
name += internal.AppExtension
145+
}
146+
}
147+
if err != nil {
148+
return name, nameKindReference
149+
}
150+
if st.IsDir() {
151+
return name, nameKindDir
152+
}
153+
return name, nameKindFile
154+
}
155+
156+
func extractAndLoadAppBasedBundle(dockerCli command.Cli, namespace, name string) (*bundle.Bundle, error) {
157+
app, err := packager.Extract(name)
158+
if err != nil {
159+
return nil, err
160+
}
161+
defer app.Cleanup()
162+
return makeBundleFromApp(dockerCli, app, namespace, "")
163+
}
164+
165+
func resolveBundle(dockerCli command.Cli, namespace, name string) (*bundle.Bundle, error) {
166+
// resolution logic:
167+
// - if there is a docker-app package in working directory, or an http:// / https:// prefix, use packager.Extract result
168+
// - the name has a .json or .cnab extension and refers to an existing file or web resource: load the bundle
169+
// - name matches a bundle name:version stored in duffle bundle store: use it
170+
// - pull the bundle from the registry and add it to the bundle store
171+
name, kind := getAppNameKind(name)
172+
switch kind {
173+
case nameKindFile:
174+
if strings.HasSuffix(name, internal.AppExtension) {
175+
return extractAndLoadAppBasedBundle(dockerCli, namespace, name)
176+
}
177+
return loader.NewDetectingLoader().Load(name)
178+
case nameKindDir, nameKindEmpty:
179+
return extractAndLoadAppBasedBundle(dockerCli, namespace, name)
180+
case nameKindReference:
181+
// TODO: pull the bundle
182+
fmt.Fprintln(dockerCli.Err(), "WARNING: pulling a CNAB is not yet supported")
183+
}
184+
return nil, fmt.Errorf("could not resolve bundle %q", name)
185+
}

0 commit comments

Comments
 (0)