This repository has been archived by the owner on Jun 13, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 174
/
install.go
147 lines (130 loc) · 4.54 KB
/
install.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
package commands
import (
"fmt"
"os"
"github.com/deislabs/duffle/pkg/action"
"github.com/deislabs/duffle/pkg/credentials"
"github.com/docker/app/internal/store"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/spf13/cobra"
)
type installOptions struct {
parametersOptions
credentialOptions
registryOptions
pullOptions
orchestrator string
kubeNamespace string
stackName string
}
type nameKind uint
const (
_ nameKind = iota
nameKindEmpty
nameKindFile
nameKindDir
nameKindReference
)
const longDescription = `Install an application.
By default, the application definition in the current directory will be
installed. The APP_NAME can also be:
- a path to a Docker Application definition (.dockerapp) or a CNAB bundle.json
- a registry Application Package reference`
const example = `$ docker app install myapp.dockerapp --name myinstallation --target-context=mycontext
$ docker app install myrepo/myapp:mytag --name myinstallation --target-context=mycontext
$ docker app install bundle.json --name myinstallation --credential-set=mycredentials.yml`
func installCmd(dockerCli command.Cli) *cobra.Command {
var opts installOptions
cmd := &cobra.Command{
Use: "install [APP_NAME] [--name INSTALLATION_NAME] [--target-context TARGET_CONTEXT] [OPTIONS]",
Aliases: []string{"deploy"},
Short: "Install an application",
Long: longDescription,
Example: example,
Args: cli.RequiresMaxArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
return runInstall(dockerCli, firstOrEmpty(args), opts)
},
}
opts.parametersOptions.addFlags(cmd.Flags())
opts.credentialOptions.addFlags(cmd.Flags())
opts.registryOptions.addFlags(cmd.Flags())
opts.pullOptions.addFlags(cmd.Flags())
cmd.Flags().StringVar(&opts.orchestrator, "orchestrator", "", "Orchestrator to install on (swarm, kubernetes)")
cmd.Flags().StringVar(&opts.kubeNamespace, "kubernetes-namespace", "default", "Kubernetes namespace to install into")
cmd.Flags().StringVar(&opts.stackName, "name", "", "Installation name (defaults to application name)")
return cmd
}
func runInstall(dockerCli command.Cli, appname string, opts installOptions) error {
defer muteDockerCli(dockerCli)()
opts.SetDefaultTargetContext(dockerCli)
bind, err := requiredBindMount(opts.targetContext, opts.orchestrator, dockerCli.ContextStore())
if err != nil {
return err
}
bundleStore, installationStore, credentialStore, err := prepareStores(opts.targetContext)
if err != nil {
return err
}
bndl, ref, err := resolveBundle(dockerCli, bundleStore, appname, opts.pull, opts.insecureRegistries)
if err != nil {
return err
}
if err := bndl.Validate(); err != nil {
return err
}
installationName := opts.stackName
if installationName == "" {
installationName = bndl.Name
}
if installation, err := installationStore.Read(installationName); err == nil {
// A failed installation can be overridden, but with a warning
if isInstallationFailed(installation) {
fmt.Fprintf(os.Stderr, "WARNING: installing over previously failed installation %q\n", installationName)
} else {
// Return an error in case of successful installation, or even failed upgrade, which means
// their was already a successful installation.
return fmt.Errorf("Installation %q already exists, use 'docker app upgrade' instead", installationName)
}
}
installation, err := store.NewInstallation(installationName, ref)
if err != nil {
return err
}
driverImpl, errBuf, err := prepareDriver(dockerCli, bind, nil)
if err != nil {
return err
}
installation.Bundle = bndl
if err := mergeBundleParameters(installation,
withFileParameters(opts.parametersFiles),
withCommandLineParameters(opts.overrides),
withOrchestratorParameters(opts.orchestrator, opts.kubeNamespace),
withSendRegistryAuth(opts.sendRegistryAuth),
); err != nil {
return err
}
creds, err := prepareCredentialSet(bndl, opts.CredentialSetOpts(dockerCli, credentialStore)...)
if err != nil {
return err
}
if err := credentials.Validate(creds, bndl.Credentials); err != nil {
return err
}
inst := &action.Install{
Driver: driverImpl,
}
err = inst.Run(&installation.Claim, creds, os.Stdout)
// Even if the installation failed, the installation is persisted with its failure status,
// so any installation needs a clean uninstallation.
err2 := installationStore.Store(installation)
if err != nil {
return fmt.Errorf("Installation failed: %s\n%s", errBuf, err)
}
if err2 != nil {
return err2
}
fmt.Printf("Application %q installed on context %q\n", installationName, opts.targetContext)
return nil
}