Skip to content

Conversation

@aiordache
Copy link
Contributor

Change required by PR-625

- What I did
Moved cli config load in ClientInfo() function such that when calling it we don't have to initialize the struct in case it isn't.
- How I did it
Load cli config on the first call of ClientInfo().
- How to verify it
ClientInfo() should always return an object with the config data already loaded.
- Description for the changelog
Load cli config on the first call to the ClientInfo() from the cli interface
- A picture of a cute animal (not mandatory but encouraged)
8d1

Copy link
Contributor

@silvin-lubecki silvin-lubecki left a comment

Choose a reason for hiding this comment

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

@aiordache can you rebase on top of master?

if experimentalValue = os.Getenv("DOCKER_CLI_EXPERIMENTAL"); experimentalValue == "" {
experimentalValue = cli.ConfigFile().Experimental
}
hasExperimental, _ := isEnabled(experimentalValue)
Copy link
Contributor

Choose a reason for hiding this comment

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

Here we are dropping the error, so we will be silent if the experimentalValue is not valid. I don't want to panic here, but returning an error in ClientInfo() would break many people. @thaJeztah any idea?

Copy link
Member

Choose a reason for hiding this comment

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

Looking at it if we can find a way around that. The problem is that with these changes, these "getters" are no longer "getters"; they're doing way more than that (a getter should never return an error, but now they're loading, validating, and returning the info

@aiordache aiordache force-pushed the app-214_client_info_load_func branch from 577cf52 to 7091f8e Compare October 3, 2019 10:12
@aiordache aiordache changed the title Load Client info in getter function APP-214 Load Client info in getter function Oct 3, 2019
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.

Looking at some options, and have pushes a branch with a possible approach

if cli.configFile != nil {
return cli.configFile
}
cli.configFile = cliconfig.LoadDefaultConfigFile(cli.err)
Copy link
Member

Choose a reason for hiding this comment

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

Small nit; I'm usually in favor of doing an "early return", but given that this function is really small, perhaps this would be slightly cleaner;

// ConfigFile returns the ConfigFile
func (cli *DockerCli) ConfigFile() *configfile.ConfigFile {
	if cli.configFile == nil {
		cli.configFile = cliconfig.LoadDefaultConfigFile(cli.err)
	}
	return cli.configFile
}

We should update the Description as well, to mention that it also loads the configuration file.

Something like:

// ConfigFile loads the ConfigFile if it has not yet been loaded, and returns it

Copy link
Member

Choose a reason for hiding this comment

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

Actually, looking at this; I wonder if this loads the correct config-file, because it's not taking the --config flag into account? 🤔

cli/cli/command/cli.go

Lines 202 to 210 in 0f337f1

if opts.ConfigDir != "" {
cliconfig.SetDir(opts.ConfigDir)
}
if opts.Common.Debug {
debug.Enable()
}
cli.configFile = cliconfig.LoadDefaultConfigFile(cli.err)

if experimentalValue = os.Getenv("DOCKER_CLI_EXPERIMENTAL"); experimentalValue == "" {
experimentalValue = cli.ConfigFile().Experimental
}
hasExperimental, _ := isEnabled(experimentalValue)
Copy link
Member

Choose a reason for hiding this comment

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

Looking at it if we can find a way around that. The problem is that with these changes, these "getters" are no longer "getters"; they're doing way more than that (a getter should never return an error, but now they're loading, validating, and returning the info

}
hasExperimental, _ := isEnabled(experimentalValue)

version := ""
Copy link
Member

Choose a reason for hiding this comment

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

this clashes with the github.com/docker/cli/cli/version import

Suggested change
version := ""
v := ""

if cli.client != nil {
version = cli.client.ClientVersion()
} else {
version = api.DefaultVersion
Copy link
Member

Choose a reason for hiding this comment

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

Is this also a problem if this is called from the plugin? (as in; if there's no client, it will always return the default version, which may not match with the daemon that is used

@thaJeztah
Copy link
Member

thaJeztah commented Oct 4, 2019

OK, pushed one possible alternative, but it's also not perfect; https://github.com/docker/cli/compare/master...thaJeztah:app-214_client_info_load_func_alt?expand=1

Description (and change) is in this commit dd73b46;

Possible approach for client info

  • split ClientInfo() into ClientInfo() and loadClientInfo()
  • split ConfigFile() into ConfigFile() and loadConfigFile()
  • ConfigFile() and ClientInfo() call their corresponding loadXX function
    if it has not yet been loaded; this allows them to be used before
    Initialize() was called.
  • Initialize() always (re-)loads the configuration; this makes sure
    that the correct configuration is used when actually calling commands.

I think the problem remains that (IIUC), the client is not initialised at that point, so we're still working with partial / incomplete data (config-dir may be incorrect, and api-client not initialised, so we don't know the API version that the daemon supports, or if the daemon has experimental features enabled).

I also explored the "functional arguments" variant for a bit, but I wasn't fully happy with that yet, because they would also have the same problem, and have to be used in the correct order (load flags, load config, load client, get clientinfo). I think it looks cleaner with those options, but that needs more work (and thinking); https://github.com/docker/cli/compare/master..thaJeztah:more_options?expand=1

@aiordache aiordache force-pushed the app-214_client_info_load_func branch 2 times, most recently from ac3f562 to 843aa5c Compare November 7, 2019 09:01
@GordonTheTurtle
Copy link

Please sign your commits following these rules:
https://github.com/moby/moby/blob/master/CONTRIBUTING.md#sign-your-work
The easiest way to do this is to amend the last commit:

$ git clone -b "app-214_client_info_load_func" git@github.com:aiordache/cli.git somewhere
$ cd somewhere
$ git rebase -i HEAD~842354319888
editor opens
change each 'pick' to 'edit'
save the file and quit
$ git commit --amend -s --no-edit
$ git rebase --continue # and repeat the amend for each commit
$ git push -f

Amending updates the existing PR. You DO NOT need to open a new one.

@aiordache aiordache force-pushed the app-214_client_info_load_func branch from 843aa5c to 12d90c6 Compare November 7, 2019 09:04
@aiordache aiordache force-pushed the app-214_client_info_load_func branch from 3aa1869 to 429144d Compare November 7, 2019 10:58
Copy link
Contributor

@silvin-lubecki silvin-lubecki left a comment

Choose a reason for hiding this comment

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

LGTM

@aiordache aiordache force-pushed the app-214_client_info_load_func branch from 41d2a2b to f98de1c Compare November 8, 2019 09:50
Signed-off-by: Anca Iordache <anca.iordache@docker.com>

Possible approach for client info

- split ClientInfo() into ClientInfo() and loadClientInfo()
- split ConfigFile() into ConfigFile() and loadConfigFile()
- ConfigFile() and ClientInfo() call their corresponding loadXX function
  if it has not yet been loaded; this allows them to be used before
  Initialize() was called.
- Initialize() *always* (re-)loads the configuration; this makes sure
  that the correct configuration is used when actually calling commands.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
@aiordache aiordache force-pushed the app-214_client_info_load_func branch from f98de1c to 22a5dad Compare November 8, 2019 10:39
@silvin-lubecki silvin-lubecki merged commit 37f9a88 into docker:master Nov 8, 2019
rumpl added a commit to rumpl/app that referenced this pull request Nov 8, 2019
Once app is GA and no longer hidden experimental we will want to hide
the cnab-bundle-json flag if the user didn't activate experimental
features. docker/cli was updated to latest that had the fix for cli
plugins to be able to get the client configuration (docker/cli#2095)
rumpl added a commit to rumpl/app that referenced this pull request Nov 8, 2019
Once app is GA and no longer hidden experimental we will want to hide
the cnab-bundle-json flag if the user didn't activate experimental
features. docker/cli was updated to latest that had the fix for cli
plugins to be able to get the client configuration (docker/cli#2095)

Signed-off-by: Djordje Lukic <djordje.lukic@docker.com>
@thaJeztah thaJeztah added this to the 20.03.0 milestone Feb 19, 2020
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.

4 participants