Skip to content

Commit

Permalink
fix: validate old sauce values when upgrading a recipe (#110)
Browse files Browse the repository at this point in the history
  • Loading branch information
majori authored Jun 12, 2024
1 parent e8618a4 commit 3a9590b
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 7 deletions.
9 changes: 8 additions & 1 deletion internal/cli/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,14 @@ func runUpgrade(cmd *cobra.Command, opts upgradeOptions) error {
values = recipeutil.MergeValues(reusedValues, providedValues)

if opts.ReuseOldValues {
values = recipeutil.MergeValues(oldSauce.Values, values)
validatedValues, errs := recipeutil.CleanValues(re.Variables, oldSauce.Values)
if len(errs) != 0 {
for _, err := range errs {
cmd.Printf("WARNING: failed to validate old value for the variable %s. The value will be ignored.\n", err)
}
}

values = recipeutil.MergeValues(validatedValues, values)
}

// Don't prompt variables which already has a value in existing sauce or is predefined
Expand Down
5 changes: 5 additions & 0 deletions pkg/recipe/variable.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,11 @@ func (val VariableValues) Validate() error {
return nil
}

// RequiresTableContext returns true if the validator function should be created with CreateTableValidatorFunc
func (r *VariableValidator) RequiresTableContext() bool {
return r.Unique
}

func (r *VariableValidator) CreateTableValidatorFunc() (func(cols []string, rows [][]string, input string) error, error) {
if r.Unique {
return func(cols []string, rows [][]string, input string) error {
Expand Down
69 changes: 69 additions & 0 deletions pkg/recipeutil/values.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,75 @@ func ParseProvidedValues(variables []recipe.Variable, flags []string, delimiter
return values, nil
}

func CleanValues(variables []recipe.Variable, values recipe.VariableValues) (recipe.VariableValues, []error) {
validatedValues := make(recipe.VariableValues, len(values))
errs := make([]error, 0, len(values))
for _, variable := range variables {
if _, exists := values[variable.Name]; !exists {
continue
}

for _, validator := range variable.Validators {
if err := ValidateValue(validator, values[variable.Name]); err != nil {
errs = append(errs, fmt.Errorf("'%s': %w", variable.Name, err))
continue
}
}

validatedValues[variable.Name] = values[variable.Name]
}

return validatedValues, errs
}

func ValidateValue(validator recipe.VariableValidator, value interface{}) error {
switch v := value.(type) {
case string:
validatorFunc, err := validator.CreateValidatorFunc()
if err != nil {
return fmt.Errorf("validator creation failed: %w", err)
}

if err := validatorFunc(v); err != nil {
return err
}

case recipe.TableValue:
var validatorFunc func(string) error

if validator.RequiresTableContext() {
tableValidatorFunc, err := validator.CreateTableValidatorFunc()
if err != nil {
return fmt.Errorf("validator creation failed: %w", err)
}

validatorFunc = func(input string) error {
return tableValidatorFunc(v.Columns, v.Rows, input)
}

} else {
staticValidatorFunc, err := validator.CreateValidatorFunc()
if err != nil {
return fmt.Errorf("validator creation failed: %w", err)
}

validatorFunc = staticValidatorFunc
}

for _, row := range v.Rows {
for _, cell := range row {
if err := validatorFunc(cell); err != nil {
return err
}
}
}
default:
return fmt.Errorf("unsupported value type: %T", value)
}

return nil
}

// MergeValues merges multiple VariableValues into one. If a key exists in multiple VariableValues, the value from the
// last VariableValues will be used.
func MergeValues(valuesSlice ...recipe.VariableValues) recipe.VariableValues {
Expand Down
13 changes: 7 additions & 6 deletions pkg/ui/survey/prompt/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,22 +38,23 @@ func NewTableModel(v recipe.Variable, styles style.Styles) TableModel {
validators[validator.Column] = make([]func([]string, [][]string, string) error, 0)
}

if validator.Pattern != "" {
if validator.RequiresTableContext() {
validatorFn, err := validator.CreateTableValidatorFunc()
if err == nil {
validators[validator.Column] = append(validators[validator.Column], validatorFn)
}
} else {
regexValidator, err := v.Validators[i].CreateValidatorFunc()
if err == nil {
validators[validator.Column] = append(validators[validator.Column],
func(cols []string, rows [][]string, input string) error {
return regexValidator(input)
})
}
} else {
validatorFn, err := validator.CreateTableValidatorFunc()
if err == nil {
validators[validator.Column] = append(validators[validator.Column], validatorFn)
}
}
}
}

for i, c := range v.Columns {
cols[i] = editable.Column{
Title: c,
Expand Down

0 comments on commit 3a9590b

Please sign in to comment.