Activate kubernetes only when experimental cli is enabled

* Refactor tests on version and kubernetes switch
* Fix rebase errors
* Refactor for gocyclo linter

Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
This commit is contained in:
Silvin Lubecki 2017-12-26 15:40:17 +01:00
parent 5d375b348a
commit ad409767bf
11 changed files with 163 additions and 65 deletions

View File

@ -136,11 +136,11 @@ func (cli *DockerCli) Initialize(opts *cliflags.ClientOptions) error {
if err != nil { if err != nil {
return errors.Wrap(err, "Experimental field") return errors.Wrap(err, "Experimental field")
} }
orchestrator := GetOrchestrator(opts.Common.Orchestrator, cli.configFile.Orchestrator) orchestrator := GetOrchestrator(hasExperimental, opts.Common.Orchestrator, cli.configFile.Orchestrator)
cli.clientInfo = ClientInfo{ cli.clientInfo = ClientInfo{
DefaultVersion: cli.client.ClientVersion(), DefaultVersion: cli.client.ClientVersion(),
HasExperimental: hasExperimental, HasExperimental: hasExperimental,
HasKubernetes: orchestrator == OrchestratorKubernetes, HasKubernetes: hasExperimental && orchestrator == OrchestratorKubernetes,
Orchestrator: orchestrator, Orchestrator: orchestrator,
} }
cli.initializeFromClient() cli.initializeFromClient()

View File

@ -170,6 +170,110 @@ func TestExperimentalCLI(t *testing.T) {
} }
} }
func TestOrchestratorSwitch(t *testing.T) {
defaultVersion := "v1.55"
var testcases = []struct {
doc string
configfile string
envOrchestrator string
flagOrchestrator string
expectedOrchestrator string
expectedKubernetes bool
}{
{
doc: "default",
configfile: `{
"experimental": "enabled"
}`,
expectedOrchestrator: "swarm",
expectedKubernetes: false,
},
{
doc: "kubernetesIsExperimental",
configfile: `{
"experimental": "disabled",
"orchestrator": "kubernetes"
}`,
envOrchestrator: "kubernetes",
flagOrchestrator: "kubernetes",
expectedOrchestrator: "swarm",
expectedKubernetes: false,
},
{
doc: "kubernetesConfigFile",
configfile: `{
"experimental": "enabled",
"orchestrator": "kubernetes"
}`,
expectedOrchestrator: "kubernetes",
expectedKubernetes: true,
},
{
doc: "kubernetesEnv",
configfile: `{
"experimental": "enabled"
}`,
envOrchestrator: "kubernetes",
expectedOrchestrator: "kubernetes",
expectedKubernetes: true,
},
{
doc: "kubernetesFlag",
configfile: `{
"experimental": "enabled"
}`,
flagOrchestrator: "kubernetes",
expectedOrchestrator: "kubernetes",
expectedKubernetes: true,
},
{
doc: "envOverridesConfigFile",
configfile: `{
"experimental": "enabled",
"orchestrator": "kubernetes"
}`,
envOrchestrator: "swarm",
expectedOrchestrator: "swarm",
expectedKubernetes: false,
},
{
doc: "flagOverridesEnv",
configfile: `{
"experimental": "enabled"
}`,
envOrchestrator: "kubernetes",
flagOrchestrator: "swarm",
expectedOrchestrator: "swarm",
expectedKubernetes: false,
},
}
for _, testcase := range testcases {
t.Run(testcase.doc, func(t *testing.T) {
dir := fs.NewDir(t, testcase.doc, fs.WithFile("config.json", testcase.configfile))
defer dir.Remove()
apiclient := &fakeClient{
version: defaultVersion,
}
if testcase.envOrchestrator != "" {
defer patchEnvVariable(t, "DOCKER_ORCHESTRATOR", testcase.envOrchestrator)()
}
cli := &DockerCli{client: apiclient, err: os.Stderr}
cliconfig.SetDir(dir.Path())
options := flags.NewClientOptions()
if testcase.flagOrchestrator != "" {
options.Common.Orchestrator = testcase.flagOrchestrator
}
err := cli.Initialize(options)
assert.NoError(t, err)
assert.Equal(t, testcase.expectedKubernetes, cli.ClientInfo().HasKubernetes)
assert.Equal(t, testcase.expectedOrchestrator, string(cli.ClientInfo().Orchestrator))
})
}
}
func TestGetClientWithPassword(t *testing.T) { func TestGetClientWithPassword(t *testing.T) {
expected := "password" expected := "password"

View File

@ -33,7 +33,11 @@ func normalize(flag string) Orchestrator {
// GetOrchestrator checks DOCKER_ORCHESTRATOR environment variable and configuration file // GetOrchestrator checks DOCKER_ORCHESTRATOR environment variable and configuration file
// orchestrator value and returns user defined Orchestrator. // orchestrator value and returns user defined Orchestrator.
func GetOrchestrator(flagValue, value string) Orchestrator { func GetOrchestrator(isExperimental bool, flagValue, value string) Orchestrator {
// Non experimental CLI has kubernetes disabled
if !isExperimental {
return defaultOrchestrator
}
// Check flag // Check flag
if o := normalize(flagValue); o != orchestratorUnset { if o := normalize(flagValue); o != orchestratorUnset {
return o return o

View File

@ -19,7 +19,7 @@ func newDeployCommand(dockerCli command.Cli) *cobra.Command {
Args: cli.ExactArgs(1), Args: cli.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
opts.Namespace = args[0] opts.Namespace = args[0]
if dockerCli.ClientInfo().HasKubernetes() { if dockerCli.ClientInfo().HasKubernetes {
kli, err := kubernetes.WrapCli(dockerCli, cmd) kli, err := kubernetes.WrapCli(dockerCli, cmd)
if err != nil { if err != nil {
return err return err

View File

@ -18,7 +18,7 @@ func newListCommand(dockerCli command.Cli) *cobra.Command {
Short: "List stacks", Short: "List stacks",
Args: cli.NoArgs, Args: cli.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
if dockerCli.ClientInfo().HasKubernetes() { if dockerCli.ClientInfo().HasKubernetes {
kli, err := kubernetes.WrapCli(dockerCli, cmd) kli, err := kubernetes.WrapCli(dockerCli, cmd)
if err != nil { if err != nil {
return err return err

View File

@ -19,7 +19,7 @@ func newPsCommand(dockerCli command.Cli) *cobra.Command {
Args: cli.ExactArgs(1), Args: cli.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
opts.Namespace = args[0] opts.Namespace = args[0]
if dockerCli.ClientInfo().HasKubernetes() { if dockerCli.ClientInfo().HasKubernetes {
kli, err := kubernetes.WrapCli(dockerCli, cmd) kli, err := kubernetes.WrapCli(dockerCli, cmd)
if err != nil { if err != nil {
return err return err

View File

@ -19,7 +19,7 @@ func newRemoveCommand(dockerCli command.Cli) *cobra.Command {
Args: cli.RequiresMinArgs(1), Args: cli.RequiresMinArgs(1),
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
opts.Namespaces = args opts.Namespaces = args
if dockerCli.ClientInfo().HasKubernetes() { if dockerCli.ClientInfo().HasKubernetes {
kli, err := kubernetes.WrapCli(dockerCli, cmd) kli, err := kubernetes.WrapCli(dockerCli, cmd)
if err != nil { if err != nil {
return err return err

View File

@ -19,7 +19,7 @@ func newServicesCommand(dockerCli command.Cli) *cobra.Command {
Args: cli.ExactArgs(1), Args: cli.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
opts.Namespace = args[0] opts.Namespace = args[0]
if dockerCli.ClientInfo().HasKubernetes() { if dockerCli.ClientInfo().HasKubernetes {
kli, err := kubernetes.WrapCli(dockerCli, cmd) kli, err := kubernetes.WrapCli(dockerCli, cmd)
if err != nil { if err != nil {
return err return err

View File

@ -5,7 +5,8 @@ import (
"strings" "strings"
"testing" "testing"
"github.com/docker/cli/cli/config/configfile" "github.com/docker/cli/cli/command"
"github.com/docker/cli/internal/test" "github.com/docker/cli/internal/test"
"github.com/docker/docker/api" "github.com/docker/docker/api"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
@ -33,23 +34,14 @@ func fakeServerVersion(ctx context.Context) (types.Version, error) {
}, nil }, nil
} }
func TestVersionWithDefaultOrchestrator(t *testing.T) { func TestVersionWithOrchestrator(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{serverVersion: fakeServerVersion}) cli := test.NewFakeCli(&fakeClient{serverVersion: fakeServerVersion})
cli.SetClientInfo(func() command.ClientInfo { return command.ClientInfo{Orchestrator: "swarm"} })
cmd := NewVersionCommand(cli) cmd := NewVersionCommand(cli)
assert.NoError(t, cmd.Execute()) assert.NoError(t, cmd.Execute())
assert.Contains(t, cleanTabs(cli.OutBuffer().String()), "Orchestrator: swarm") assert.Contains(t, cleanTabs(cli.OutBuffer().String()), "Orchestrator: swarm")
} }
func TestVersionWithOverridenOrchestrator(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{serverVersion: fakeServerVersion})
config := configfile.New("configfile")
config.Orchestrator = "Kubernetes"
cli.SetConfigFile(config)
cmd := NewVersionCommand(cli)
assert.NoError(t, cmd.Execute())
assert.Contains(t, cleanTabs(cli.OutBuffer().String()), "Orchestrator: kubernetes")
}
func cleanTabs(line string) string { func cleanTabs(line string) string {
return strings.Join(strings.Fields(line), " ") return strings.Join(strings.Fields(line), " ")
} }

View File

@ -195,7 +195,24 @@ type versionDetails interface {
Client() client.APIClient Client() client.APIClient
ClientInfo() command.ClientInfo ClientInfo() command.ClientInfo
ServerInfo() command.ServerInfo ServerInfo() command.ServerInfo
ClientInfo() command.ClientInfo }
func hideFeatureFlag(f *pflag.Flag, hasFeature bool, annotation string) {
if hasFeature {
return
}
if _, ok := f.Annotations[annotation]; ok {
f.Hidden = true
}
}
func hideFeatureSubCommand(subcmd *cobra.Command, hasFeature bool, annotation string) {
if hasFeature {
return
}
if _, ok := subcmd.Annotations[annotation]; ok {
subcmd.Hidden = true
}
} }
func hideUnsupportedFeatures(cmd *cobra.Command, details versionDetails) { func hideUnsupportedFeatures(cmd *cobra.Command, details versionDetails) {
@ -206,27 +223,10 @@ func hideUnsupportedFeatures(cmd *cobra.Command, details versionDetails) {
hasKubernetes := details.ClientInfo().HasKubernetes hasKubernetes := details.ClientInfo().HasKubernetes
cmd.Flags().VisitAll(func(f *pflag.Flag) { cmd.Flags().VisitAll(func(f *pflag.Flag) {
// hide experimental flags hideFeatureFlag(f, hasExperimental, "experimental")
if !hasExperimental { hideFeatureFlag(f, hasExperimentalCLI, "experimentalCLI")
if _, ok := f.Annotations["experimental"]; ok { hideFeatureFlag(f, hasKubernetes, "kubernetes")
f.Hidden = true hideFeatureFlag(f, !hasKubernetes, "swarm")
}
}
if !hasExperimentalCLI {
if _, ok := f.Annotations["experimentalCLI"]; ok {
f.Hidden = true
}
}
if !hasKubernetes {
if _, ok := f.Annotations["kubernetes"]; ok {
f.Hidden = true
}
} else {
if _, ok := f.Annotations["swarm"]; ok {
f.Hidden = true
}
}
// hide flags not supported by the server // hide flags not supported by the server
if !isOSTypeSupported(f, osType) || !isVersionSupported(f, clientVersion) { if !isOSTypeSupported(f, osType) || !isVersionSupported(f, clientVersion) {
f.Hidden = true f.Hidden = true
@ -234,28 +234,10 @@ func hideUnsupportedFeatures(cmd *cobra.Command, details versionDetails) {
}) })
for _, subcmd := range cmd.Commands() { for _, subcmd := range cmd.Commands() {
// hide experimental subcommands hideFeatureSubCommand(subcmd, hasExperimental, "experimental")
if !hasExperimental { hideFeatureSubCommand(subcmd, hasExperimentalCLI, "experimentalCLI")
if _, ok := subcmd.Annotations["experimental"]; ok { hideFeatureSubCommand(subcmd, hasKubernetes, "kubernetes")
subcmd.Hidden = true hideFeatureSubCommand(subcmd, !hasKubernetes, "swarm")
}
}
if !hasExperimentalCLI {
if _, ok := subcmd.Annotations["experimentalCLI"]; ok {
subcmd.Hidden = true
}
}
if !hasKubernetes {
if _, ok := subcmd.Annotations["kubernetes"]; ok {
subcmd.Hidden = true
}
} else {
if _, ok := subcmd.Annotations["swarm"]; ok {
subcmd.Hidden = true
}
}
// hide subcommands not supported by the server // hide subcommands not supported by the server
if subcmdVersion, ok := subcmd.Annotations["version"]; ok && versions.LessThan(clientVersion, subcmdVersion) { if subcmdVersion, ok := subcmd.Annotations["version"]; ok && versions.LessThan(clientVersion, subcmdVersion) {
subcmd.Hidden = true subcmd.Hidden = true
@ -279,7 +261,8 @@ func areFlagsSupported(cmd *cobra.Command, details versionDetails) error {
clientVersion := details.Client().ClientVersion() clientVersion := details.Client().ClientVersion()
osType := details.ServerInfo().OSType osType := details.ServerInfo().OSType
hasExperimental := details.ServerInfo().HasExperimental hasExperimental := details.ServerInfo().HasExperimental
hasKubernetes := details.ClientInfo().HasKubernetes() hasKubernetes := details.ClientInfo().HasKubernetes
hasExperimentalCLI := details.ClientInfo().HasExperimental
errs := []string{} errs := []string{}

View File

@ -15,6 +15,7 @@ import (
) )
type notaryClientFuncType func(imgRefAndAuth trust.ImageRefAndAuth, actions []string) (notaryclient.Repository, error) type notaryClientFuncType func(imgRefAndAuth trust.ImageRefAndAuth, actions []string) (notaryclient.Repository, error)
type clientInfoFuncType func() command.ClientInfo
// FakeCli emulates the default DockerCli // FakeCli emulates the default DockerCli
type FakeCli struct { type FakeCli struct {
@ -26,6 +27,7 @@ type FakeCli struct {
err *bytes.Buffer err *bytes.Buffer
in *command.InStream in *command.InStream
server command.ServerInfo server command.ServerInfo
clientInfoFunc clientInfoFuncType
notaryClientFunc notaryClientFuncType notaryClientFunc notaryClientFuncType
} }
@ -88,6 +90,19 @@ func (c *FakeCli) ServerInfo() command.ServerInfo {
return c.server return c.server
} }
// ClientInfo returns client information
func (c *FakeCli) ClientInfo() command.ClientInfo {
if c.clientInfoFunc != nil {
return c.clientInfoFunc()
}
return c.DockerCli.ClientInfo()
}
// SetClientInfo sets the internal getter for retrieving a ClientInfo
func (c *FakeCli) SetClientInfo(clientInfoFunc clientInfoFuncType) {
c.clientInfoFunc = clientInfoFunc
}
// OutBuffer returns the stdout buffer // OutBuffer returns the stdout buffer
func (c *FakeCli) OutBuffer() *bytes.Buffer { func (c *FakeCli) OutBuffer() *bytes.Buffer {
return c.outBuffer return c.outBuffer