|
@@ -15,15 +15,22 @@ import (
|
|
"github.com/docker/docker/pkg/jsonmessage"
|
|
"github.com/docker/docker/pkg/jsonmessage"
|
|
"github.com/docker/docker/registry"
|
|
"github.com/docker/docker/registry"
|
|
"github.com/spf13/cobra"
|
|
"github.com/spf13/cobra"
|
|
|
|
+ "github.com/spf13/pflag"
|
|
"golang.org/x/net/context"
|
|
"golang.org/x/net/context"
|
|
)
|
|
)
|
|
|
|
|
|
type pluginOptions struct {
|
|
type pluginOptions struct {
|
|
- name string
|
|
|
|
- alias string
|
|
|
|
- grantPerms bool
|
|
|
|
- disable bool
|
|
|
|
- args []string
|
|
|
|
|
|
+ remote string
|
|
|
|
+ localName string
|
|
|
|
+ grantPerms bool
|
|
|
|
+ disable bool
|
|
|
|
+ args []string
|
|
|
|
+ skipRemoteCheck bool
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func loadPullFlags(opts *pluginOptions, flags *pflag.FlagSet) {
|
|
|
|
+ flags.BoolVar(&opts.grantPerms, "grant-all-permissions", false, "Grant all permissions necessary to run the plugin")
|
|
|
|
+ command.AddTrustVerificationFlags(flags)
|
|
}
|
|
}
|
|
|
|
|
|
func newInstallCommand(dockerCli *command.DockerCli) *cobra.Command {
|
|
func newInstallCommand(dockerCli *command.DockerCli) *cobra.Command {
|
|
@@ -33,7 +40,7 @@ func newInstallCommand(dockerCli *command.DockerCli) *cobra.Command {
|
|
Short: "Install a plugin",
|
|
Short: "Install a plugin",
|
|
Args: cli.RequiresMinArgs(1),
|
|
Args: cli.RequiresMinArgs(1),
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
- options.name = args[0]
|
|
|
|
|
|
+ options.remote = args[0]
|
|
if len(args) > 1 {
|
|
if len(args) > 1 {
|
|
options.args = args[1:]
|
|
options.args = args[1:]
|
|
}
|
|
}
|
|
@@ -42,12 +49,9 @@ func newInstallCommand(dockerCli *command.DockerCli) *cobra.Command {
|
|
}
|
|
}
|
|
|
|
|
|
flags := cmd.Flags()
|
|
flags := cmd.Flags()
|
|
- flags.BoolVar(&options.grantPerms, "grant-all-permissions", false, "Grant all permissions necessary to run the plugin")
|
|
|
|
|
|
+ loadPullFlags(&options, flags)
|
|
flags.BoolVar(&options.disable, "disable", false, "Do not enable the plugin on install")
|
|
flags.BoolVar(&options.disable, "disable", false, "Do not enable the plugin on install")
|
|
- flags.StringVar(&options.alias, "alias", "", "Local name for plugin")
|
|
|
|
-
|
|
|
|
- command.AddTrustVerificationFlags(flags)
|
|
|
|
-
|
|
|
|
|
|
+ flags.StringVar(&options.localName, "alias", "", "Local name for plugin")
|
|
return cmd
|
|
return cmd
|
|
}
|
|
}
|
|
|
|
|
|
@@ -83,49 +87,33 @@ func newRegistryService() registry.Service {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-func runInstall(dockerCli *command.DockerCli, opts pluginOptions) error {
|
|
|
|
|
|
+func buildPullConfig(ctx context.Context, dockerCli *command.DockerCli, opts pluginOptions, cmdName string) (types.PluginInstallOptions, error) {
|
|
// Names with both tag and digest will be treated by the daemon
|
|
// Names with both tag and digest will be treated by the daemon
|
|
- // as a pull by digest with an alias for the tag
|
|
|
|
- // (if no alias is provided).
|
|
|
|
- ref, err := reference.ParseNormalizedNamed(opts.name)
|
|
|
|
|
|
+ // as a pull by digest with a local name for the tag
|
|
|
|
+ // (if no local name is provided).
|
|
|
|
+ ref, err := reference.ParseNormalizedNamed(opts.remote)
|
|
if err != nil {
|
|
if err != nil {
|
|
- return err
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- alias := ""
|
|
|
|
- if opts.alias != "" {
|
|
|
|
- aref, err := reference.ParseNormalizedNamed(opts.alias)
|
|
|
|
- if err != nil {
|
|
|
|
- return err
|
|
|
|
- }
|
|
|
|
- if _, ok := aref.(reference.Canonical); ok {
|
|
|
|
- return fmt.Errorf("invalid name: %s", opts.alias)
|
|
|
|
- }
|
|
|
|
- alias = reference.FamiliarString(reference.EnsureTagged(aref))
|
|
|
|
|
|
+ return types.PluginInstallOptions{}, err
|
|
}
|
|
}
|
|
- ctx := context.Background()
|
|
|
|
|
|
|
|
repoInfo, err := registry.ParseRepositoryInfo(ref)
|
|
repoInfo, err := registry.ParseRepositoryInfo(ref)
|
|
if err != nil {
|
|
if err != nil {
|
|
- return err
|
|
|
|
|
|
+ return types.PluginInstallOptions{}, err
|
|
}
|
|
}
|
|
|
|
|
|
remote := ref.String()
|
|
remote := ref.String()
|
|
|
|
|
|
_, isCanonical := ref.(reference.Canonical)
|
|
_, isCanonical := ref.(reference.Canonical)
|
|
if command.IsTrusted() && !isCanonical {
|
|
if command.IsTrusted() && !isCanonical {
|
|
- if alias == "" {
|
|
|
|
- alias = reference.FamiliarString(ref)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
nt, ok := ref.(reference.NamedTagged)
|
|
nt, ok := ref.(reference.NamedTagged)
|
|
if !ok {
|
|
if !ok {
|
|
nt = reference.EnsureTagged(ref)
|
|
nt = reference.EnsureTagged(ref)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ ctx := context.Background()
|
|
trusted, err := image.TrustedReference(ctx, dockerCli, nt, newRegistryService())
|
|
trusted, err := image.TrustedReference(ctx, dockerCli, nt, newRegistryService())
|
|
if err != nil {
|
|
if err != nil {
|
|
- return err
|
|
|
|
|
|
+ return types.PluginInstallOptions{}, err
|
|
}
|
|
}
|
|
remote = reference.FamiliarString(trusted)
|
|
remote = reference.FamiliarString(trusted)
|
|
}
|
|
}
|
|
@@ -134,23 +122,42 @@ func runInstall(dockerCli *command.DockerCli, opts pluginOptions) error {
|
|
|
|
|
|
encodedAuth, err := command.EncodeAuthToBase64(authConfig)
|
|
encodedAuth, err := command.EncodeAuthToBase64(authConfig)
|
|
if err != nil {
|
|
if err != nil {
|
|
- return err
|
|
|
|
|
|
+ return types.PluginInstallOptions{}, err
|
|
}
|
|
}
|
|
-
|
|
|
|
- registryAuthFunc := command.RegistryAuthenticationPrivilegedFunc(dockerCli, repoInfo.Index, "plugin install")
|
|
|
|
|
|
+ registryAuthFunc := command.RegistryAuthenticationPrivilegedFunc(dockerCli, repoInfo.Index, cmdName)
|
|
|
|
|
|
options := types.PluginInstallOptions{
|
|
options := types.PluginInstallOptions{
|
|
RegistryAuth: encodedAuth,
|
|
RegistryAuth: encodedAuth,
|
|
RemoteRef: remote,
|
|
RemoteRef: remote,
|
|
Disabled: opts.disable,
|
|
Disabled: opts.disable,
|
|
AcceptAllPermissions: opts.grantPerms,
|
|
AcceptAllPermissions: opts.grantPerms,
|
|
- AcceptPermissionsFunc: acceptPrivileges(dockerCli, opts.name),
|
|
|
|
|
|
+ AcceptPermissionsFunc: acceptPrivileges(dockerCli, opts.remote),
|
|
// TODO: Rename PrivilegeFunc, it has nothing to do with privileges
|
|
// TODO: Rename PrivilegeFunc, it has nothing to do with privileges
|
|
PrivilegeFunc: registryAuthFunc,
|
|
PrivilegeFunc: registryAuthFunc,
|
|
Args: opts.args,
|
|
Args: opts.args,
|
|
}
|
|
}
|
|
|
|
+ return options, nil
|
|
|
|
+}
|
|
|
|
|
|
- responseBody, err := dockerCli.Client().PluginInstall(ctx, alias, options)
|
|
|
|
|
|
+func runInstall(dockerCli *command.DockerCli, opts pluginOptions) error {
|
|
|
|
+ var localName string
|
|
|
|
+ if opts.localName != "" {
|
|
|
|
+ aref, err := reference.ParseNormalizedNamed(opts.localName)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+ if _, ok := aref.(reference.Canonical); ok {
|
|
|
|
+ return fmt.Errorf("invalid name: %s", opts.localName)
|
|
|
|
+ }
|
|
|
|
+ localName = reference.FamiliarString(reference.EnsureTagged(aref))
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ctx := context.Background()
|
|
|
|
+ options, err := buildPullConfig(ctx, dockerCli, opts, "plugin install")
|
|
|
|
+ if err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+ responseBody, err := dockerCli.Client().PluginInstall(ctx, localName, options)
|
|
if err != nil {
|
|
if err != nil {
|
|
if strings.Contains(err.Error(), "target is image") {
|
|
if strings.Contains(err.Error(), "target is image") {
|
|
return errors.New(err.Error() + " - Use `docker image pull`")
|
|
return errors.New(err.Error() + " - Use `docker image pull`")
|
|
@@ -161,7 +168,7 @@ func runInstall(dockerCli *command.DockerCli, opts pluginOptions) error {
|
|
if err := jsonmessage.DisplayJSONMessagesToStream(responseBody, dockerCli.Out(), nil); err != nil {
|
|
if err := jsonmessage.DisplayJSONMessagesToStream(responseBody, dockerCli.Out(), nil); err != nil {
|
|
return err
|
|
return err
|
|
}
|
|
}
|
|
- fmt.Fprintf(dockerCli.Out(), "Installed plugin %s\n", opts.name) // todo: return proper values from the API for this result
|
|
|
|
|
|
+ fmt.Fprintf(dockerCli.Out(), "Installed plugin %s\n", opts.remote) // todo: return proper values from the API for this result
|
|
return nil
|
|
return nil
|
|
}
|
|
}
|
|
|
|
|