Skip to content

Commit 9720077

Browse files
authored
Merge pull request #100 from onepanelio/feat/validating.params
feat: additional validation of parameters to prevent placeholders
2 parents 2549df5 + e11f02d commit 9720077

4 files changed

Lines changed: 80 additions & 13 deletions

File tree

cmd/apply.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ var applyCmd = &cobra.Command{
7575
resApp := ""
7676
errResApp := ""
7777

78-
7978
resApp, errResApp, err = applyKubernetesFile(applicationKubernetesYamlFilePath)
8079
if err != nil {
8180
yamlFile, yamlErr := util.LoadDynamicYamlFromFile(config.Spec.Params)

cmd/build.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ func init() {
6767
generateCmd.Flags().BoolVarP(&Dev, "latest", "", false, "Sets conditions to allow development testing.")
6868
}
6969

70-
// Given the path to the manifests, and a kustomize config, creates the final kustomization file.
70+
// GenerateKustomizeResult Given the path to the manifests, and a kustomize config, creates the final kustomization file.
7171
// It does this by copying the manifests into a temporary directory, inserting the kustomize template
7272
// and running the kustomize command
7373
func GenerateKustomizeResult(config opConfig.Config, kustomizeTemplate template.Kustomize) (string, error) {
@@ -640,11 +640,11 @@ func HumanizeKustomizeError(err error) string {
640640
case "missing":
641641
return fmt.Sprintf("%s is missing in your params.yaml", paramsError.Key)
642642
case "parameter":
643-
return fmt.Sprintf("%s can not be '%s', please enter a namespace", paramsError.Key, *paramsError.Value)
643+
return fmt.Sprintf("%s can not be '%s', please enter a different value for %v. %v", paramsError.Key, *paramsError.Value, paramsError.ShortKey, paramsError.ValidationMessage)
644644
case "blank":
645-
return fmt.Sprintf("%s can not be blank, please use a different namespace in your params.yaml", paramsError.Key)
645+
return fmt.Sprintf("%s can not be blank, please use a different %v in your params.yaml", paramsError.Key, paramsError.ShortKey)
646646
case "reserved":
647-
return fmt.Sprintf("%s can not be '%v' please use a different namespace in your params.yaml", paramsError.Key, *paramsError.Value)
647+
return fmt.Sprintf("%s can not be '%v' please use a different %v in your params.yaml", paramsError.Key, *paramsError.Value, paramsError.ShortKey)
648648
}
649649
}
650650

manifest/manifest.go

Lines changed: 69 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import (
66
"log"
77
"os"
88
"path/filepath"
9+
"regexp"
10+
"sort"
911
"strings"
1012
)
1113

@@ -17,9 +19,11 @@ type Manifest struct {
1719

1820
// ParamsError represents an error encountered in the params.yaml file
1921
type ParamsError struct {
20-
Key string
21-
Value *string
22-
ErrorType string
22+
Key string // The full key, as in 'application.domain'
23+
ShortKey string // The short key, as in 'domain'
24+
Value *string
25+
ErrorType string
26+
ValidationMessage string // empty space means none
2327
}
2428

2529
// Error returns an error string indicating what key/value is invalid
@@ -130,16 +134,74 @@ func Validate(manifest *util.DynamicYaml) error {
130134

131135
defaultNamespace := manifest.GetValue("application.defaultNamespace")
132136
if defaultNamespace == nil {
133-
return &ParamsError{Key: "application.defaultNamespace", ErrorType: "missing"}
137+
return &ParamsError{Key: "application.defaultNamespace", ShortKey: "defaultNamespace", ErrorType: "missing"}
134138
}
135139
if defaultNamespace.Value == "" {
136-
return &ParamsError{Key: "application.defaultNamespace", ErrorType: "blank"}
140+
return &ParamsError{Key: "application.defaultNamespace", ShortKey: "defaultNamespace", ErrorType: "blank"}
137141
}
138142
if defaultNamespace.Value == "<namespace>" {
139-
return &ParamsError{Key: "application.defaultNamespace", Value: &defaultNamespace.Value, ErrorType: "parameter"}
143+
return &ParamsError{
144+
Key: "application.defaultNamespace",
145+
ShortKey: "defaultNamespace",
146+
Value: &defaultNamespace.Value,
147+
ErrorType: "parameter",
148+
ValidationMessage: "Namespace can not be <namespace> please provide a value like 'example'",
149+
}
140150
}
141151
if _, ok := reservedNamespaces[defaultNamespace.Value]; ok {
142-
return &ParamsError{Key: "application.defaultNamespace", Value: &defaultNamespace.Value, ErrorType: "reserved"}
152+
return &ParamsError{Key: "application.defaultNamespace", ShortKey: "defaultNamespace", Value: &defaultNamespace.Value, ErrorType: "reserved"}
153+
}
154+
155+
if len(defaultNamespace.Value) > 63 {
156+
return &ParamsError{
157+
Key: "application.defaultNamespace",
158+
ShortKey: "defaultNamespace",
159+
Value: &defaultNamespace.Value,
160+
ErrorType: "parameter",
161+
ValidationMessage: "Namespace must be less than 63 characters",
162+
}
163+
}
164+
165+
if strings.HasPrefix(defaultNamespace.Value, "kube-") {
166+
return &ParamsError{
167+
Key: "application.defaultNamespace",
168+
ShortKey: "defaultNamespace",
169+
Value: &defaultNamespace.Value,
170+
ErrorType: "parameter",
171+
ValidationMessage: "A namespace can not start with 'kube-'",
172+
}
173+
}
174+
175+
namespaceRegex := regexp.MustCompile(`^[a-z0-9]([-a-z0-9]*[a-z0-9])$`)
176+
if !namespaceRegex.MatchString(defaultNamespace.Value) {
177+
return &ParamsError{
178+
Key: "application.defaultNamespace",
179+
ShortKey: "defaultNamespace",
180+
Value: &defaultNamespace.Value,
181+
ErrorType: "parameter",
182+
ValidationMessage: "A namespace can not start with 'kube-', must be lowercase, and can not start or end with dashes '-'",
183+
}
184+
}
185+
186+
flatMap := manifest.FlattenToKeyValue(util.AppendDotFlatMapKeyFormatter)
187+
mapKeys := []string{}
188+
for key := range flatMap {
189+
mapKeys = append(mapKeys, key)
190+
}
191+
sort.Strings(mapKeys)
192+
193+
for _, key := range mapKeys {
194+
value := flatMap[key]
195+
valueString, ok := value.(string)
196+
if !ok {
197+
continue
198+
}
199+
200+
if strings.HasPrefix(valueString, "<") {
201+
lastDotIndex := strings.LastIndex(key, ".")
202+
shortKey := key[lastDotIndex+1:]
203+
return &ParamsError{Key: key, ShortKey: shortKey, Value: &valueString, ErrorType: "parameter"}
204+
}
143205
}
144206

145207
return nil

util/dynamic_yaml.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,12 @@ func flattenMap(path string, keyFormatter FlatMapKeyFormatter, node *yaml.Node,
729729
} else if childNode.Kind == yaml.MappingNode {
730730
flattenMap(path, keyFormatter, childNode, results)
731731
continue
732+
} else if childNode.Kind == yaml.SequenceNode {
733+
for i, sequenceNode := range childNode.Content {
734+
newPath := keyFormatter(path, fmt.Sprintf("[%v]", i))
735+
flattenMap(newPath, keyFormatter, sequenceNode, results)
736+
}
737+
continue
732738
}
733739
}
734740
}
@@ -763,4 +769,4 @@ func GetYamlStringValue(mapping map[string]interface{}, key string) (*string, er
763769
result := strings.ToLower(valueString)
764770

765771
return &result, nil
766-
}
772+
}

0 commit comments

Comments
 (0)