Skip to content

Commit 8920f69

Browse files
committed
chore: implement validation in an exported function
Allows dynamic params to reuse the same logic
1 parent 53a68cd commit 8920f69

File tree

1 file changed

+75
-58
lines changed

1 file changed

+75
-58
lines changed

provider/parameter.go

+75-58
Original file line numberDiff line numberDiff line change
@@ -153,11 +153,7 @@ func parameterDataSource() *schema.Resource {
153153
}
154154

155155
// Validate options
156-
157-
// optionType might differ from parameter.Type. This is ok, and parameter.Type
158-
// should be used for the value type, and optionType for options.
159-
var optionType OptionType
160-
optionType, parameter.FormType, err = ValidateFormType(parameter.Type, len(parameter.Option), parameter.FormType)
156+
_, parameter.FormType, err = ValidateFormType(parameter.Type, len(parameter.Option), parameter.FormType)
161157
if err != nil {
162158
return diag.FromErr(err)
163159
}
@@ -166,60 +162,11 @@ func parameterDataSource() *schema.Resource {
166162
// is used and saved.
167163
rd.Set("form_type", parameter.FormType)
168164

169-
if len(parameter.Option) > 0 {
170-
names := map[string]interface{}{}
171-
values := map[string]interface{}{}
172-
for _, option := range parameter.Option {
173-
_, exists := names[option.Name]
174-
if exists {
175-
return diag.Errorf("multiple options cannot have the same name %q", option.Name)
176-
}
177-
_, exists = values[option.Value]
178-
if exists {
179-
return diag.Errorf("multiple options cannot have the same value %q", option.Value)
180-
}
181-
err := valueIsType(optionType, option.Value)
182-
if err != nil {
183-
return err
184-
}
185-
values[option.Value] = nil
186-
names[option.Name] = nil
187-
}
188-
189-
if parameter.Default != "" {
190-
if parameter.Type == OptionTypeListString && optionType == OptionTypeString {
191-
// If the type is list(string) and optionType is string, we have
192-
// to ensure all elements of the default exist as options.
193-
var defaultValues []string
194-
// TODO: We do this unmarshal in a few spots. It should be standardized.
195-
err = json.Unmarshal([]byte(parameter.Default), &defaultValues)
196-
if err != nil {
197-
return diag.Errorf("default value %q is not a list of strings", parameter.Default)
198-
}
199-
200-
// missing is used to construct a more helpful error message
201-
var missing []string
202-
for _, defaultValue := range defaultValues {
203-
_, defaultIsValid := values[defaultValue]
204-
if !defaultIsValid {
205-
missing = append(missing, defaultValue)
206-
}
207-
}
208-
209-
if len(missing) > 0 {
210-
return diag.Errorf(
211-
"default value %q is not a valid option, values %q are missing from the option",
212-
parameter.Default, strings.Join(missing, ", "),
213-
)
214-
}
215-
} else {
216-
_, defaultIsValid := values[parameter.Default]
217-
if !defaultIsValid {
218-
return diag.Errorf("%q default value %q must be defined as one of options", parameter.FormType, parameter.Default)
219-
}
220-
}
221-
}
165+
diags := parameter.Valid()
166+
if diags.HasError() {
167+
return diags
222168
}
169+
223170
return nil
224171
},
225172
Schema: map[string]*schema.Schema{
@@ -459,6 +406,76 @@ func valueIsType(typ OptionType, value string) diag.Diagnostics {
459406
return nil
460407
}
461408

409+
func (v *Parameter) Valid() diag.Diagnostics {
410+
// optionType might differ from parameter.Type. This is ok, and parameter.Type
411+
// should be used for the value type, and optionType for options.
412+
optionType, formType, err := ValidateFormType(v.Type, len(v.Option), v.FormType)
413+
if err != nil {
414+
return diag.FromErr(err)
415+
}
416+
417+
if formType != v.FormType {
418+
return diag.FromErr(fmt.Errorf("form_type %q is not valid for type %q", v.FormType, v.Type))
419+
}
420+
421+
optionNames := map[string]interface{}{}
422+
optionValues := map[string]interface{}{}
423+
if len(v.Option) > 0 {
424+
for _, option := range v.Option {
425+
_, exists := optionNames[option.Name]
426+
if exists {
427+
return diag.FromErr(fmt.Errorf("multiple options cannot have the same name %q", option.Name))
428+
}
429+
_, exists = optionValues[option.Value]
430+
if exists {
431+
return diag.FromErr(fmt.Errorf("multiple options cannot have the same value %q", option.Value))
432+
}
433+
diags := valueIsType(optionType, option.Value)
434+
if diags.HasError() {
435+
return diags
436+
}
437+
optionValues[option.Value] = nil
438+
optionNames[option.Name] = nil
439+
}
440+
}
441+
442+
if v.Default != "" {
443+
if v.Type == OptionTypeListString && optionType == OptionTypeString {
444+
// If the type is list(string) and optionType is string, we have
445+
// to ensure all elements of the default exist as options.
446+
var defaultValues []string
447+
// TODO: We do this unmarshal in a few spots. It should be standardized.
448+
err = json.Unmarshal([]byte(v.Default), &defaultValues)
449+
if err != nil {
450+
return diag.FromErr(fmt.Errorf("default value %q is not a list of strings", v.Default))
451+
}
452+
453+
// missing is used to construct a more helpful error message
454+
var missing []string
455+
for _, defaultValue := range defaultValues {
456+
_, defaultIsValid := optionValues[defaultValue]
457+
if !defaultIsValid {
458+
missing = append(missing, defaultValue)
459+
}
460+
}
461+
462+
if len(missing) > 0 {
463+
return diag.FromErr(fmt.Errorf(
464+
"default value %q is not a valid option, values %q are missing from the option",
465+
v.Default, strings.Join(missing, ", "),
466+
))
467+
}
468+
} else {
469+
_, defaultIsValid := optionValues[v.Default]
470+
if !defaultIsValid {
471+
return diag.FromErr(fmt.Errorf("%q default value %q must be defined as one of options", v.FormType, v.Default))
472+
}
473+
}
474+
}
475+
476+
return nil
477+
}
478+
462479
func (v *Validation) Valid(typ OptionType, value string) error {
463480
if typ != OptionTypeNumber {
464481
if !v.MinDisabled {

0 commit comments

Comments
 (0)