-
Notifications
You must be signed in to change notification settings - Fork 1.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Better namespace experience with Kubernetes #991
Conversation
a17f07f
to
b03b1c0
Compare
@silvin-lubecki looks like there's a linting issue
|
Yes, I'm on it, thanks @thaJeztah! |
b03b1c0
to
e3fb0c4
Compare
PTAL |
e3fb0c4
to
27f8396
Compare
Rebased! |
@silvin-lubecki what's the easiest way for me to test this ? |
@vieux silvin is on holiday, I'm carrying his PRs meanwhile. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 🐸
On non docker-for-desktop, you need to have |
cli/command/stack/kubernetes/cli.go
Outdated
|
||
configNamespace, _, err := clientConfig.Namespace() | ||
if err != nil { | ||
return nil, err |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this code is executed (possibly showing an error) even if the namespace is overridden through opts.Namespace
. Retrieving the namespace from the config should probably be done conditional (i.e., if there's no --namespace
option set)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, I'll invert the condition below, but the code in here is likely going to change when I address your next comment about --namespace
.
cli/command/stack/kubernetes/cli.go
Outdated
return nil, err | ||
} | ||
cli.kubeNamespace = configNamespace | ||
if opts.Namespace != "default" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- What if
opts.Namespace
is an empty string? (also; I'm not a big fan of magic words, such as"default"
for default values) - What if I run
docker stack ls --namespace=default
; will the specified ("default"
) namespace be ignored? (perhapskubernetes.NewOptions()
should useflags.Changed()
to detect if the flag was set (even if it's with the default valuecli/cli/command/stack/kubernetes/cli.go
Lines 31 to 41 in 854aad8
// NewOptions returns an Options initialized with command line flags func NewOptions(flags *flag.FlagSet) Options { var opts Options if namespace, err := flags.GetString("namespace"); err == nil { opts.Namespace = namespace } if kubeConfig, err := flags.GetString("kubeconfig"); err == nil { opts.Config = kubeConfig } return opts }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Running a complete set of (manual) tests with both kubectl get stacks
and docker stack ls
reveals a few discrepancies. I'll sort that out.
kubernetes/config.go
Outdated
"k8s.io/client-go/tools/clientcmd" | ||
) | ||
|
||
// NewKubernetesConfig resolves the path to the desired Kubernetes configuration file, depending | ||
// environment variable and command line flag. | ||
func NewKubernetesConfig(configFlag string) (*restclient.Config, error) { | ||
func NewKubernetesConfig(configFlag string) clientcmd.ClientConfig { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not new, but the configFlag
variable is a bit confusing (i.e., it's not the flag itself, but a custom path, which happens to be passed through a flag). Perhaps renamed this to (e.g.) configPath
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, changing this.
kubernetes/config.go
Outdated
"k8s.io/client-go/tools/clientcmd" | ||
) | ||
|
||
// NewKubernetesConfig resolves the path to the desired Kubernetes configuration file, depending | ||
// environment variable and command line flag. | ||
func NewKubernetesConfig(configFlag string) (*restclient.Config, error) { | ||
func NewKubernetesConfig(configFlag string) clientcmd.ClientConfig { | ||
kubeConfig := configFlag | ||
if kubeConfig == "" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The exact same code is also in cli.WrapCli()
(and looks to be redundant). I suggest extracting this to a function, e.g.
func ConfigPath(kubeconfigPath string) string {
if kubeconfigPath != "" {
return kubeconfigPath
}
if config := os.Getenv("KUBECONFIG"); config != "" {
return config
}
return filepath.Join(homedir.Get(), ".kube/config")
}
Is a non-existing path reason for an error?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well actually WrapCli
calls NewKubernetesConfig
right after the duplicated code so this looks like the code was moved/factorized and not removed…
Fixed!
cli/command/formatter/stack.go
Outdated
} | ||
|
||
// NewStackFormat returns a format for use with a stack Context | ||
func NewStackFormat(source string) Format { | ||
switch source { | ||
case TableFormatKey: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a change in behaviour; before this change:
docker stack ls --format=table
NAME SERVICES
foobar 1
After this change:
docker stack ls --format=table
# (no output)
Perhaps remove this function, and in swarm/kubernetes do;
if len(format) == 0 || format == formatter.TableFormatKey {
format = formatter.KubernetesStackTableFormat
}
stackCtx := formatter.Context{
Output: dockerCli.Out(),
Format: formatter.Format(format),
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, fixing this!
cli/command/stack/kubernetes/list.go
Outdated
@@ -17,7 +17,7 @@ func RunList(dockerCli *KubeCli, opts options.List) error { | |||
} | |||
format := opts.Format | |||
if len(format) == 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See my other comment above
cli/command/stack/swarm/list.go
Outdated
@@ -25,7 +25,7 @@ func RunList(dockerCli command.Cli, opts options.List) error { | |||
} | |||
format := opts.Format | |||
if len(format) == 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See my other comment above
@@ -31,5 +31,7 @@ func newListCommand(dockerCli command.Cli) *cobra.Command { | |||
|
|||
flags := cmd.Flags() | |||
flags.StringVar(&opts.Format, "format", "", "Pretty-print stacks using a Go template") | |||
flags.BoolVarP(&opts.AllNamespaces, "all-namespaces", "", false, "List stacks among all Kubernetes namespaces") | |||
flags.SetAnnotation("all-namespaces", "kubernetes", nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this have to be gated by API-version as well? (possibly not because it was experimental so far)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes it was experimental and also targeting only Kubernetes and UCP. The behavior toward the Docker daemon is supposed to not have been changed.
@@ -31,5 +31,7 @@ func newListCommand(dockerCli command.Cli) *cobra.Command { | |||
|
|||
flags := cmd.Flags() | |||
flags.StringVar(&opts.Format, "format", "", "Pretty-print stacks using a Go template") | |||
flags.BoolVarP(&opts.AllNamespaces, "all-namespaces", "", false, "List stacks among all Kubernetes namespaces") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wonder if we considered
- using
--namespace=all
(e.g.) to show all namespaces (which would be consistent with--orchestrator=all
), also allowing listing stack in a single namespace--namespace=<something>
- showing all namespaces by default, but use a
--filter namespace=foo
to limit the output
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe what drives the current design is to mimic what kubectl
does in order to not confuse Kubernetes users.
Oh, this also needs a documentation update to document the |
For the record, here is the manual test suite I ran against kubectl, obviously this is highly dependent on the services deployed beforehand…
|
And here is the matching
|
@thaJeztah I believe I have addressed all your comments. I added small commits so it remains easy for you to check the changes, but afterwards if you would rather have me collapse them or merge them with the bigger commits from @silvin-lubecki I'll do it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, but if you can combine some of the commits, that'd be good
Signed-off-by: Silvin Lubecki <[email protected]>
Signed-off-by: Silvin Lubecki <[email protected]>
…elongs Signed-off-by: Silvin Lubecki <[email protected]>
…rnetes orchestrator Signed-off-by: Silvin Lubecki <[email protected]>
…rator, to list all stacks in all namespaces. Signed-off-by: Silvin Lubecki <[email protected]>
…alues Signed-off-by: Mathieu Champlon <[email protected]>
a82c9f1
to
2af66be
Compare
Done, thanks for your help! |
- What I did
I redesigned a better UX for namespaces with Kubernetes:
~/.kube/config
is now used with all stack commandsNAMESPACE
column is added fordocker stack ls
command on Kubernetes orchestrator only--all-namespaces
flag is added fordocker stack ls
command on Kubernetes orchestrator only- How I did it
NAMESPACE
column, I modified the formatter/stack.go:NewStackFormat function, which is now almost no-op. We now have two default format, a Kubernetes one with a NAMESPACE column, and a Swarm one without it, so I let the caller choosing the appropriate default table format. Buy the way now these two default format are exported. A closer look will be appreciated 😄--all-namespaces
flag, I patched the Stack client to handle the all-namespaces option on List command. All stack clients are namespaced, but with Kubernetes, setting the namespace to empty string means all namespaces.- How to verify it
- Description for the changelog
- A picture of a cute animal (not mandatory but encouraged)