Add namespace column for docker stack ls command while targeting Kubernetes orchestrator

Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
This commit is contained in:
Silvin Lubecki 2018-04-09 15:11:45 +02:00 committed by Mathieu Champlon
parent 31dccfffb5
commit 65526a201f
7 changed files with 39 additions and 24 deletions

View File

@ -5,10 +5,14 @@ import (
) )
const ( const (
defaultStackTableFormat = "table {{.Name}}\t{{.Services}}\t{{.Orchestrator}}" // KubernetesStackTableFormat is the default Kubernetes stack format
KubernetesStackTableFormat = "table {{.Name}}\t{{.Services}}\t{{.Orchestrator}}\t{{.Namespace}}"
// SwarmStackTableFormat is the default Swarm stack format
SwarmStackTableFormat = "table {{.Name}}\t{{.Services}}\t{{.Orchestrator}}"
stackServicesHeader = "SERVICES" stackServicesHeader = "SERVICES"
stackOrchestrastorHeader = "ORCHESTRATOR" stackOrchestrastorHeader = "ORCHESTRATOR"
stackNamespaceHeader = "NAMESPACE"
) )
// Stack contains deployed stack information. // Stack contains deployed stack information.
@ -17,17 +21,10 @@ type Stack struct {
Name string Name string
// Services is the number of the services // Services is the number of the services
Services int Services int
// Orchestratort is the platform on which the stack is deployed // Orchestrator is the platform where the stack is deployed
Orchestrator string Orchestrator string
} // Namespace is the Kubernetes namespace assigned to the stack
Namespace string
// NewStackFormat returns a format for use with a stack Context
func NewStackFormat(source string) Format {
switch source {
case TableFormatKey:
return defaultStackTableFormat
}
return Format(source)
} }
// StackWrite writes formatted stacks using the Context // StackWrite writes formatted stacks using the Context
@ -54,6 +51,7 @@ func newStackContext() *stackContext {
"Name": nameHeader, "Name": nameHeader,
"Services": stackServicesHeader, "Services": stackServicesHeader,
"Orchestrator": stackOrchestrastorHeader, "Orchestrator": stackOrchestrastorHeader,
"Namespace": stackNamespaceHeader,
} }
return &stackCtx return &stackCtx
} }
@ -73,3 +71,7 @@ func (s *stackContext) Services() string {
func (s *stackContext) Orchestrator() string { func (s *stackContext) Orchestrator() string {
return s.s.Orchestrator return s.s.Orchestrator
} }
func (s *stackContext) Namespace() string {
return s.s.Namespace
}

View File

@ -26,14 +26,22 @@ func TestStackContextWrite(t *testing.T) {
}, },
// Table format // Table format
{ {
Context{Format: NewStackFormat("table")}, Context{Format: Format(SwarmStackTableFormat)},
`NAME SERVICES ORCHESTRATOR `NAME SERVICES ORCHESTRATOR
baz 2 orchestrator1 baz 2 orchestrator1
bar 1 orchestrator2 bar 1 orchestrator2
`, `,
}, },
// Kubernetes table format adds Namespace column
{ {
Context{Format: NewStackFormat("table {{.Name}}")}, Context{Format: Format(KubernetesStackTableFormat)},
`NAME SERVICES ORCHESTRATOR NAMESPACE
baz 2 orchestrator1 namespace1
bar 1 orchestrator2 namespace2
`,
},
{
Context{Format: Format("table {{.Name}}")},
`NAME `NAME
baz baz
bar bar
@ -41,7 +49,7 @@ bar
}, },
// Custom Format // Custom Format
{ {
Context{Format: NewStackFormat("{{.Name}}")}, Context{Format: Format("{{.Name}}")},
`baz `baz
bar bar
`, `,
@ -49,8 +57,8 @@ bar
} }
stacks := []*Stack{ stacks := []*Stack{
{Name: "baz", Services: 2, Orchestrator: "orchestrator1"}, {Name: "baz", Services: 2, Orchestrator: "orchestrator1", Namespace: "namespace1"},
{Name: "bar", Services: 1, Orchestrator: "orchestrator2"}, {Name: "bar", Services: 1, Orchestrator: "orchestrator2", Namespace: "namespace2"},
} }
for _, testcase := range cases { for _, testcase := range cases {
out := bytes.NewBufferString("") out := bytes.NewBufferString("")

View File

@ -37,6 +37,7 @@ func stackFromV1beta1(in *v1beta1.Stack) (stack, error) {
} }
return stack{ return stack{
name: in.ObjectMeta.Name, name: in.ObjectMeta.Name,
namespace: in.ObjectMeta.Namespace,
composeFile: in.Spec.ComposeFile, composeFile: in.Spec.ComposeFile,
spec: fromComposeConfig(ioutil.Discard, cfg), spec: fromComposeConfig(ioutil.Discard, cfg),
}, nil }, nil
@ -55,8 +56,9 @@ func stackToV1beta1(s stack) *v1beta1.Stack {
func stackFromV1beta2(in *v1beta2.Stack) stack { func stackFromV1beta2(in *v1beta2.Stack) stack {
return stack{ return stack{
name: in.ObjectMeta.Name, name: in.ObjectMeta.Name,
spec: in.Spec, namespace: in.ObjectMeta.Namespace,
spec: in.Spec,
} }
} }

View File

@ -16,12 +16,12 @@ func RunList(dockerCli *KubeCli, opts options.List) error {
return err return err
} }
format := opts.Format format := opts.Format
if len(format) == 0 { if format == "" || format == formatter.TableFormatKey {
format = formatter.TableFormatKey format = formatter.KubernetesStackTableFormat
} }
stackCtx := formatter.Context{ stackCtx := formatter.Context{
Output: dockerCli.Out(), Output: dockerCli.Out(),
Format: formatter.NewStackFormat(format), Format: formatter.Format(format),
} }
sort.Sort(byName(stacks)) sort.Sort(byName(stacks))
return formatter.StackWrite(stackCtx, stacks) return formatter.StackWrite(stackCtx, stacks)
@ -51,6 +51,7 @@ func getStacks(kubeCli *KubeCli) ([]*formatter.Stack, error) {
Name: stack.name, Name: stack.name,
Services: len(stack.getServices()), Services: len(stack.getServices()),
Orchestrator: "Kubernetes", Orchestrator: "Kubernetes",
Namespace: stack.namespace,
}) })
} }
return formattedStacks, nil return formattedStacks, nil

View File

@ -15,6 +15,7 @@ import (
// stack is the main type used by stack commands so they remain independent from kubernetes compose component version. // stack is the main type used by stack commands so they remain independent from kubernetes compose component version.
type stack struct { type stack struct {
name string name string
namespace string
composeFile string composeFile string
spec *v1beta2.StackSpec spec *v1beta2.StackSpec
} }

View File

@ -24,12 +24,12 @@ func RunList(dockerCli command.Cli, opts options.List) error {
return err return err
} }
format := opts.Format format := opts.Format
if len(format) == 0 { if format == "" || format == formatter.TableFormatKey {
format = formatter.TableFormatKey format = formatter.SwarmStackTableFormat
} }
stackCtx := formatter.Context{ stackCtx := formatter.Context{
Output: dockerCli.Out(), Output: dockerCli.Out(),
Format: formatter.NewStackFormat(format), Format: formatter.Format(format),
} }
sort.Sort(byName(stacks)) sort.Sort(byName(stacks))
return formatter.StackWrite(stackCtx, stacks) return formatter.StackWrite(stackCtx, stacks)

View File

@ -55,6 +55,7 @@ Valid placeholders for the Go template are listed below:
| `.Name` | Stack name | | `.Name` | Stack name |
| `.Services` | Number of services | | `.Services` | Number of services |
| `.Orchestrator` | Orchestrator name | | `.Orchestrator` | Orchestrator name |
| `.Namespace` | Namespace |
When using the `--format` option, the `stack ls` command either outputs When using the `--format` option, the `stack ls` command either outputs
the data exactly as the template declares or, when using the the data exactly as the template declares or, when using the