Skip to content

Commit

Permalink
Add enums to flags (#165)
Browse files Browse the repository at this point in the history
* Moving form keymap settings

* Add enum flag

* Parse enum

* Add enum to form

* Add in multi-select

* Add more multi select

* Add enum tests

* Make case insensitive

* Use EqualFold

Co-authored-by: Max Eshleman <[email protected]>

---------

Co-authored-by: Max Eshleman <[email protected]>
  • Loading branch information
mdbenjam and kitemongerer authored Dec 5, 2024
1 parent ba104d3 commit 61ac957
Show file tree
Hide file tree
Showing 8 changed files with 344 additions and 52 deletions.
17 changes: 13 additions & 4 deletions cmd/logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,15 @@ func getLogsOptions(ctx context.Context, breadcrumb string) []tui.CustomOption {
}

func init() {
directionFlag := command.NewEnumInput([]string{"backward", "forward"}, false)
levelFlag := command.NewEnumInput([]string{
"debug", "info", "notice", "warning", "error", "critical", "alert", "emergency",
}, true)
logTypeFlag := command.NewEnumInput([]string{"app", "request", "build"}, true)
methodTypeFlag := command.NewEnumInput([]string{
"GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD", "CONNECT", "TRACE",
}, true)

logsCmd.RunE = func(cmd *cobra.Command, args []string) error {
var input views.LogInput
err := command.ParseCommand(cmd, args, &input)
Expand Down Expand Up @@ -148,14 +157,14 @@ func init() {
logsCmd.Flags().String("start", "", "The start time of the logs to query")
logsCmd.Flags().String("end", "", "The end time of the logs to query")
logsCmd.Flags().StringSlice("text", []string{}, "A list of comma separated strings to search for in the logs")
logsCmd.Flags().StringSlice("level", []string{}, "A list of comma separated log levels to query")
logsCmd.Flags().StringSlice("type", []string{}, "A list of comma separated log types to query")
logsCmd.Flags().Var(levelFlag, "level", "A list of comma separated log levels to query")
logsCmd.Flags().Var(logTypeFlag, "type", "A list of comma separated log types to query")
logsCmd.Flags().StringSlice("instance", []string{}, "A list of comma separated instance IDs to query")
logsCmd.Flags().StringSlice("host", []string{}, "A list of comma separated hosts to query")
logsCmd.Flags().StringSlice("status-code", []string{}, "A list of comma separated status codes to query")
logsCmd.Flags().StringSlice("method", []string{}, "A list of comma separated HTTP methods to query")
logsCmd.Flags().Var(methodTypeFlag, "method", "A list of comma separated HTTP methods to query")
logsCmd.Flags().StringSlice("path", []string{}, "A list of comma separated paths to query")
logsCmd.Flags().Int("limit", 100, "The maximum number of logs to return")
logsCmd.Flags().String("direction", "backward", "The direction to query the logs. Can be 'forward' or 'backward'")
logsCmd.Flags().Var(directionFlag, "direction", "The direction to query the logs. Can be 'forward' or 'backward'")
logsCmd.Flags().Bool("tail", false, "Stream new logs")
}
80 changes: 80 additions & 0 deletions pkg/command/enum.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package command

import (
"fmt"
"strings"
)

const (
EnumType = "enum"
)

type CobraEnum struct {
values []string
selectedIndexes []int
isMultiSelect bool
}

func NewEnumInput(values []string, isMultiSelect bool) *CobraEnum {
return &CobraEnum{
values: values,
isMultiSelect: isMultiSelect,
}
}

func (e *CobraEnum) String() string {
if len(e.values) == 0 && !e.isMultiSelect {
return "Invalid enum value"
}

values := make([]string, len(e.selectedIndexes))
for i, index := range e.selectedIndexes {
values[i] = e.values[index]
}

return strings.Join(values, ", ")
}

func (e *CobraEnum) Set(v string) error {
values := strings.Split(v, ",")

for _, splitValue := range values {
for i, value := range e.values {
if strings.EqualFold(splitValue, value) {
e.selectedIndexes = append(e.selectedIndexes, i)
}
}
}

if len(e.selectedIndexes) != 0 {
return nil
}

var stringValues []string

for _, value := range e.values {
stringValues = append(stringValues, fmt.Sprintf("%q", value))
}

return fmt.Errorf("must be one of %s", strings.Join(stringValues, ", "))
}

func (e *CobraEnum) Type() string {
return EnumType
}

func (e *CobraEnum) Values() []string {
return e.values
}

func (e *CobraEnum) SelectedValues() []string {
var selectedValues []string
for _, index := range e.selectedIndexes {
selectedValues = append(selectedValues, e.values[index])
}
return selectedValues
}

func (e *CobraEnum) IsMultiSelect() bool {
return e.isMultiSelect
}
72 changes: 72 additions & 0 deletions pkg/command/enum_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package command_test

import (
"testing"

"github.com/renderinc/cli/pkg/command"
"github.com/stretchr/testify/require"
)

func TestCobraEnum(t *testing.T) {
t.Run("single select", func(t *testing.T) {
t.Run("properties", func(t *testing.T) {
enum := command.NewEnumInput([]string{"a", "b", "c"}, false)

require.False(t, enum.IsMultiSelect())
require.Equal(t, "enum", enum.Type())
require.Equal(t, []string{"a", "b", "c"}, enum.Values())
})

t.Run("can set to valid value", func(t *testing.T) {
enum := command.NewEnumInput([]string{"a", "b", "c"}, false)

require.NoError(t, enum.Set("b"))
require.Equal(t, []string{"b"}, enum.SelectedValues())
})

t.Run("is case insensitive", func(t *testing.T) {
enum := command.NewEnumInput([]string{"a", "b", "c"}, false)

require.NoError(t, enum.Set("B"))
require.Equal(t, []string{"b"}, enum.SelectedValues())
})

t.Run("errors when set to invalid value", func(t *testing.T) {
enum := command.NewEnumInput([]string{"a", "b", "c"}, false)

require.Error(t, enum.Set("d"))
require.Empty(t, enum.SelectedValues())
})
})

t.Run("multi select", func(t *testing.T) {
t.Run("properties", func(t *testing.T) {
enum := command.NewEnumInput([]string{"a", "b", "c"}, true)

require.True(t, enum.IsMultiSelect())
require.Equal(t, "enum", enum.Type())
require.Equal(t, []string{"a", "b", "c"}, enum.Values())
})

t.Run("can set to valid value", func(t *testing.T) {
enum := command.NewEnumInput([]string{"a", "b", "c"}, true)

require.NoError(t, enum.Set("b,c"))
require.Equal(t, []string{"b", "c"}, enum.SelectedValues())
})

t.Run("is case insensitive", func(t *testing.T) {
enum := command.NewEnumInput([]string{"a", "b", "c"}, true)

require.NoError(t, enum.Set("B,C"))
require.Equal(t, []string{"b", "c"}, enum.SelectedValues())
})

t.Run("errors when set to invalid value", func(t *testing.T) {
enum := command.NewEnumInput([]string{"a", "b", "c"}, true)

require.Error(t, enum.Set("d"))
require.Empty(t, enum.SelectedValues())
})
})
}
Loading

0 comments on commit 61ac957

Please sign in to comment.