Skip to content

Conversation

@vdemeester
Copy link
Collaborator

@vdemeester vdemeester commented Dec 20, 2017

Allow to mark some commands and flags experimental on cli (i.e. not
depending to the state of the daemon). This will allow more flexibility
on experimentation with the cli.

Marking docker trust as cli experimental as it is documented so.

$ docker trust --help
docker trust is only supported on a Docker cli with experimental features enabled
# edit docker client configuration file
$ cat ~/.docker/config.json
{
        "experimental": "enabled"
}
$ docker trust --help
Usage:  docker trust COMMAND

Manage trust on Docker images (experimental)

Options:


Management Commands:
  key         Manage keys for signing Docker images (experimental)
  signer      Manage entities who can sign Docker images (experimental)

Commands:
  revoke      Remove trust for an image
  sign        Sign an image
  view        Display detailed information about keys and signatures

Run 'docker trust COMMAND --help' for more information on a command.

This is required for #721 (as we will put the k8s support under experimental at first)

jpeg image 271 x 186 pixels

Signed-off-by: Vincent Demeester [email protected]

func isExperimentalCli(configfile *configfile.ConfigFile) bool {
if e := os.Getenv("DOCKER_EXPERIMENTAL_CLI"); e != "" {
value := strings.ToLower(e)
return value == "1" || value == "y" || value == "yes"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no support for "true"?

Probably strconv.ParseBool should be used

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thx @AkihiroSuda 🤗

}

func isExperimentalCli(configfile *configfile.ConfigFile) bool {
if e := os.Getenv("DOCKER_EXPERIMENTAL_CLI"); e != "" {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this environment variable is useful. Contrary to the DOCKER_ORCHESTRATOR one which you can use to switch between orchestrators, I think switching to experimental features should be a "long term" choice from the user.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, we can probably skip it for now. Easy to add in future if there's a real need for it.

@codecov-io
Copy link

codecov-io commented Dec 20, 2017

Codecov Report

Merging #758 into master will increase coverage by 0.01%.
The diff coverage is 41.02%.

@@            Coverage Diff             @@
##           master     #758      +/-   ##
==========================================
+ Coverage   53.45%   53.46%   +0.01%     
==========================================
  Files         218      218              
  Lines       14613    14642      +29     
==========================================
+ Hits         7811     7829      +18     
- Misses       6321     6327       +6     
- Partials      481      486       +5

Copy link
Member

@thaJeztah thaJeztah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From a user-perspective, I wonder if we should have some connection between "server experimental" and "client experimental".

Thinking something like;

  • auto (default) CLI follows daemon's "experimental"
  • disabled Disable all experimental features; hide experimental commands, even if they are enabled on the daemon
  • enabled Enable experimental (cli) commands; experimental features that require the daemon to have experimental are still disabled

It's a bit tricky if people want to be able to enable/disable them separate (without having access to the daemon), in which case it'd become;

  • auto | disabled | enabled | cli-only | daemon-only ? (most likely too detailed)

We'll need some documentation around this, because for users it will not be clear which features are client-side, and which ones are daemon-side.

return err
}
cli.clientInfo = ClientInfo{
HasExperimental: isExperimentalCli(cli.configFile),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably need to add this information to the docker version output as well;

type clientVersion struct {
Platform struct{ Name string } `json:",omitempty"`
Version string
APIVersion string `json:"ApiVersion"`
DefaultAPIVersion string `json:"DefaultAPIVersion,omitempty"`
GitCommit string
GoVersion string
Os string
Arch string
BuildTime string `json:",omitempty"`
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah right !

}

func isExperimentalCli(configfile *configfile.ConfigFile) bool {
if e := os.Getenv("DOCKER_EXPERIMENTAL_CLI"); e != "" {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, we can probably skip it for now. Easy to add in future if there's a real need for it.

@vdemeester
Copy link
Collaborator Author

vdemeester commented Dec 20, 2017

@thaJeztah Interesting, I like that approach 👼

Copy link
Contributor

@dnephin dnephin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought we were considering calling this "beta" instead of experimental. What happened with that discussion?

}

cli := &DockerCli{client: apiclient, err: os.Stderr}
t.Log("yo ", tmpDir)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oups 🤣

}
}

func createTemporaryConfigfile(t *testing.T, name, content string) (string, func()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be replaced with

dir := fs.NewDir(t, name, fs.WithFile("config.json", content))
defer dir.Remove()

defaultVersion string
server ServerInfo
serverInfo ServerInfo
clientInfo ClientInfo
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could move defaultVersion to clientInfo I think, but doesn't need to happen in this PR.

errs = append(errs, fmt.Sprintf("\"--%s\" is only supported on a Docker daemon with experimental features enabled", f.Name))
}
if _, ok := f.Annotations["experimentalCli"]; ok && !hasExperimentalCli {
errs = append(errs, fmt.Sprintf("\"--%s\" is only supported on a Docker cli with experimental features enabled", f.Name))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"only supported when experimental cli features are enabled"

I just realized all of this was duplicated. We should be able to declare this visitor once, and call it for the root command case. Doesn't need to be part of this PR.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dnephin yep, we realized that too in #721 just didn't want to add more code to it 😛

return fmt.Errorf("%s is only supported on a Docker daemon with experimental features enabled", cmd.CommandPath())
}
if _, ok := curr.Annotations["experimentalCli"]; ok && !hasExperimentalCli {
return fmt.Errorf("%s is only supported on a Docker cli with experimental features enabled", cmd.CommandPath())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"only supported when experimental cli features are enabled"

@dnephin
Copy link
Contributor

dnephin commented Dec 20, 2017

From a user-perspective, I wonder if we should have some connection between "server experimental" and "client experimental".

I think this implies there is some relationship between the two, when in reality there is not. I think it would be better to keep them separate. Even using different names for them would be great (beta vs experimental).

@thaJeztah
Copy link
Member

The tricky bit is that something being "client side" or "daemon side" should largely be an implementation detail; most users won't be aware where the functionality lives, and I'm not sure we should put that burden onto them if not needed for the 99% (but we can still consider having more fine-grained options in addition).

Some features may even move from cli to daemon (or vice versa)

@dnephin
Copy link
Contributor

dnephin commented Dec 20, 2017

I think the reality is that the user needs to be aware of where it's implemented because a single client can connect to more than one server.

We could maybe avoid some of the confusion by using feature flags instead of a global "experimental". So users could enable trust, or k8s-stacks, instead of enabling everything.

@vdemeester
Copy link
Collaborator Author

@thaJeztah @dnephin Updated with comments taken into account. Switch to enabled and disabled as value so we could, in the future, have more options for it 😉

@thaJeztah
Copy link
Member

enabled|disabled LGTM, but still would love to see auto, as it feels natural to me to (if no configuration is set) have the CLI follow the daemon (and not require people to set the "experimental" option in two locations)

because a single client can connect to more than one server.

Different topic, but we could really use a way to set multiple configurations (per daemon/host), either by having a nodes: [{}] option in the configuration file, or (likely more flexible) having subdirectories with configuration files per-host (a-la docker-machine). We have --config already, but I can see there's configurations that are "global", and ones that are "per host"

@vdemeester
Copy link
Collaborator Author

@thaJeztah could we add auto on a follow-up PR (to discuss it) ? 👼

Different topic, but we could really use a way to set multiple configurations (per daemon/host), either by having a nodes: [{}] option in the configuration file, or (likely more flexible) having subdirectories with configuration files per-host (a-la docker-machine).

Yes ! This is in my TODOs 👼

@thaJeztah
Copy link
Member

could we add auto on a follow-up PR (to discuss it) ?

Yes, definitely; current implementation allows expanding options (hence: not using a boolean true/false)

LGTM, but awaiting @dnephin before moving to "code review"

case "", "disabled":
return false, nil
default:
return false, errors.Errorf("%q is not valid, should be either enabled or disabled", value)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think we should mention the configuration option here, currently it shows:

$ docker version
"Moby was here" is not valid, should be either enabled or disabled

Perhaps something like:

Invalid value for "experimentalCli": "Moby was here". Valid options are "enabled" and "disabled"

(better suggestions welcome)

NodesFormat string `json:"nodesFormat,omitempty"`
PruneFilters []string `json:"pruneFilters,omitempty"`
Proxies map[string]ProxyConfig `json:"proxies,omitempty"`
ExperimentalCli string `json:"experimentalCli,omitempty"`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CLI is an acronym, so this should be ExperimentalCLI (and experimentalCLI for JSON)

Given that this configuration file is for the CLI; is CLI a bit redundant? Perhaps just Experimental?

Copy link
Contributor

@dnephin dnephin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

design LGTM

}
hasExperimental, err := isEnabled(cli.configFile.ExperimentalCli)
if err != nil {
return err
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this should errors.Wrapf(err, "ExperimentalCLI field") so that the error message mentions which field has a problem

@vdemeester
Copy link
Collaborator Author

cc @AkihiroSuda @yongtang

@vdemeester vdemeester force-pushed the experimental-cli branch 2 times, most recently from deae842 to bae6e20 Compare December 22, 2017 13:33
}
}

func TestExperimentalCli(t *testing.T) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

small nit: TestExperimentalCLI to stay consistent with casing

@tiborvass
Copy link
Collaborator

LGTM

Allow to mark some commands and flags experimental on cli (i.e. not
depending to the state of the daemon). This will allow more flexibility
on experimentation with the cli.

Marking `docker trust` as cli experimental as it is documented so.

Signed-off-by: Vincent Demeester <[email protected]>
Copy link
Member

@thaJeztah thaJeztah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

@thaJeztah thaJeztah merged commit 70db7cc into docker:master Dec 22, 2017
@GordonTheTurtle GordonTheTurtle added this to the 18.01.0 milestone Dec 22, 2017
@vdemeester vdemeester deleted the experimental-cli branch December 22, 2017 13:59
@bitsofinfo
Copy link

thx

nobiit pushed a commit to nobidev/docker-cli that referenced this pull request Nov 19, 2025
Add support for experimental Cli configuration
Upstream-commit: 70db7cc
Component: cli
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants