mirror of https://github.com/docker/cli.git
Merge pull request #1840 from tiborvass/cli-plugin-aliases
cli-plugins: alias an existing allowed command (only builder for now)
This commit is contained in:
commit
70f48f2231
|
@ -164,6 +164,7 @@ func PluginRunCommand(dockerCli command.Cli, name string, rootcmd *cobra.Command
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if plugin.Err != nil {
|
if plugin.Err != nil {
|
||||||
|
// TODO: why are we not returning plugin.Err?
|
||||||
return nil, errPluginNotFound(name)
|
return nil, errPluginNotFound(name)
|
||||||
}
|
}
|
||||||
cmd := exec.Command(plugin.Path, args...)
|
cmd := exec.Command(plugin.Path, args...)
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
|
|
||||||
"github.com/docker/cli/cli"
|
"github.com/docker/cli/cli"
|
||||||
"github.com/docker/cli/cli/command"
|
"github.com/docker/cli/cli/command"
|
||||||
|
"github.com/docker/cli/cli/command/image"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewBuilderCommand returns a cobra command for `builder` subcommands
|
// NewBuilderCommand returns a cobra command for `builder` subcommands
|
||||||
|
@ -18,6 +19,7 @@ func NewBuilderCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
}
|
}
|
||||||
cmd.AddCommand(
|
cmd.AddCommand(
|
||||||
NewPruneCommand(dockerCli),
|
NewPruneCommand(dockerCli),
|
||||||
|
image.NewBuildCommand(dockerCli),
|
||||||
)
|
)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
|
@ -161,3 +161,34 @@ func ValidateOutputPathFileMode(fileMode os.FileMode) error {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func stringSliceIndex(s, subs []string) int {
|
||||||
|
j := 0
|
||||||
|
if len(subs) > 0 {
|
||||||
|
for i, x := range s {
|
||||||
|
if j < len(subs) && subs[j] == x {
|
||||||
|
j++
|
||||||
|
} else {
|
||||||
|
j = 0
|
||||||
|
}
|
||||||
|
if len(subs) == j {
|
||||||
|
return i + 1 - j
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringSliceReplaceAt replaces the sub-slice old, with the sub-slice new, in the string
|
||||||
|
// slice s, returning a new slice and a boolean indicating if the replacement happened.
|
||||||
|
// requireIdx is the index at which old needs to be found at (or -1 to disregard that).
|
||||||
|
func StringSliceReplaceAt(s, old, new []string, requireIndex int) ([]string, bool) {
|
||||||
|
idx := stringSliceIndex(s, old)
|
||||||
|
if (requireIndex != -1 && requireIndex != idx) || idx == -1 {
|
||||||
|
return s, false
|
||||||
|
}
|
||||||
|
out := append([]string{}, s[:idx]...)
|
||||||
|
out = append(out, new...)
|
||||||
|
out = append(out, s[idx+len(old):]...)
|
||||||
|
return out, true
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"gotest.tools/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestStringSliceReplaceAt(t *testing.T) {
|
||||||
|
out, ok := StringSliceReplaceAt([]string{"abc", "foo", "bar", "bax"}, []string{"foo", "bar"}, []string{"baz"}, -1)
|
||||||
|
assert.Assert(t, ok)
|
||||||
|
assert.DeepEqual(t, []string{"abc", "baz", "bax"}, out)
|
||||||
|
|
||||||
|
out, ok = StringSliceReplaceAt([]string{"foo"}, []string{"foo", "bar"}, []string{"baz"}, -1)
|
||||||
|
assert.Assert(t, !ok)
|
||||||
|
assert.DeepEqual(t, []string{"foo"}, out)
|
||||||
|
|
||||||
|
out, ok = StringSliceReplaceAt([]string{"abc", "foo", "bar", "bax"}, []string{"foo", "bar"}, []string{"baz"}, 0)
|
||||||
|
assert.Assert(t, !ok)
|
||||||
|
assert.DeepEqual(t, []string{"abc", "foo", "bar", "bax"}, out)
|
||||||
|
|
||||||
|
out, ok = StringSliceReplaceAt([]string{"foo", "bar", "bax"}, []string{"foo", "bar"}, []string{"baz"}, 0)
|
||||||
|
assert.Assert(t, ok)
|
||||||
|
assert.DeepEqual(t, []string{"baz", "bax"}, out)
|
||||||
|
|
||||||
|
out, ok = StringSliceReplaceAt([]string{"abc", "foo", "bar", "baz"}, []string{"foo", "bar"}, nil, -1)
|
||||||
|
assert.Assert(t, ok)
|
||||||
|
assert.DeepEqual(t, []string{"abc", "baz"}, out)
|
||||||
|
|
||||||
|
out, ok = StringSliceReplaceAt([]string{"foo"}, nil, []string{"baz"}, -1)
|
||||||
|
assert.Assert(t, !ok)
|
||||||
|
assert.DeepEqual(t, []string{"foo"}, out)
|
||||||
|
}
|
|
@ -50,6 +50,7 @@ type ConfigFile struct {
|
||||||
CurrentContext string `json:"currentContext,omitempty"`
|
CurrentContext string `json:"currentContext,omitempty"`
|
||||||
CLIPluginsExtraDirs []string `json:"cliPluginsExtraDirs,omitempty"`
|
CLIPluginsExtraDirs []string `json:"cliPluginsExtraDirs,omitempty"`
|
||||||
Plugins map[string]map[string]string `json:"plugins,omitempty"`
|
Plugins map[string]map[string]string `json:"plugins,omitempty"`
|
||||||
|
Aliases map[string]string `json:"aliases,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProxyConfig contains proxy configuration settings
|
// ProxyConfig contains proxy configuration settings
|
||||||
|
@ -72,6 +73,7 @@ func New(fn string) *ConfigFile {
|
||||||
HTTPHeaders: make(map[string]string),
|
HTTPHeaders: make(map[string]string),
|
||||||
Filename: fn,
|
Filename: fn,
|
||||||
Plugins: make(map[string]map[string]string),
|
Plugins: make(map[string]map[string]string),
|
||||||
|
Aliases: make(map[string]string),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
@ -16,11 +15,16 @@ import (
|
||||||
"github.com/docker/cli/cli/version"
|
"github.com/docker/cli/cli/version"
|
||||||
"github.com/docker/docker/api/types/versions"
|
"github.com/docker/docker/api/types/versions"
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var allowedAliases = map[string]struct{}{
|
||||||
|
"builder": {},
|
||||||
|
}
|
||||||
|
|
||||||
func newDockerCommand(dockerCli *command.DockerCli) *cli.TopLevelCommand {
|
func newDockerCommand(dockerCli *command.DockerCli) *cli.TopLevelCommand {
|
||||||
var (
|
var (
|
||||||
opts *cliflags.ClientOptions
|
opts *cliflags.ClientOptions
|
||||||
|
@ -204,6 +208,38 @@ func tryPluginRun(dockerCli command.Cli, cmd *cobra.Command, subcommand string)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func processAliases(dockerCli command.Cli, cmd *cobra.Command, args, osArgs []string) ([]string, []string, error) {
|
||||||
|
aliasMap := dockerCli.ConfigFile().Aliases
|
||||||
|
aliases := make([][2][]string, 0, len(aliasMap))
|
||||||
|
|
||||||
|
for k, v := range aliasMap {
|
||||||
|
if _, ok := allowedAliases[k]; !ok {
|
||||||
|
return args, osArgs, errors.Errorf("Not allowed to alias %q. Allowed aliases: %#v", k, allowedAliases)
|
||||||
|
}
|
||||||
|
if _, _, err := cmd.Find(strings.Split(v, " ")); err == nil {
|
||||||
|
return args, osArgs, errors.Errorf("Not allowed to alias with builtin %q as target", v)
|
||||||
|
}
|
||||||
|
aliases = append(aliases, [2][]string{{k}, {v}})
|
||||||
|
}
|
||||||
|
|
||||||
|
if v, ok := aliasMap["builder"]; ok {
|
||||||
|
aliases = append(aliases,
|
||||||
|
[2][]string{{"build"}, {v, "build"}},
|
||||||
|
[2][]string{{"image", "build"}, {v, "build"}},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
for _, al := range aliases {
|
||||||
|
var didChange bool
|
||||||
|
args, didChange = command.StringSliceReplaceAt(args, al[0], al[1], 0)
|
||||||
|
if didChange {
|
||||||
|
osArgs, _ = command.StringSliceReplaceAt(osArgs, al[0], al[1], -1)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return args, osArgs, nil
|
||||||
|
}
|
||||||
|
|
||||||
func runDocker(dockerCli *command.DockerCli) error {
|
func runDocker(dockerCli *command.DockerCli) error {
|
||||||
tcmd := newDockerCommand(dockerCli)
|
tcmd := newDockerCommand(dockerCli)
|
||||||
|
|
||||||
|
@ -216,6 +252,11 @@ func runDocker(dockerCli *command.DockerCli) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
args, os.Args, err = processAliases(dockerCli, cmd, args, os.Args)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
if _, _, err := cmd.Find(args); err != nil {
|
if _, _, err := cmd.Find(args); err != nil {
|
||||||
err := tryPluginRun(dockerCli, cmd, args[0])
|
err := tryPluginRun(dockerCli, cmd, args[0])
|
||||||
|
|
Loading…
Reference in New Issue