Skip to content

Commit 875b316

Browse files
committed
validate input vales
1 parent ac2f9bf commit 875b316

File tree

1 file changed

+82
-44
lines changed

1 file changed

+82
-44
lines changed

provider/parameter.go

Lines changed: 82 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ import (
2121
"golang.org/x/xerrors"
2222
)
2323

24+
var (
25+
defaultValuePath = cty.Path{cty.GetAttrStep{Name: "default"}}
26+
)
27+
2428
type Option struct {
2529
Name string
2630
Description string
@@ -124,7 +128,7 @@ func parameterDataSource() *schema.Resource {
124128
}
125129
var value string
126130
if parameter.Default != "" {
127-
err := valueIsType(parameter.Type, parameter.Default, cty.Path{cty.GetAttrStep{Name: "default"}})
131+
err := valueIsType(parameter.Type, parameter.Default, defaultValuePath)
128132
if err != nil {
129133
return err
130134
}
@@ -144,34 +148,22 @@ func parameterDataSource() *schema.Resource {
144148
return diag.Errorf("ephemeral parameter requires the default property")
145149
}
146150

147-
// TODO: Should we move this into the Valid() function on
148-
// Parameter?
149-
if len(parameter.Validation) == 1 {
150-
validation := &parameter.Validation[0]
151-
err = validation.Valid(parameter.Type, value)
152-
if err != nil {
153-
return diag.FromErr(err)
154-
}
151+
// Do ValidateFormType up front. If there is no error, update the
152+
// 'parameter.FormType' value to the new value. This is to handle default cases,
153+
// since the default logic is more advanced than the sdk provider schema
154+
// supports.
155+
_, newFT, err := ValidateFormType(parameter.Type, len(parameter.Option), parameter.FormType)
156+
if err == nil {
157+
// If there is an error, parameter.Valid will catch it.
158+
parameter.FormType = newFT
159+
160+
// Set the form_type back in case the value was changed.
161+
// Eg via a default. If a user does not specify, a default value
162+
// is used and saved.
163+
rd.Set("form_type", parameter.FormType)
155164
}
156165

157-
// Validate options
158-
_, parameter.FormType, err = ValidateFormType(parameter.Type, len(parameter.Option), parameter.FormType)
159-
if err != nil {
160-
return diag.Diagnostics{
161-
{
162-
Severity: diag.Error,
163-
Summary: "Invalid form_type for parameter",
164-
Detail: err.Error(),
165-
AttributePath: cty.Path{cty.GetAttrStep{Name: "form_type"}},
166-
},
167-
}
168-
}
169-
// Set the form_type back in case the value was changed.
170-
// Eg via a default. If a user does not specify, a default value
171-
// is used and saved.
172-
rd.Set("form_type", parameter.FormType)
173-
174-
diags := parameter.Valid()
166+
diags := parameter.Valid(value)
175167
if diags.HasError() {
176168
return diags
177169
}
@@ -414,10 +406,13 @@ func valueIsType(typ OptionType, value string, attrPath cty.Path) diag.Diagnosti
414406
return nil
415407
}
416408

417-
func (v *Parameter) Valid() diag.Diagnostics {
409+
func (v *Parameter) Valid(value string) diag.Diagnostics {
410+
var err error
411+
var optionType OptionType
412+
418413
// optionType might differ from parameter.Type. This is ok, and parameter.Type
419414
// should be used for the value type, and optionType for options.
420-
optionType, _, err := ValidateFormType(v.Type, len(v.Option), v.FormType)
415+
optionType, v.FormType, err = ValidateFormType(v.Type, len(v.Option), v.FormType)
421416
if err != nil {
422417
return diag.Diagnostics{
423418
{
@@ -458,55 +453,98 @@ func (v *Parameter) Valid() diag.Diagnostics {
458453
}
459454
optionValues[option.Value] = nil
460455
optionNames[option.Name] = nil
456+
457+
// TODO: Option values should also be validated.
458+
// v.validValue(option.Value, optionType, nil, cty.Path{})
459+
}
460+
}
461+
462+
// Validate the default value
463+
if v.Default != "" {
464+
d := v.validValue(v.Default, optionType, optionValues, defaultValuePath)
465+
if d.HasError() {
466+
return d
461467
}
462468
}
463469

464-
if v.Default != "" && len(v.Option) > 0 {
470+
// Value must always be validated
471+
d := v.validValue(value, optionType, optionValues, cty.Path{})
472+
if d.HasError() {
473+
return d
474+
}
475+
476+
return nil
477+
}
478+
479+
func (v *Parameter) validValue(value string, optionType OptionType, optionValues map[string]any, path cty.Path) diag.Diagnostics {
480+
// name is used for constructing more precise error messages.
481+
name := "Value"
482+
if path.Equals(defaultValuePath) {
483+
name = "Default value"
484+
}
485+
486+
// First validate if the value is a valid option
487+
if len(optionValues) > 0 {
465488
if v.Type == OptionTypeListString && optionType == OptionTypeString {
466489
// If the type is list(string) and optionType is string, we have
467490
// to ensure all elements of the default exist as options.
468-
defaultValues, diags := valueIsListString(v.Default, cty.Path{cty.GetAttrStep{Name: "default"}})
491+
listValues, diags := valueIsListString(value, defaultValuePath)
469492
if diags.HasError() {
470493
return diags
471494
}
472495

473496
// missing is used to construct a more helpful error message
474497
var missing []string
475-
for _, defaultValue := range defaultValues {
476-
_, defaultIsValid := optionValues[defaultValue]
477-
if !defaultIsValid {
478-
missing = append(missing, defaultValue)
498+
for _, listValue := range listValues {
499+
_, isValid := optionValues[listValue]
500+
if !isValid {
501+
missing = append(missing, listValue)
479502
}
480503
}
481504

482505
if len(missing) > 0 {
483506
return diag.Diagnostics{
484507
{
485508
Severity: diag.Error,
486-
Summary: "Default values must be a valid option",
509+
Summary: fmt.Sprintf("%ss must be a valid option", name),
487510
Detail: fmt.Sprintf(
488-
"default value %q is not a valid option, values %q are missing from the options",
489-
v.Default, strings.Join(missing, ", "),
511+
"%s %q is not a valid option, values %q are missing from the options",
512+
name, value, strings.Join(missing, ", "),
490513
),
491-
AttributePath: cty.Path{cty.GetAttrStep{Name: "default"}},
514+
AttributePath: defaultValuePath,
492515
},
493516
}
494517
}
495518
} else {
496-
_, defaultIsValid := optionValues[v.Default]
497-
if !defaultIsValid {
519+
_, isValid := optionValues[value]
520+
if !isValid {
498521
return diag.Diagnostics{
499522
{
500523
Severity: diag.Error,
501-
Summary: "Default value must be a valid option",
502-
Detail: fmt.Sprintf("the value %q must be defined as one of options", v.Default),
503-
AttributePath: cty.Path{cty.GetAttrStep{Name: "default"}},
524+
Summary: fmt.Sprintf("%s must be a valid option", name),
525+
Detail: fmt.Sprintf("the value %q must be defined as one of options", value),
526+
AttributePath: path,
504527
},
505528
}
506529
}
507530
}
508531
}
509532

533+
if len(v.Validation) == 1 {
534+
validCheck := &v.Validation[0]
535+
err := validCheck.Valid(v.Type, value)
536+
if err != nil {
537+
return diag.Diagnostics{
538+
{
539+
Severity: diag.Error,
540+
Summary: fmt.Sprintf("Invalid parameter %s according to 'validation' block", strings.ToLower(name)),
541+
Detail: err.Error(),
542+
AttributePath: path,
543+
},
544+
}
545+
}
546+
}
547+
510548
return nil
511549
}
512550

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy