Skip to content
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

adding params list #1029

Merged
merged 7 commits into from
Nov 6, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ require (
github.com/dustinkirkland/golang-petname v0.0.0-20170921220637-d3c2ba80e75e
github.com/go-test/deep v1.0.1
github.com/gogo/protobuf v1.3.1 // indirect
github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3
github.com/golangci/golangci-lint v1.21.0
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf
github.com/gophercloud/gophercloud v0.2.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,8 @@ github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zV
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 h1:zN2lZNZRflqFyxVaTIU61KNKQ9C0055u9CAfpmqUvo4=
github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3/go.mod h1:nPpo7qLxd6XL3hWJG/O60sR8ZKfMCiIoNap5GvD12KU=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
Expand Down
72 changes: 18 additions & 54 deletions pkg/kudoctl/cmd/package.go
Original file line number Diff line number Diff line change
@@ -1,72 +1,36 @@
package cmd

import (
"fmt"
"io"

"github.com/kudobuilder/kudo/pkg/kudoctl/packages"
"github.com/spf13/afero"
"github.com/spf13/cobra"
)

const (
pkgDesc = `Package a KUDO operator from local filesystem into a package tarball.
The package argument must be a directory which contains the operator definition files. The package command will create a tgz file containing the operator.
`
pkgExample = ` # package zookeeper (where zookeeper is a folder in the current directory)
kubectl kudo package zookeeper
const packageDesc = `
This command consists of multiple sub-commands to interact with KUDO operators.

# Specify a destination folder other than current working directory
kubectl kudo package ../operators/repository/zookeeper/operator/ --destination=out-folder`
)
It can be used to package or verify an operator, or list parameters. When working with parameters it can
provide a list of parameters from a remote operator given a url or repository along with the name and version.
`

type packageCmd struct {
path string
destination string
overwrite bool
out io.Writer
fs afero.Fs
}
const packageExamples = ` kubectl kudo package create [operator folder]
kubectl kudo package params list [operator]
kubectl kudo package verify [operator]
`

// newPackageCmd creates an operator tarball. fs is the file system, out is stdout for CLI
// newPackageCmd for operator commands such as packaging an operator or retrieving it's parameters
func newPackageCmd(fs afero.Fs, out io.Writer) *cobra.Command {

pkg := &packageCmd{out: out, fs: fs}
cmd := &cobra.Command{
Use: "package <operator_dir>",
Short: "Package a local KUDO operator into a tarball.",
Long: pkgDesc,
Example: pkgExample,
RunE: func(cmd *cobra.Command, args []string) error {
if err := validate(args); err != nil {
return err
}
pkg.path = args[0]
if err := pkg.run(); err != nil {
return err
}
return nil
},
Use: "package [FLAGS] package|params|verify [ARGS]",
Short: "package an operator, or understand it's content",
Long: packageDesc,
Example: packageExamples,
}

f := cmd.Flags()
f.StringVarP(&pkg.destination, "destination", "d", ".", "Location to write the package.")
f.BoolVarP(&pkg.overwrite, "overwrite", "w", false, "Overwrite existing package.")
return cmd
}

func validate(args []string) error {
if len(args) != 1 {
return fmt.Errorf("expecting exactly one argument - directory of the operator to package")
}
return nil
}
cmd.AddCommand(newPackageCreateCmd(fs, out))
cmd.AddCommand(newPackageParamsCmd(fs, out))
cmd.AddCommand(newPackageVerifyCmd(fs, out))

// run returns the errors associated with cmd env
func (pkg *packageCmd) run() error {
tarfile, err := packages.CreateTarball(pkg.fs, pkg.path, pkg.destination, pkg.overwrite)
if err == nil {
fmt.Fprintf(pkg.out, "Package created: %v\n", tarfile)
}
return err
return cmd
}
72 changes: 72 additions & 0 deletions pkg/kudoctl/cmd/package_create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package cmd

import (
"fmt"
"io"

"github.com/kudobuilder/kudo/pkg/kudoctl/packages"
"github.com/spf13/afero"
"github.com/spf13/cobra"
)

const (
pkgCreateDesc = `Package a KUDO operator from local filesystem into a package tarball.
The package argument must be a directory which contains the operator definition files. The package command will create a tgz file containing the operator.
`
pkgCreateExample = ` # package zookeeper (where zookeeper is a folder in the current directory)
kubectl kudo package create zookeeper

# Specify a destination folder other than current working directory
kubectl kudo package create ../operators/repository/zookeeper/operator/ --destination=out-folder`
)

type packageCreateCmd struct {
path string
destination string
overwrite bool
out io.Writer
fs afero.Fs
}

// newPackageCreateCmd creates an operator tarball. fs is the file system, out is stdout for CLI
func newPackageCreateCmd(fs afero.Fs, out io.Writer) *cobra.Command {

pkg := &packageCreateCmd{out: out, fs: fs}
cmd := &cobra.Command{
Use: "create <operator_dir>",
Short: "package a local KUDO operator into a tarball.",
Long: pkgCreateDesc,
Example: pkgCreateExample,
RunE: func(cmd *cobra.Command, args []string) error {
if err := validateOperatorArg(args); err != nil {
return err
}
pkg.path = args[0]
if err := pkg.run(); err != nil {
return err
}
return nil
},
}

f := cmd.Flags()
f.StringVarP(&pkg.destination, "destination", "d", ".", "Location to write the package.")
f.BoolVarP(&pkg.overwrite, "overwrite", "w", false, "Overwrite existing package.")
return cmd
}

func validateOperatorArg(args []string) error {
if len(args) != 1 {
return fmt.Errorf("expecting exactly one argument - directory of the operator or name of package")
}
return nil
}

// run returns the errors associated with cmd env
func (pkg *packageCreateCmd) run() error {
tarfile, err := packages.CreateTarball(pkg.fs, pkg.path, pkg.destination, pkg.overwrite)
if err == nil {
fmt.Fprintf(pkg.out, "Package created: %v\n", tarfile)
}
return err
}
30 changes: 30 additions & 0 deletions pkg/kudoctl/cmd/package_params.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package cmd

import (
"io"

"github.com/spf13/afero"
"github.com/spf13/cobra"
)

const paramsDesc = `
This command consists of multiple sub-commands to interact with KUDO parameters when working on creating or modifying an operator.

It can be used to list operator properties
`

const paramsExamples = ` kubectl kudo package params list [operator folder]
`

// newPackageParamsCmd for repo commands such as building a repo index
func newPackageParamsCmd(fs afero.Fs, out io.Writer) *cobra.Command {
cmd := &cobra.Command{
Use: "params [FLAGS] list [ARGS]",
Short: "list kudo operator parameters",
Long: paramsDesc,
Example: paramsExamples,
}
cmd.AddCommand(newParamsListCmd(fs, out))

return cmd
}
132 changes: 132 additions & 0 deletions pkg/kudoctl/cmd/package_params_list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package cmd

import (
"fmt"
"io"
"sort"

"github.com/kudobuilder/kudo/pkg/kudoctl/clog"
"github.com/kudobuilder/kudo/pkg/kudoctl/env"
"github.com/kudobuilder/kudo/pkg/kudoctl/packages"
"github.com/kudobuilder/kudo/pkg/kudoctl/util/kudo"
"github.com/kudobuilder/kudo/pkg/kudoctl/util/repo"

"github.com/gosuri/uitable"
"github.com/pkg/errors"
"github.com/spf13/afero"
"github.com/spf13/cobra"
)

type paramsListCmd struct {
fs afero.Fs
out io.Writer
path string
descriptions bool
namesOnly bool
required bool
RepoName string
PackageVersion string
}

func newParamsListCmd(fs afero.Fs, out io.Writer) *cobra.Command {
list := &paramsListCmd{fs: fs, out: out}

cmd := &cobra.Command{
Use: "list [operator]",
Short: "List operator parameters",
Example: " kubectl kudo package params list",
RunE: func(cmd *cobra.Command, args []string) error {
//list.home = Settings.Home
if err := validateOperatorArg(args); err != nil {
return err
}
list.path = args[0]
return list.run(fs, &Settings)
},
}

f := cmd.Flags()
f.BoolVarP(&list.descriptions, "descriptions", "d", false, "Display descriptions.")
f.BoolVarP(&list.required, "required", "r", false, "Restricts list to params which have no defaults but are required.")
f.BoolVar(&list.namesOnly, "names-only", false, "Display only names.")
f.StringVar(&list.RepoName, "repo", "", "Name of repository configuration to use. (default defined by context)")
f.StringVar(&list.PackageVersion, "version", "", "A specific package version on the official GitHub repo. (default to the most recent)")

return cmd
}

// run provides a table listing the parameters. There are 3 defined ways to view the table
// 1. names only using --names-only. This is based on challenges with other approaches reading really long parameter names
// 2. name, default and required. This is the **default**
// 3. name, default, required, desc.
func (c *paramsListCmd) run(fs afero.Fs, settings *env.Settings) error {

repository, err := repo.ClientFromSettings(fs, settings.Home, c.RepoName)
if err != nil {
return errors.WithMessage(err, "could not build operator repository")
}
clog.V(4).Printf("repository used %s", repository)

clog.V(3).Printf("getting package pkg files for %v with version: %v", c.path, c.PackageVersion)
pf, err := kudo.PkgFiles(c.path, c.PackageVersion, repository)
if err != nil {
return errors.Wrapf(err, "failed to resolve package files for operator: %s", c.path)
}

return displayParamsTable(pf, c)
}

func displayParamsTable(pf *packages.PackageFiles, cmd *paramsListCmd) error {
sort.Sort(pf.Params)
table := uitable.New()
tValue := true
// required
if cmd.required {
table.AddRow("Name")
found := false
for _, p := range pf.Params {
if p.Default == nil && p.Required == &tValue {
found = true
table.AddRow(p.Name)
}
}
if found {
fmt.Fprintln(cmd.out, table)
} else {
fmt.Fprintf(cmd.out, "no required parameters without default values found\n")
}
return nil
}
// names only
if cmd.namesOnly {
table.AddRow("Name")
for _, p := range pf.Params {
table.AddRow(p.Name)
}
fmt.Fprintln(cmd.out, table)
return nil
}
table.MaxColWidth = 35
table.Wrap = true
if cmd.descriptions {
//table.MaxColWidth = 50
table.AddRow("Name", "Default", "Required", "Descriptions")

} else {
table.AddRow("Name", "Default", "Required")
}
sort.Sort(pf.Params)
for _, p := range pf.Params {
pDefault := ""
if p.Default != nil {
pDefault = *p.Default
}
if cmd.descriptions {
table.AddRow(p.Name, pDefault, *p.Required, p.Description)
} else {
table.AddRow(p.Name, pDefault, *p.Required)
}
}
fmt.Fprintln(cmd.out, table)
return nil
}
34 changes: 34 additions & 0 deletions pkg/kudoctl/cmd/package_params_list_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package cmd

import (
"bytes"
"io/ioutil"
"path/filepath"
"testing"

"github.com/stretchr/testify/assert"
)

func TestParamsLis(t *testing.T) {
file := "params-list"
out := &bytes.Buffer{}
cmd := newParamsListCmd(fs, out)
if err := cmd.RunE(cmd, []string{"../packages/testdata/zk.tgz"}); err != nil {
t.Fatal(err)
}

gp := filepath.Join("testdata", file+".golden")

if *updateGolden {
t.Log("update golden file")
if err := ioutil.WriteFile(gp, out.Bytes(), 0644); err != nil {
t.Fatalf("failed to update golden file: %s", err)
}
}
g, err := ioutil.ReadFile(gp)
if err != nil {
t.Fatalf("failed reading .golden: %s", err)
}

assert.Equal(t, out.String(), string(g), "yaml does not match .golden file %s", gp)
}
Loading