Skip to content

Commit

Permalink
feat: add global --quiet flag to hide non-error messages (#656)
Browse files Browse the repository at this point in the history
Closes #644
  • Loading branch information
phm07 authored Jan 10, 2024
1 parent c4f5e15 commit 25fcbbf
Show file tree
Hide file tree
Showing 121 changed files with 829 additions and 343 deletions.
12 changes: 11 additions & 1 deletion internal/cli/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,23 @@ func NewRootCommand(s state.State) *cobra.Command {
primaryip.NewCommand(s),
)
cmd.PersistentFlags().Duration("poll-interval", 500*time.Millisecond, "Interval at which to poll information, for example action progress")
cmd.SetOut(os.Stdout)
cmd.PersistentFlags().Bool("quiet", false, "Only print error messages")

cmd.PersistentPreRunE = func(cmd *cobra.Command, args []string) error {
pollInterval, err := cmd.Flags().GetDuration("poll-interval")
if err != nil {
return err
}
s.Client().WithOpts(hcloud.WithPollBackoffFunc(hcloud.ConstantBackoff(pollInterval)))

out := os.Stdout
if quiet, _ := cmd.Flags().GetBool("quiet"); quiet {
out, err = os.Open(os.DevNull)
if err != nil {
return err
}
}
cmd.SetOut(out)
return nil
}
return cmd
Expand Down
2 changes: 1 addition & 1 deletion internal/cmd/all/all.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ func NewCommand(s state.State) *cobra.Command {
DisableFlagsInUseLine: true,
}
cmd.AddCommand(
listCmd.CobraCommand(s),
ListCmd.CobraCommand(s),
)
return cmd
}
2 changes: 1 addition & 1 deletion internal/cmd/all/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ var allCmds = []base.ListCmd{
sshkey.ListCmd,
}

var listCmd = base.Cmd{
var ListCmd = base.Cmd{
BaseCobraCommand: func(client hcapi2.Client) *cobra.Command {

var resources []string
Expand Down
7 changes: 4 additions & 3 deletions internal/cmd/all/list_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package all
package all_test

import (
_ "embed"
Expand All @@ -9,6 +9,7 @@ import (
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"

"github.com/hetznercloud/cli/internal/cmd/all"
"github.com/hetznercloud/cli/internal/testutil"
"github.com/hetznercloud/hcloud-go/v2/hcloud"
)
Expand All @@ -22,7 +23,7 @@ func TestListAll(t *testing.T) {

time.Local = time.UTC

cmd := listCmd.CobraCommand(fx.State())
cmd := all.ListCmd.CobraCommand(fx.State())
fx.ExpectEnsureToken()

fx.Client.ServerClient.EXPECT().
Expand Down Expand Up @@ -246,7 +247,7 @@ func TestListAllPaidJSON(t *testing.T) {

time.Local = time.UTC

cmd := listCmd.CobraCommand(fx.State())
cmd := all.ListCmd.CobraCommand(fx.State())
fx.ExpectEnsureToken()

fx.Client.ServerClient.EXPECT().
Expand Down
6 changes: 3 additions & 3 deletions internal/cmd/base/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ func (cc *CreateCmd) CobraCommand(s state.State) *cobra.Command {
cmd.RunE = func(cmd *cobra.Command, args []string) error {
outputFlags := output.FlagsForCommand(cmd)

quiet, _ := cmd.Flags().GetBool("quiet")

isSchema := outputFlags.IsSet("json") || outputFlags.IsSet("yaml")
if isSchema {
if isSchema && !quiet {
cmd.SetOut(os.Stderr)
} else {
cmd.SetOut(os.Stdout)
}

resource, schema, err := cc.Run(s, cmd, args)
Expand Down
71 changes: 71 additions & 0 deletions internal/cmd/base/create_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package base_test

import (
"testing"

"github.com/spf13/cobra"

"github.com/hetznercloud/cli/internal/cmd/base"
"github.com/hetznercloud/cli/internal/cmd/util"
"github.com/hetznercloud/cli/internal/hcapi2"
"github.com/hetznercloud/cli/internal/state"
"github.com/hetznercloud/cli/internal/testutil"
)

type fakeResource struct {
ID int `json:"id"`
Name string `json:"name"`
}

var fakeCreateCmd = &base.CreateCmd{
BaseCobraCommand: func(client hcapi2.Client) *cobra.Command {
return &cobra.Command{
Use: "create",
}
},
Run: func(s state.State, cmd *cobra.Command, strings []string) (any, any, error) {
cmd.Println("Creating fake resource")

resource := &fakeResource{
ID: 123,
Name: "test",
}

return resource, util.Wrap("resource", resource), nil
},
}

func TestCreate(t *testing.T) {
const resourceSchema = `{"resource": {"id": 123, "name": "test"}}`
testutil.TestCommand(t, fakeCreateCmd, map[string]testutil.TestCase{
"no flags": {
Args: []string{"create"},
ExpOut: "Creating fake resource\n",
},
"json": {
Args: []string{"create", "-o=json"},
ExpOut: resourceSchema,
ExpOutType: testutil.DataTypeJSON,
ExpErrOut: "Creating fake resource\n",
},
"yaml": {
Args: []string{"create", "-o=yaml"},
ExpOut: resourceSchema,
ExpOutType: testutil.DataTypeYAML,
ExpErrOut: "Creating fake resource\n",
},
"quiet": {
Args: []string{"create", "--quiet"},
},
"json quiet": {
Args: []string{"create", "-o=json", "--quiet"},
ExpOut: resourceSchema,
ExpOutType: testutil.DataTypeJSON,
},
"yaml quiet": {
Args: []string{"create", "-o=yaml", "--quiet"},
ExpOut: resourceSchema,
ExpOutType: testutil.DataTypeYAML,
},
})
}
48 changes: 48 additions & 0 deletions internal/cmd/base/delete_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package base_test

import (
"testing"

"github.com/spf13/cobra"

"github.com/hetznercloud/cli/internal/cmd/base"
"github.com/hetznercloud/cli/internal/hcapi2"
"github.com/hetznercloud/cli/internal/state"
"github.com/hetznercloud/cli/internal/testutil"
"github.com/hetznercloud/hcloud-go/v2/hcloud"
)

var fakeDeleteCmd = &base.DeleteCmd{
ResourceNameSingular: "Fake resource",
Delete: func(s state.State, cmd *cobra.Command, resource interface{}) error {
cmd.Println("Deleting fake resource")
return nil
},

Fetch: func(s state.State, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) {
cmd.Println("Fetching fake resource")

resource := &fakeResource{
ID: 123,
Name: "test",
}

return resource, nil, nil
},

NameSuggestions: func(client hcapi2.Client) func() []string {
return nil
},
}

func TestDelete(t *testing.T) {
testutil.TestCommand(t, fakeDeleteCmd, map[string]testutil.TestCase{
"no flags": {
Args: []string{"delete", "123"},
ExpOut: "Fetching fake resource\nDeleting fake resource\nFake resource 123 deleted\n",
},
"quiet": {
Args: []string{"delete", "123", "--quiet"},
},
})
}
8 changes: 8 additions & 0 deletions internal/cmd/base/describe.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package base

import (
"fmt"
"os"
"reflect"
"strings"

Expand Down Expand Up @@ -54,6 +55,13 @@ func (dc *DescribeCmd) CobraCommand(s state.State) *cobra.Command {
func (dc *DescribeCmd) Run(s state.State, cmd *cobra.Command, args []string) error {
outputFlags := output.FlagsForCommand(cmd)

quiet, _ := cmd.Flags().GetBool("quiet")

isSchema := outputFlags.IsSet("json") || outputFlags.IsSet("yaml")
if isSchema && !quiet {
cmd.SetOut(os.Stderr)
}

idOrName := args[0]
resource, schema, err := dc.Fetch(s, cmd, idOrName)
if err != nil {
Expand Down
77 changes: 77 additions & 0 deletions internal/cmd/base/describe_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package base_test

import (
"testing"

"github.com/spf13/cobra"

"github.com/hetznercloud/cli/internal/cmd/base"
"github.com/hetznercloud/cli/internal/cmd/util"
"github.com/hetznercloud/cli/internal/hcapi2"
"github.com/hetznercloud/cli/internal/state"
"github.com/hetznercloud/cli/internal/testutil"
)

var fakeDescribeCmd = &base.DescribeCmd{
ResourceNameSingular: "Fake resource",

Fetch: func(s state.State, cmd *cobra.Command, idOrName string) (interface{}, interface{}, error) {
cmd.Println("Fetching fake resource")

resource := &fakeResource{
ID: 123,
Name: "test",
}

return resource, util.Wrap("resource", resource), nil
},

PrintText: func(s state.State, cmd *cobra.Command, resource interface{}) error {
rsc := resource.(*fakeResource)
cmd.Printf("ID: %d\n", rsc.ID)
cmd.Printf("Name: %s\n", rsc.Name)
return nil
},

NameSuggestions: func(client hcapi2.Client) func() []string {
return nil
},
}

func TestDescribe(t *testing.T) {
const resourceSchema = `{"resource": {"id": 123, "name": "test"}}`
testutil.TestCommand(t, fakeDescribeCmd, map[string]testutil.TestCase{
"no flags": {
Args: []string{"describe", "123"},
ExpOut: `Fetching fake resource
ID: 123
Name: test
`,
},
"json": {
Args: []string{"describe", "123", "-o=json"},
ExpOut: resourceSchema,
ExpOutType: testutil.DataTypeJSON,
ExpErrOut: "Fetching fake resource\n",
},
"yaml": {
Args: []string{"describe", "123", "-o=yaml"},
ExpOut: resourceSchema,
ExpOutType: testutil.DataTypeYAML,
ExpErrOut: "Fetching fake resource\n",
},
"quiet": {
Args: []string{"describe", "123", "--quiet"},
},
"json quiet": {
Args: []string{"describe", "123", "-o=json", "--quiet"},
ExpOut: resourceSchema,
ExpOutType: testutil.DataTypeJSON,
},
"yaml quiet": {
Args: []string{"describe", "123", "-o=yaml", "--quiet"},
ExpOut: resourceSchema,
ExpOutType: testutil.DataTypeYAML,
},
})
}
Loading

0 comments on commit 25fcbbf

Please sign in to comment.