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

🗑️ Migrate to wavesoftware/commandline package #205

Merged
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
26 changes: 3 additions & 23 deletions cmd/kn-event-sender/main.go
Original file line number Diff line number Diff line change
@@ -1,35 +1,15 @@
package main

import (
"context"
"os"

"go.uber.org/zap"
"knative.dev/kn-plugin-event/pkg/cli/retcode"
"knative.dev/kn-plugin-event/pkg/configuration"
"knative.dev/pkg/logging"
"github.com/wavesoftware/go-commandline"
"knative.dev/kn-plugin-event/internal/ics"
)

// ExitFunc will be used to exit Go process in case of error.
var ExitFunc = os.Exit // nolint:gochecknoglobals

func main() {
logger := createLogger()
app := configuration.CreateIcs()
if err := app.SendFromEnv(); err != nil {
logger.Error(err)
ExitFunc(retcode.Calc(err))
}
commandline.New(ics.App{}).ExecuteOrDie(ics.Options...)
}

// TestMain is used by tests.
//goland:noinspection GoUnusedExportedFunction
func TestMain() { //nolint:deadcode
main()
}

func createLogger() *zap.SugaredLogger {
return logging.
FromContext(context.TODO()).
With("env", os.Environ())
}
18 changes: 17 additions & 1 deletion cmd/kn-event-sender/main_test.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,33 @@
package main_test

import (
"bytes"
"net/url"
"strings"
"testing"
"time"

cloudevents "github.com/cloudevents/sdk-go/v2"
"github.com/google/uuid"
"github.com/wavesoftware/go-commandline"
"gotest.tools/v3/assert"
kes "knative.dev/kn-plugin-event/cmd/kn-event-sender"
internalics "knative.dev/kn-plugin-event/internal/ics"
"knative.dev/kn-plugin-event/pkg/cli/ics"
"knative.dev/kn-plugin-event/pkg/tests"
)

func TestMainSender(t *testing.T) {
defer func() {
internalics.Options = nil
}()
var outBuf bytes.Buffer
internalics.Options = []commandline.Option{
commandline.WithOutput(&outBuf),
}
id := uuid.New().String()
want := cloudevents.NewEvent()
want.SetID("azxswq")
want.SetID(id)
want.SetTime(time.Now().UTC())
want.SetType("example")
want.SetSource("tests://example")
Expand All @@ -31,7 +44,10 @@ func TestMainSender(t *testing.T) {
return nil
})
})
out := outBuf.String()
assert.NilError(t, err)

assert.DeepEqual(t, want, *got)
assert.Check(t, strings.Contains(out, "Event sent"))
assert.Check(t, strings.Contains(out, id))
}
10 changes: 5 additions & 5 deletions cmd/kn-event/main.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package main

import "knative.dev/kn-plugin-event/internal/cli/cmd"

// Suppress global check for testing purposes.
var mainCmd = &cmd.Cmd{} //nolint:gochecknoglobals
import (
"github.com/wavesoftware/go-commandline"
"knative.dev/kn-plugin-event/internal/cli/cmd"
)

func main() {
mainCmd.Execute()
commandline.New(new(cmd.App)).ExecuteOrDie(cmd.Options...)
}
22 changes: 14 additions & 8 deletions cmd/kn-event/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,32 @@ package main // nolint:testpackage

import (
"bytes"
"math"
"strings"
"testing"

"github.com/wavesoftware/go-commandline"
"gotest.tools/v3/assert"
"knative.dev/kn-plugin-event/internal/cli/cmd"
)

func TestMainFunc(t *testing.T) {
tc := cmd.TestingCmd{
Cmd: mainCmd,
retcode := math.MinInt64
defer func() {
cmd.Options = nil
}()
var buf bytes.Buffer
cmd.Options = []commandline.Option{
commandline.WithExit(func(code int) {
retcode = code
}),
commandline.WithOutput(&buf),
commandline.WithArgs(""),
}
buf := bytes.NewBuffer([]byte{})
tc.Out(buf)
tc.Args("")
tc.Exit(func(code int) {
assert.Equal(t, 0, code)
})

main()

out := buf.String()
assert.Check(t, strings.Contains(out, "Manage CloudEvents from command line"))
assert.Check(t, retcode == math.MinInt64)
}
6 changes: 4 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@ require (
github.com/magefile/mage v1.11.0
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2
github.com/pkg/errors v0.9.1
github.com/spf13/cobra v1.3.0
github.com/spf13/cobra v1.5.0
github.com/thediveo/enumflag v0.10.0
github.com/wavesoftware/go-commandline v1.0.0
github.com/wavesoftware/go-ensure v1.0.0
github.com/wavesoftware/go-magetasks v0.6.0
go.uber.org/zap v1.21.0
gopkg.in/yaml.v2 v2.4.0
gotest.tools/v3 v3.1.0
gotest.tools/v3 v3.3.0
k8s.io/api v0.23.9
k8s.io/apimachinery v0.23.9
k8s.io/client-go v0.23.9
Expand Down Expand Up @@ -138,6 +139,7 @@ require (
github.com/stretchr/testify v1.7.0 // indirect
github.com/subosito/gotenv v1.2.0 // indirect
github.com/vbatts/tar-split v0.11.2 // indirect
github.com/wavesoftware/go-retcode v1.0.0 // indirect
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca // indirect
go.opencensus.io v0.23.0 // indirect
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect
Expand Down
58 changes: 9 additions & 49 deletions go.sum

Large diffs are not rendered by default.

8 changes: 3 additions & 5 deletions internal/cli/cmd/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
var ErrCantBePresented = errors.New("can't be presented")

type buildCommand struct {
*Cmd
*App
event *cli.EventArgs
}

Expand All @@ -28,14 +28,12 @@ func (b *buildCommand) command() *cobra.Command {
}

func (b *buildCommand) run(cmd *cobra.Command, _ []string) error {
b.options.OutWriter = cmd.OutOrStdout()
b.options.ErrWriter = cmd.ErrOrStderr()
c := configuration.CreateCli()
c := configuration.CreateCli(cmd)
ce, err := c.CreateWithArgs(b.event)
if err != nil {
return cantBuildEventError(err)
}
out, err := c.PresentWith(ce, b.options.Output)
out, err := c.PresentWith(ce, b.Output)
if err != nil {
return fmt.Errorf("event %w: %v", ErrCantBePresented, err)
}
Expand Down
10 changes: 5 additions & 5 deletions internal/cli/cmd/build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import (
"testing"

cloudevents "github.com/cloudevents/sdk-go/v2"
"github.com/wavesoftware/go-commandline"
"gotest.tools/v3/assert"
"knative.dev/kn-plugin-event/internal/cli/cmd"
"knative.dev/kn-plugin-event/pkg/event"
"knative.dev/kn-plugin-event/pkg/tests"
)
Expand Down Expand Up @@ -61,10 +61,10 @@ func newCmdArgs(args ...string) cmdArgs {
func performTestsOnBuildSubCommand(t *testing.T, args cmdArgs, preparers ...eventPreparer) {
t.Helper()
buf := bytes.NewBuffer([]byte{})
c := cmd.TestingCmd{}
c.Out(buf)
c.Args(args.args...)
assert.NilError(t, c.Execute())
assert.NilError(t, testapp().Execute(
commandline.WithOutput(buf),
commandline.WithArgs(args.args...),
))
output := buf.Bytes()
ec := newEventChecks(t)
for _, preparer := range preparers {
Expand Down
97 changes: 24 additions & 73 deletions internal/cli/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,117 +2,68 @@ package cmd

import (
"fmt"
"io"
"os"

"github.com/spf13/cobra"
"github.com/thediveo/enumflag"
"github.com/wavesoftware/go-commandline"
_ "k8s.io/client-go/plugin/pkg/client/auth" // for kubeconfig auth plugins to work correctly see issue #24 .
"knative.dev/kn-plugin-event/pkg/cli"
"knative.dev/kn-plugin-event/pkg/cli/retcode"
"knative.dev/kn-plugin-event/pkg/metadata"
)

// Cmd represents a command line application entrypoint.
type Cmd struct {
options *cli.Options
root *cobra.Command
exit func(code int)
}
// Options to override the commandline for testing purposes.
var Options []commandline.Option //nolint:gochecknoglobals

// Execute will execute the application.
func (c *Cmd) Execute() {
if err := c.execute(); err != nil {
c.exit(retcode.Calc(err))
}
type App struct {
cli.Options
}

// ExecuteWithOptions will execute the application with the provided options.
func (c *Cmd) ExecuteWithOptions(options ...CommandOption) error {
return c.execute(options...)
}

// WithArgs creates an option which sets args.
func WithArgs(args ...string) CommandOption {
return func(command *cobra.Command) {
command.SetArgs(args)
}
}

// WithOutput creates an option witch sets os.Stdout and os.Stderr.
func WithOutput(out io.Writer) CommandOption {
return func(command *cobra.Command) {
command.SetOut(out)
command.SetErr(out)
}
}

// CommandOption is used to configure a command in Cmd.ExecuteWithOptions.
type CommandOption func(*cobra.Command)

func (c *Cmd) execute(configs ...CommandOption) error {
c.init()
for _, config := range configs {
config(c.root)
}
// cobra.Command should pass our own errors, no need to wrap them.
return c.root.Execute() //nolint:wrapcheck
}

func (c *Cmd) init() {
if c.root != nil {
return
}
c.exit = os.Exit
c.options = &cli.Options{}
c.root = &cobra.Command{
func (a *App) Command() *cobra.Command {
c := &cobra.Command{
Use: metadata.PluginUse,
Aliases: []string{fmt.Sprintf("kn %s", metadata.PluginUse)},
Short: metadata.PluginDescription,
Long: metadata.PluginLongDescription,
}
c.root.SetOut(os.Stdout)
c.root.SetErr(os.Stderr)
c.root.PersistentFlags().BoolVarP(
&c.options.Verbose, "verbose", "v",
c.PersistentFlags().BoolVarP(
&a.Verbose, "verbose", "v",
false, "verbose output",
)
c.root.PersistentFlags().VarP(
enumflag.New(&c.options.Output, "output", outputModeIds(), enumflag.EnumCaseInsensitive),
c.PersistentFlags().VarP(
enumflag.New(&a.Output, "output", outputModeIds(), enumflag.EnumCaseInsensitive),
"output", "o",
"Output format. One of: human|json|yaml.",
)

eventArgs := &cli.EventArgs{}
targetArgs := &cli.TargetArgs{}
commands := []subcommand{
&buildCommand{Cmd: c, event: eventArgs},
&sendCommand{Cmd: c, event: eventArgs, target: targetArgs},
&versionCommand{Cmd: c},
&buildCommand{App: a, event: eventArgs},
&sendCommand{App: a, event: eventArgs, target: targetArgs},
&versionCommand{App: a},
}
for _, each := range commands {
c.root.AddCommand(each.command())
c.AddCommand(each.command())
}

c.root.PersistentFlags().StringVar(
&c.options.KubeconfigOptions.Path, "kubeconfig", "",
c.PersistentFlags().StringVar(
&a.KubeconfigOptions.Path, "kubeconfig", "",
"kubectl configuration file (default: ~/.kube/config)",
)
c.root.PersistentFlags().StringVar(
&c.options.KubeconfigOptions.Context, "context", "",
c.PersistentFlags().StringVar(
&a.KubeconfigOptions.Context, "context", "",
"name of the kubeconfig context to use",
)
c.root.PersistentFlags().StringVar(
&c.options.KubeconfigOptions.Cluster, "cluster", "",
c.PersistentFlags().StringVar(
&a.KubeconfigOptions.Cluster, "cluster", "",
"name of the kubeconfig cluster to use",
)

c.root.PersistentPreRun = func(cmd *cobra.Command, args []string) {
c.options.OutWriter = cmd.OutOrStdout()
c.options.ErrWriter = cmd.ErrOrStderr()
}
return c
}

var _ commandline.CobraProvider = new(App)

func outputModeIds() map[cli.OutputMode][]string {
return map[cli.OutputMode][]string{
cli.HumanReadable: {"human"},
Expand Down
26 changes: 16 additions & 10 deletions internal/cli/cmd/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,29 @@ package cmd_test

import (
"bytes"
"math"
"testing"

"github.com/wavesoftware/go-commandline"
"gotest.tools/v3/assert"
"knative.dev/kn-plugin-event/internal/cli/cmd"
)

func TestRootInvalidCommand(t *testing.T) {
called := false
c := cmd.TestingCmd{}
c.Exit(func(code int) {
t.Logf("exit code received: %d", code)
called = true
})
c.Args("invalid-command")
retcode := math.MinInt64
buf := bytes.NewBuffer([]byte{})
c.Out(buf)
c.ExecuteOrFail()
testapp().ExecuteOrDie(
commandline.WithOutput(buf),
commandline.WithExit(func(code int) {
retcode = code
}),
commandline.WithArgs("invalid-command"),
)

assert.Check(t, called)
assert.Check(t, retcode != math.MinInt64)
assert.Check(t, retcode != 0)
}

func testapp() *commandline.App {
return commandline.New(new(cmd.App))
}
Loading