-
Notifications
You must be signed in to change notification settings - Fork 0
/
values.go
139 lines (118 loc) · 4.02 KB
/
values.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package recipeutil
import (
"errors"
"fmt"
"os"
"slices"
"strings"
"github.com/futurice/jalapeno/pkg/recipe"
)
const ValueEnvVarPrefix = "JALAPENO_VAR_"
var (
ErrVarNotDefinedInRecipe = errors.New("following variable does not exist in the recipe")
)
func ParseProvidedValues(variables []recipe.Variable, flags []string, delimiter rune, parseEnvs bool) (recipe.VariableValues, error) {
values := make(recipe.VariableValues)
if parseEnvs {
for _, env := range os.Environ() {
if !strings.HasPrefix(env, ValueEnvVarPrefix) {
continue
}
// Add environment variables at the beginning of the slice so CLI flags override env. variables
flags = append([]string{strings.TrimPrefix(env, ValueEnvVarPrefix)}, flags...)
}
}
for _, flag := range flags {
splitted := strings.SplitN(flag, "=", 2)
if len(splitted) != 2 {
return nil, fmt.Errorf("invalid format on flag '%s'. Use format 'MY_VAR=VALUE'", flag)
}
varName := splitted[0]
varValue := splitted[1]
var targetedVariable *recipe.Variable
for _, variable := range variables {
if variable.Name != varName {
continue
} else {
targetedVariable = &variable
break
}
}
if targetedVariable == nil {
return nil, fmt.Errorf("%w: %s", ErrVarNotDefinedInRecipe, varName)
}
switch {
case targetedVariable.Confirm:
if varValue == "true" {
values[varName] = true
} else if varValue == "false" {
values[varName] = false
} else {
return nil, fmt.Errorf("value provided for variable '%s' was not a boolean", varName)
}
case len(targetedVariable.Columns) > 0:
varValue = strings.ReplaceAll(varValue, "\\n", "\n")
table := recipe.TableValue{}
err := table.FromCSV(targetedVariable.Columns, varValue, delimiter)
if err != nil {
return nil, fmt.Errorf("failed to parse table from CSV for variable '%s': %w", varName, err)
}
for i := range targetedVariable.Validators {
validator := targetedVariable.Validators[i]
validatorFunc := validator.CreateValidatorFunc()
for _, row := range table.Rows {
columnIndex := slices.Index(table.Columns, validator.Column)
if err := validatorFunc(row[columnIndex]); err != nil {
return nil, fmt.Errorf("validator failed for variable %s in column %s, row %d: %w", varName, validator.Column, i, err)
}
}
}
values[varName] = table
default:
for i := range targetedVariable.Validators {
validatorFunc := targetedVariable.Validators[i].CreateValidatorFunc()
if err := validatorFunc(varValue); err != nil {
return nil, fmt.Errorf("validator failed for value '%s=%s': %w", varName, varValue, err)
}
}
values[varName] = varValue
}
}
return values, 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 {
merged := make(recipe.VariableValues)
for _, values := range valuesSlice {
for key := range values {
merged[key] = values[key]
}
}
return merged
}
func FilterVariablesWithoutValues(variables []recipe.Variable, values recipe.VariableValues) []recipe.Variable {
variablesWithoutValues := make([]recipe.Variable, 0, len(variables))
for _, variable := range variables {
if _, exists := values[variable.Name]; !exists {
variablesWithoutValues = append(variablesWithoutValues, variable)
}
}
return variablesWithoutValues
}
func NewNoInputError(vars []recipe.Variable) error {
var errMsg string
switch len(vars) {
case 0:
return errors.New("there was file conflicts which needs to be manually resolved while `--no-input` flag was set to true")
case 1:
return fmt.Errorf("value for variable %s is missing and `--no-input` flag was set to true", vars[0].Name)
default:
varNames := make([]string, len(vars))
for i, v := range vars {
varNames[i] = v.Name
}
errMsg = fmt.Sprintf("values for variables [%s] are", strings.Join(varNames, ","))
return fmt.Errorf("%s missing and `--no-input` flag was set to true", errMsg)
}
}