Skip to content

Commit

Permalink
Merge pull request #480 from vmware-tanzu/cli
Browse files Browse the repository at this point in the history
Enhancements/additions to kctrl CLI
  • Loading branch information
cppforlife authored Feb 15, 2022
2 parents 995b29a + 08d1a64 commit 5d3f81e
Show file tree
Hide file tree
Showing 17 changed files with 380 additions and 165 deletions.
43 changes: 43 additions & 0 deletions cli/pkg/kctrl/cmd/core/examples.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright 2022 VMware, Inc.
// SPDX-License-Identifier: Apache-2.0

package core

import (
"fmt"
"strings"
)

type PackageCommandTreeOpts struct {
BinaryName string
PositionalArgs bool

Color bool
JSON bool
}

type Example struct {
Description string
Args []string
}

func (e Example) asString(nameFlag string, opts PackageCommandTreeOpts) string {
command := opts.BinaryName
for _, arg := range e.Args {
if opts.PositionalArgs && arg == nameFlag {
continue
}
command += " " + arg
}
return fmt.Sprintf("# %s \n%s", e.Description, command)
}

type Examples []Example

func (es Examples) Description(nameFlag string, opts PackageCommandTreeOpts) string {
var description string
for _, example := range es {
description += example.asString(nameFlag, opts) + "\n\n"
}
return strings.TrimSuffix(description, "\n\n")
}
46 changes: 46 additions & 0 deletions cli/pkg/kctrl/cmd/core/file_sources.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright 2020 VMware, Inc.
// SPDX-License-Identifier: Apache-2.0

package core

import (
"io/ioutil"
"os"
)

type InputFile struct {
source FileSource
}

func NewInputFile(file string) InputFile {
switch file {
case "-":
return InputFile{source: NewStdinSource()}
default:
return InputFile{source: NewLocalFileSource(file)}
}
}

func (f InputFile) Bytes() ([]byte, error) {
return f.source.Bytes()
}

type FileSource interface {
Bytes() ([]byte, error)
}

type StdinSource struct{}

var _ FileSource = StdinSource{}

func NewStdinSource() StdinSource { return StdinSource{} }
func (s StdinSource) Bytes() ([]byte, error) { return ioutil.ReadAll(os.Stdin) }

type LocalFileSource struct {
path string
}

var _ FileSource = LocalFileSource{}

func NewLocalFileSource(path string) LocalFileSource { return LocalFileSource{path} }
func (s LocalFileSource) Bytes() ([]byte, error) { return ioutil.ReadFile(s.path) }
2 changes: 1 addition & 1 deletion cli/pkg/kctrl/cmd/core/semver_value.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 20210 VMware, Inc.
// Copyright 2021 VMware, Inc.
// SPDX-License-Identifier: Apache-2.0

package core
Expand Down
54 changes: 28 additions & 26 deletions cli/pkg/kctrl/cmd/kctrl.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,24 +70,26 @@ func NewKctrlCmd(o *KctrlOptions, flagsFactory cmdcore.FlagsFactory) *cobra.Comm
cmdcore.RestOfCommandsHelpGroup,
}))

SetGlobalFlags(o, cmd, flagsFactory)
pkgOpts := cmdcore.PackageCommandTreeOpts{BinaryName: "kctrl", PositionalArgs: false, Color: true, JSON: true}

SetGlobalFlags(o, cmd, flagsFactory, pkgOpts)

ConfigurePathResolvers(o, cmd, flagsFactory)

cmd.AddCommand(NewVersionCmd(NewVersionOptions(o.ui), flagsFactory))
cmd.AddCommand(NewVersionCmd(NewVersionOptions(o.ui, o.depsFactory), flagsFactory))

pkgCmd := cmdpkg.NewCmd()
AddPackageCommands(o, pkgCmd, flagsFactory, false)
AddPackageCommands(o, pkgCmd, flagsFactory, pkgOpts)

cmd.AddCommand(pkgCmd)

ConfigureGlobalFlags(o, cmd, flagsFactory, false)
ConfigureGlobalFlags(o, cmd, flagsFactory, pkgOpts.PositionalArgs)

return cmd
}

func SetGlobalFlags(o *KctrlOptions, cmd *cobra.Command, flagsFactory cmdcore.FlagsFactory) {
o.UIFlags.Set(cmd, flagsFactory)
func SetGlobalFlags(o *KctrlOptions, cmd *cobra.Command, flagsFactory cmdcore.FlagsFactory, opts cmdcore.PackageCommandTreeOpts) {
o.UIFlags.Set(cmd, flagsFactory, opts)
o.LoggerFlags.Set(cmd, flagsFactory)
o.KubeAPIFlags.Set(cmd, flagsFactory)
o.KubeconfigFlags.Set(cmd, flagsFactory)
Expand Down Expand Up @@ -128,45 +130,45 @@ func ConfigureGlobalFlags(o *KctrlOptions, cmd *cobra.Command, flagsFactory cmdc
}
}

func AddPackageCommands(o *KctrlOptions, cmd *cobra.Command, flagsFactory cmdcore.FlagsFactory, positionalNameArg bool) {
func AddPackageCommands(o *KctrlOptions, cmd *cobra.Command, flagsFactory cmdcore.FlagsFactory, opts cmdcore.PackageCommandTreeOpts) {
pkgrepoCmd := pkgrepo.NewCmd()
pkgrepoCmd.AddCommand(pkgrepo.NewListCmd(pkgrepo.NewListOptions(o.ui, o.depsFactory, o.logger), flagsFactory))
pkgrepoCmd.AddCommand(pkgrepo.NewGetCmd(pkgrepo.NewGetOptions(o.ui, o.depsFactory, o.logger, positionalNameArg), flagsFactory))
pkgrepoCmd.AddCommand(pkgrepo.NewDeleteCmd(pkgrepo.NewDeleteOptions(o.ui, o.depsFactory, o.logger, positionalNameArg), flagsFactory))
pkgrepoCmd.AddCommand(pkgrepo.NewAddCmd(pkgrepo.NewAddOrUpdateOptions(o.ui, o.depsFactory, o.logger, positionalNameArg), flagsFactory))
pkgrepoCmd.AddCommand(pkgrepo.NewUpdateCmd(pkgrepo.NewAddOrUpdateOptions(o.ui, o.depsFactory, o.logger, positionalNameArg), flagsFactory))
pkgrepoCmd.AddCommand(pkgrepo.NewListCmd(pkgrepo.NewListOptions(o.ui, o.depsFactory, o.logger, opts), flagsFactory))
pkgrepoCmd.AddCommand(pkgrepo.NewGetCmd(pkgrepo.NewGetOptions(o.ui, o.depsFactory, o.logger, opts), flagsFactory))
pkgrepoCmd.AddCommand(pkgrepo.NewDeleteCmd(pkgrepo.NewDeleteOptions(o.ui, o.depsFactory, o.logger, opts), flagsFactory))
pkgrepoCmd.AddCommand(pkgrepo.NewAddCmd(pkgrepo.NewAddOrUpdateOptions(o.ui, o.depsFactory, o.logger, opts), flagsFactory))
pkgrepoCmd.AddCommand(pkgrepo.NewUpdateCmd(pkgrepo.NewAddOrUpdateOptions(o.ui, o.depsFactory, o.logger, opts), flagsFactory))

pkgiCmd := pkginst.NewCmd()
pkgiCmd.AddCommand(pkginst.NewListCmd(pkginst.NewListOptions(o.ui, o.depsFactory, o.logger), flagsFactory))
pkgiCmd.AddCommand(pkginst.NewGetCmd(pkginst.NewGetOptions(o.ui, o.depsFactory, o.logger, positionalNameArg), flagsFactory))
pkgiCmd.AddCommand(pkginst.NewCreateCmd(pkginst.NewCreateOrUpdateOptions(o.ui, o.depsFactory, o.logger, positionalNameArg), flagsFactory))
pkgiCmd.AddCommand(pkginst.NewUpdateCmd(pkginst.NewCreateOrUpdateOptions(o.ui, o.depsFactory, o.logger, positionalNameArg), flagsFactory))
pkgiCmd.AddCommand(pkginst.NewDeleteCmd(pkginst.NewDeleteOptions(o.ui, o.depsFactory, o.logger, positionalNameArg), flagsFactory))
pkgiCmd.AddCommand(pkginst.NewListCmd(pkginst.NewListOptions(o.ui, o.depsFactory, o.logger, opts), flagsFactory))
pkgiCmd.AddCommand(pkginst.NewGetCmd(pkginst.NewGetOptions(o.ui, o.depsFactory, o.logger, opts), flagsFactory))
pkgiCmd.AddCommand(pkginst.NewCreateCmd(pkginst.NewCreateOrUpdateOptions(o.ui, o.depsFactory, o.logger, opts), flagsFactory))
pkgiCmd.AddCommand(pkginst.NewUpdateCmd(pkginst.NewCreateOrUpdateOptions(o.ui, o.depsFactory, o.logger, opts), flagsFactory))
pkgiCmd.AddCommand(pkginst.NewDeleteCmd(pkginst.NewDeleteOptions(o.ui, o.depsFactory, o.logger, opts), flagsFactory))

pkgaCmd := pkgavail.NewCmd()
pkgaCmd.AddCommand(pkgavail.NewListCmd(pkgavail.NewListOptions(o.ui, o.depsFactory, o.logger, positionalNameArg), flagsFactory))
pkgaCmd.AddCommand(pkgavail.NewGetCmd(pkgavail.NewGetOptions(o.ui, o.depsFactory, o.logger, positionalNameArg), flagsFactory))
pkgaCmd.AddCommand(pkgavail.NewListCmd(pkgavail.NewListOptions(o.ui, o.depsFactory, o.logger, opts), flagsFactory))
pkgaCmd.AddCommand(pkgavail.NewGetCmd(pkgavail.NewGetOptions(o.ui, o.depsFactory, o.logger, opts), flagsFactory))

cmd.AddCommand(pkgrepoCmd)
cmd.AddCommand(pkgiCmd)
cmd.AddCommand(pkgaCmd)
cmd.AddCommand(pkginst.NewInstallCmd(pkginst.NewCreateOrUpdateOptions(o.ui, o.depsFactory, o.logger, positionalNameArg), flagsFactory))
cmd.AddCommand(pkginst.NewInstallCmd(pkginst.NewCreateOrUpdateOptions(o.ui, o.depsFactory, o.logger, opts), flagsFactory))
}

func AttachGlobalFlags(o *KctrlOptions, cmd *cobra.Command, flagsFactory cmdcore.FlagsFactory, positionalNameArg bool) {
SetGlobalFlags(o, cmd, flagsFactory)
func AttachGlobalFlags(o *KctrlOptions, cmd *cobra.Command, flagsFactory cmdcore.FlagsFactory, opts cmdcore.PackageCommandTreeOpts) {
SetGlobalFlags(o, cmd, flagsFactory, opts)
ConfigurePathResolvers(o, cmd, flagsFactory)
ConfigureGlobalFlags(o, cmd, flagsFactory, positionalNameArg)
ConfigureGlobalFlags(o, cmd, flagsFactory, opts.PositionalArgs)
}

func AttachKctrlPackageCommandTree(cmd *cobra.Command, confUI *ui.ConfUI) {
func AttachKctrlPackageCommandTree(cmd *cobra.Command, confUI *ui.ConfUI, opts cmdcore.PackageCommandTreeOpts) {
configFactory := cmdcore.NewConfigFactoryImpl()
depsFactory := cmdcore.NewDepsFactoryImpl(configFactory, confUI)
options := NewKctrlOptions(confUI, configFactory, depsFactory)
flagsFactory := cmdcore.NewFlagsFactory(configFactory, depsFactory)

AddPackageCommands(options, cmd, flagsFactory, true)
AttachGlobalFlags(options, cmd, flagsFactory, true)
AddPackageCommands(options, cmd, flagsFactory, opts)
AttachGlobalFlags(options, cmd, flagsFactory, opts)
}

type uiBlockWriter struct {
Expand Down
28 changes: 17 additions & 11 deletions cli/pkg/kctrl/cmd/package/available/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,31 +30,37 @@ type GetOptions struct {

ValuesSchema bool

positionalNameArg bool
pkgCmdTreeOpts cmdcore.PackageCommandTreeOpts
}

func NewGetOptions(ui ui.UI, depsFactory cmdcore.DepsFactory, logger logger.Logger, positionalNameArg bool) *GetOptions {
return &GetOptions{ui: ui, depsFactory: depsFactory, logger: logger, positionalNameArg: positionalNameArg}
func NewGetOptions(ui ui.UI, depsFactory cmdcore.DepsFactory, logger logger.Logger, pkgCmdTreeOpts cmdcore.PackageCommandTreeOpts) *GetOptions {
return &GetOptions{ui: ui, depsFactory: depsFactory, logger: logger, pkgCmdTreeOpts: pkgCmdTreeOpts}
}

func NewGetCmd(o *GetOptions, flagsFactory cmdcore.FlagsFactory) *cobra.Command {
cmd := &cobra.Command{
Use: "get",
Aliases: []string{"g"},
Short: "Get details for an available package or the openAPI schema of a package with a specific version",
Args: cobra.ExactArgs(1),
RunE: func(_ *cobra.Command, args []string) error { return o.Run(args) },
Example: `
# Get details about an available package
kctrl package available get --package cert-manager.community.tanzu.vmware.com
# Get the values schema for a particular version of the package
kctrl package available get --package cert-manager.community.tanzu.vmware.com --values-schema`,
Example: cmdcore.Examples{
cmdcore.Example{"Get details about an available package",
[]string{"package", "available", "get", "-p", "cert-manager.community.tanzu.vmware.com"},
},
cmdcore.Example{"Get the values schema for a particular version of the package",
[]string{"package", "available", "get", "-p", "cert-manager.community.tanzu.vmware.com", "--values-schema"}},
}.Description("-p", o.pkgCmdTreeOpts),
SilenceUsage: true,
Annotations: map[string]string{"table": ""},
}

o.NamespaceFlags.Set(cmd, flagsFactory)

if !o.positionalNameArg {
if !o.pkgCmdTreeOpts.PositionalArgs {
cmd.Flags().StringVarP(&o.Name, "package", "p", "", "Set package name (required)")
} else {
cmd.Use = "get PACKAGE_NAME or PACKAGE_NAME/VERSION"
}

cmd.Flags().BoolVar(&o.ValuesSchema, "values-schema", false, "Values schema of the package (optional)")
Expand All @@ -64,7 +70,7 @@ kctrl package available get --package cert-manager.community.tanzu.vmware.com --
func (o *GetOptions) Run(args []string) error {
var pkgName, pkgVersion string

if o.positionalNameArg {
if o.pkgCmdTreeOpts.PositionalArgs {
o.Name = args[0]
}

Expand Down
47 changes: 27 additions & 20 deletions cli/pkg/kctrl/cmd/package/available/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,41 +29,48 @@ type ListOptions struct {
Summary bool
Wide bool

positionalNameArg bool
pkgCmdTreeOpts cmdcore.PackageCommandTreeOpts
}

func NewListOptions(ui ui.UI, depsFactory cmdcore.DepsFactory, logger logger.Logger, positionalNameArg bool) *ListOptions {
return &ListOptions{ui: ui, depsFactory: depsFactory, logger: logger, positionalNameArg: positionalNameArg}
func NewListOptions(ui ui.UI, depsFactory cmdcore.DepsFactory, logger logger.Logger, pkgCmdTreeOpts cmdcore.PackageCommandTreeOpts) *ListOptions {
return &ListOptions{ui: ui, depsFactory: depsFactory, logger: logger, pkgCmdTreeOpts: pkgCmdTreeOpts}
}

func NewListCmd(o *ListOptions, flagsFactory cmdcore.FlagsFactory) *cobra.Command {
cmd := &cobra.Command{
Use: "list",
Aliases: []string{"l", "ls"},
Short: "List available packages in a namespace",
Args: cobra.MaximumNArgs(1),
RunE: func(_ *cobra.Command, args []string) error { return o.Run(args) },
Example: `
# List packages available on the cluster
kctrl package available list
# List packages available on the cluster with their short descriptions
kctrl package available list --wide
# List all available package versions with release dates
kctrl package available list --summary=false
# List packages available in all namespaces
kctrl package available list -A
# List all available versions of a package
kctrl package available --package cert-manager.community.tanzu.vmware.com`,
Example: cmdcore.Examples{
cmdcore.Example{"List packages available on the cluster",
[]string{"package", "available", "list"},
},
cmdcore.Example{"List packages available on the cluster with their short descriptions",
[]string{"package", "available", "list", "--wide"},
},
cmdcore.Example{"List all available package versions with release dates",
[]string{"package", "available", "list", "--summary=false"},
},
cmdcore.Example{"List packages available in all namespaces",
[]string{"package", "available", "list", "-A"},
},
cmdcore.Example{"List all available versions of a package",
[]string{"package", "available", "list", "-p", "cert-manager.community.tanzu.vmware.com"}},
}.Description("-p", o.pkgCmdTreeOpts),
SilenceUsage: true,
Annotations: map[string]string{"table": ""},
}
o.NamespaceFlags.Set(cmd, flagsFactory)
cmd.Flags().BoolVarP(&o.AllNamespaces, "all-namespaces", "A", false, "List available packages in all namespaces")

cmd.Flags().BoolVar(&o.Summary, "summary", true, "Show summarized list of packages")
if !o.positionalNameArg {

if !o.pkgCmdTreeOpts.PositionalArgs {
cmd.Flags().StringVarP(&o.Name, "package", "p", "", "List all available versions of package")
} else {
cmd.Use = "list or list PACKAGE_NAME"
}

cmd.Flags().BoolVar(&o.Wide, "wide", false, "Show additional info")
Expand All @@ -72,7 +79,7 @@ kctrl package available --package cert-manager.community.tanzu.vmware.com`,
}

func (o *ListOptions) Run(args []string) error {
if o.positionalNameArg && len(args) > 0 {
if o.pkgCmdTreeOpts.PositionalArgs && len(args) > 0 {
o.Name = args[0]
}

Expand Down
Loading

0 comments on commit 5d3f81e

Please sign in to comment.