Skip to content

Commit

Permalink
Allow config options to be an enum.
Browse files Browse the repository at this point in the history
Use it for 'security.prompt.level'.
  • Loading branch information
mitchell-as committed Sep 17, 2024
1 parent 1373a50 commit d9cce92
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 3 deletions.
21 changes: 19 additions & 2 deletions internal/mediators/config/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,27 @@ const (
String Type = iota
Int
Bool
Enum
)

var registry = make(Registry)

type Enums struct {
Options []string
Default string
}

// Event is run when a user tries to set or get a config value via `state config`
type Event func(value interface{}) (interface{}, error)

var EmptyEvent = func(value interface{}) (interface{}, error) { return value, nil }
var EmptyEvent = func(value interface{}) (interface{}, error) {
if enum, ok := value.(*Enums); ok {
// In case this config option is not set, return its default value instead
// of the Enums struct itself.
return enum.Default, nil
}
return value, nil
}

// Option defines what a config value's name and type should be, along with any get/set events
type Option struct {
Expand All @@ -25,7 +40,9 @@ type Option struct {

type Registry map[string]Option

var registry = make(Registry)
func NewEnum(options []string, default_ string) *Enums {
return &Enums{options, default_}
}

// GetOption returns a config option, regardless of whether or not it has been registered.
// Use KnownOption to determine if the returned option has been previously registered.
Expand Down
8 changes: 7 additions & 1 deletion internal/runbits/cves/cves.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,13 @@ import (

func init() {
configMediator.RegisterOption(constants.SecurityPromptConfig, configMediator.Bool, true)
configMediator.RegisterOption(constants.SecurityPromptLevelConfig, configMediator.String, vulnModel.SeverityCritical)
severities := configMediator.NewEnum([]string{
vulnModel.SeverityCritical,
vulnModel.SeverityHigh,
vulnModel.SeverityMedium,
vulnModel.SeverityLow,
}, vulnModel.SeverityCritical)
configMediator.RegisterOption(constants.SecurityPromptLevelConfig, configMediator.Enum, severities)
}

type primeable interface {
Expand Down
11 changes: 11 additions & 0 deletions internal/runners/config/set.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import (
"context"
"fmt"
"strconv"
"strings"

"github.com/thoas/go-funk"

"github.com/ActiveState/cli/internal/analytics"
"github.com/ActiveState/cli/internal/analytics/constants"
Expand Down Expand Up @@ -52,6 +55,14 @@ func (s *Set) Run(params SetParams) error {
if err != nil {
return locale.WrapInputError(err, "Invalid integer value")
}
case configMediator.Enum:
enums := option.Default.(*configMediator.Enums)
if !funk.Contains(enums.Options, params.Value) {
return locale.NewInputError(
"err_config_set_enum_invalid_value", "Invalid value '{{.V0}}': expected one of: {{.V1}}",
params.Value, strings.Join(enums.Options, ", "))
}
value = params.Value
default:
value = params.Value
}
Expand Down
29 changes: 29 additions & 0 deletions test/integration/config_int_test.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package integration

import (
"strings"
"testing"

"github.com/ActiveState/cli/internal/constants"
"github.com/ActiveState/cli/internal/testhelpers/e2e"
"github.com/ActiveState/cli/internal/testhelpers/suite"
"github.com/ActiveState/cli/internal/testhelpers/tagsuite"
vulnModel "github.com/ActiveState/cli/pkg/platform/api/vulnerabilities/model"
)

type ConfigIntegrationTestSuite struct {
Expand Down Expand Up @@ -41,6 +43,33 @@ func (suite *ConfigIntegrationTestSuite) TestConfig() {
cp.Expect("Invalid boolean value")
}

func (suite *ConfigIntegrationTestSuite) TestEnum() {
suite.OnlyRunForTags(tagsuite.Config)
ts := e2e.New(suite.T(), false)
defer ts.Close()

cp := ts.Spawn("config", "get", constants.SecurityPromptLevelConfig)
cp.Expect(vulnModel.SeverityCritical)

severities := []string{
vulnModel.SeverityCritical,
vulnModel.SeverityHigh,
vulnModel.SeverityMedium,
vulnModel.SeverityLow,
}

cp = ts.Spawn("config", "set", constants.SecurityPromptLevelConfig, "invalid")
cp.Expect("Invalid value 'invalid': expected one of: " + strings.Join(severities, ", "))
cp.ExpectNotExitCode(0)

cp = ts.Spawn("config", "set", constants.SecurityPromptLevelConfig, vulnModel.SeverityLow)
cp.ExpectExitCode(0)

cp = ts.Spawn("config", "get", constants.SecurityPromptLevelConfig)
cp.Expect(vulnModel.SeverityLow)
cp.ExpectExitCode(0)
}

func (suite *ConfigIntegrationTestSuite) TestJSON() {
suite.OnlyRunForTags(tagsuite.Config, tagsuite.JSON)
ts := e2e.New(suite.T(), false)
Expand Down

0 comments on commit d9cce92

Please sign in to comment.