diff --git a/internal/cmd/hello/hello.go b/internal/cmd/hello/hello.go new file mode 100644 index 00000000..b2de1b3e --- /dev/null +++ b/internal/cmd/hello/hello.go @@ -0,0 +1,40 @@ +package hello + +import ( + "fmt" + + "github.com/debricked/cli/internal/hello" + + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var name string + +const NameFlag = "name" + +func NewHelloCmd(g hello.IGreeter) *cobra.Command { + cmd := &cobra.Command{ + Use: "hello", + Short: "Say hello", + Long: `Says hello to you.`, + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlags(cmd.Flags()) + }, + RunE: RunE(g), + } + cmd.Flags().StringVarP(&name, NameFlag, "n", "anon", `The name to greet`) + viper.MustBindEnv(NameFlag) + + return cmd +} + +func RunE(g hello.IGreeter) func(_ *cobra.Command, args []string) error { + return func(cmd *cobra.Command, _ []string) error { + name := viper.GetString(NameFlag) + greeting := g.Greeting(name) + fmt.Println(greeting) + + return nil + } +} diff --git a/internal/cmd/hello/hello_test.go b/internal/cmd/hello/hello_test.go new file mode 100644 index 00000000..a55d1585 --- /dev/null +++ b/internal/cmd/hello/hello_test.go @@ -0,0 +1,55 @@ +package hello + +import ( + "testing" + + "github.com/debricked/cli/internal/hello" + "github.com/debricked/cli/internal/hello/testdata" + + "github.com/spf13/viper" + "github.com/stretchr/testify/assert" +) + +func TestNewHelloCmd(t *testing.T) { + cmd := NewHelloCmd(hello.NewDebrickedGreeter()) + commands := cmd.Commands() + nbrOfCommands := 0 + assert.Len(t, commands, nbrOfCommands) + + flags := cmd.Flags() + flagAssertions := map[string]string{} + for name, shorthand := range flagAssertions { + flag := flags.Lookup(name) + assert.NotNil(t, flag) + assert.Equal(t, shorthand, flag.Shorthand) + } + + var flagKeys = []string{ + NameFlag, + } + viperKeys := viper.AllKeys() + for _, flagKey := range flagKeys { + match := false + for _, key := range viperKeys { + if key == flagKey { + match = true + } + } + assert.Truef(t, match, "failed to assert that flag was present: "+flagKey) + } +} + +func TestPreRun(t *testing.T) { + mockAuthenticator := testdata.MockGreeter{} + cmd := NewHelloCmd(mockAuthenticator) + cmd.PreRun(cmd, nil) +} + +func TestRunE(t *testing.T) { + a := testdata.MockGreeter{} + runE := RunE(a) + + err := runE(nil, []string{}) + + assert.NoError(t, err) +} diff --git a/internal/cmd/root/root.go b/internal/cmd/root/root.go index a98177f3..c556f7ca 100644 --- a/internal/cmd/root/root.go +++ b/internal/cmd/root/root.go @@ -5,6 +5,7 @@ import ( "github.com/debricked/cli/internal/cmd/callgraph" "github.com/debricked/cli/internal/cmd/files" "github.com/debricked/cli/internal/cmd/fingerprint" + "github.com/debricked/cli/internal/cmd/hello" "github.com/debricked/cli/internal/cmd/report" "github.com/debricked/cli/internal/cmd/resolve" "github.com/debricked/cli/internal/cmd/scan" @@ -49,6 +50,7 @@ Read more: https://docs.debricked.com/product/administration/generate-access-tok rootCmd.AddCommand(resolve.NewResolveCmd(container.Resolver())) rootCmd.AddCommand(callgraph.NewCallgraphCmd(container.CallgraphGenerator())) rootCmd.AddCommand(auth.NewAuthCmd(container.Authenticator())) + rootCmd.AddCommand(hello.NewHelloCmd(container.Greeter())) rootCmd.CompletionOptions.DisableDefaultCmd = true diff --git a/internal/cmd/root/root_test.go b/internal/cmd/root/root_test.go index cb6ce145..0f66f054 100644 --- a/internal/cmd/root/root_test.go +++ b/internal/cmd/root/root_test.go @@ -11,7 +11,7 @@ import ( func TestNewRootCmd(t *testing.T) { cmd := NewRootCmd("v0.0.0", wire.GetCliContainer()) commands := cmd.Commands() - nbrOfCommands := 7 + nbrOfCommands := 8 if len(commands) != nbrOfCommands { t.Errorf( "failed to assert that there were %d sub commands connected (was %d)", @@ -35,7 +35,7 @@ func TestNewRootCmd(t *testing.T) { } } assert.Truef(t, match, "failed to assert that flag was present: "+AccessTokenFlag) - assert.Len(t, viperKeys, 15) + assert.Len(t, viperKeys, 16) } func TestPreRun(t *testing.T) { diff --git a/internal/hello/hello.go b/internal/hello/hello.go new file mode 100644 index 00000000..f8a9a525 --- /dev/null +++ b/internal/hello/hello.go @@ -0,0 +1,24 @@ +package hello + +import ( + "strings" +) + +type IGreeter interface { + Greeting(string) string +} + +type DebrickedGreeter struct{} + +func NewDebrickedGreeter() DebrickedGreeter { + return DebrickedGreeter{} +} + +func (dg DebrickedGreeter) Greeting(name string) string { + var sb strings.Builder + sb.WriteString("Hello ") + sb.WriteString(name) + sb.WriteString("!") + + return sb.String() +} diff --git a/internal/hello/hello_test.go b/internal/hello/hello_test.go new file mode 100644 index 00000000..7e0c4f0c --- /dev/null +++ b/internal/hello/hello_test.go @@ -0,0 +1,18 @@ +package hello + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestNewDebrickedGreeter(t *testing.T) { + greeter := NewDebrickedGreeter() + assert.NotNil(t, greeter) +} + +func TestGreeting(t *testing.T) { + greeter := NewDebrickedGreeter() + greeting := greeter.Greeting("Debricked") + assert.Equal(t, greeting, "Hello Debricked!") +} diff --git a/internal/hello/testdata/hello_mock.go b/internal/hello/testdata/hello_mock.go new file mode 100644 index 00000000..9321fafe --- /dev/null +++ b/internal/hello/testdata/hello_mock.go @@ -0,0 +1,7 @@ +package testdata + +type MockGreeter struct{} + +func (MockGreeter) Greeting(string) string { + return "hello" +} diff --git a/internal/wire/cli_container.go b/internal/wire/cli_container.go index f232f16a..110d74ff 100644 --- a/internal/wire/cli_container.go +++ b/internal/wire/cli_container.go @@ -10,6 +10,7 @@ import ( "github.com/debricked/cli/internal/client" "github.com/debricked/cli/internal/file" "github.com/debricked/cli/internal/fingerprint" + "github.com/debricked/cli/internal/hello" "github.com/debricked/cli/internal/io" licenseReport "github.com/debricked/cli/internal/report/license" vulnerabilityReport "github.com/debricked/cli/internal/report/vulnerability" @@ -93,6 +94,7 @@ func (cc *CliContainer) wire() error { cc.licenseReporter = licenseReport.Reporter{DebClient: cc.debClient} cc.vulnerabilityReporter = vulnerabilityReport.Reporter{DebClient: cc.debClient} cc.authenticator = auth.NewDebrickedAuthenticator(cc.debClient) + cc.greeter = hello.NewDebrickedGreeter() return nil } @@ -115,6 +117,7 @@ type CliContainer struct { cgScheduler callgraph.IScheduler cgStrategyFactory callgraphStrategy.IFactory authenticator auth.IAuthenticator + greeter hello.IGreeter } func (cc *CliContainer) DebClient() client.IDebClient { @@ -153,6 +156,10 @@ func (cc *CliContainer) Authenticator() auth.IAuthenticator { return cc.authenticator } +func (cc *CliContainer) Greeter() hello.IGreeter { + return cc.greeter +} + func wireErr(err error) error { return fmt.Errorf("failed to wire with cli-container. Error %s", err) }