@@ -123,12 +123,25 @@ func parameterDataSource() *schema.Resource {
123
123
if err != nil {
124
124
return diag .Errorf ("decode parameter: %s" ,err )
125
125
}
126
- value := parameter .Default
126
+
127
+ var value * string
128
+ if ! rd .GetRawConfig ().AsValueMap ()["default" ].IsNull () {
129
+ value = & parameter .Default
130
+ }
131
+
127
132
envValue ,ok := os .LookupEnv (ParameterEnvironmentVariable (parameter .Name ))
128
133
if ok {
129
- value = envValue
134
+ value = & envValue
135
+ }
136
+
137
+ if value != nil {
138
+ rd .Set ("value" ,value )
139
+ }else {
140
+ // Maintaining backwards compatibility. The previous behavior was
141
+ // to write back an empty string.
142
+ // TODO: Should an empty string exist if no value is set?
143
+ rd .Set ("value" ,"" )
130
144
}
131
- rd .Set ("value" ,value )
132
145
133
146
if ! parameter .Mutable && parameter .Ephemeral {
134
147
return diag .Errorf ("parameter can't be immutable and ephemeral" )
@@ -138,21 +151,6 @@ func parameterDataSource() *schema.Resource {
138
151
return diag .Errorf ("ephemeral parameter requires the default property" )
139
152
}
140
153
141
- // Do ValidateFormType up front. If there is no error, update the
142
- // 'parameter.FormType' value to the new value. This is to handle default cases,
143
- // since the default logic is more advanced than the sdk provider schema
144
- // supports.
145
- //_, newFT, err := ValidateFormType(parameter.Type, len(parameter.Option), parameter.FormType)
146
- //if err == nil {
147
- //// If there is an error, parameter.Valid will catch it.
148
- //parameter.FormType = newFT
149
- //
150
- //// Set the form_type back in case the value was changed.
151
- //// Eg via a default. If a user does not specify, a default value
152
- //// is used and saved.
153
- //rd.Set("form_type", parameter.FormType)
154
- //}
155
-
156
154
diags := parameter .Valid (value )
157
155
if diags .HasError () {
158
156
return diags
@@ -399,12 +397,7 @@ func valueIsType(typ OptionType, value string) error {
399
397
return nil
400
398
}
401
399
402
- func (v * Parameter )RelaxedValidation (value string ) diag.Diagnostics {
403
-
404
- return nil
405
- }
406
-
407
- func (v * Parameter )Valid (value string ) diag.Diagnostics {
400
+ func (v * Parameter )Valid (value * string ) diag.Diagnostics {
408
401
var err error
409
402
var optionType OptionType
410
403
@@ -422,88 +415,125 @@ func (v *Parameter) Valid(value string) diag.Diagnostics {
422
415
}
423
416
}
424
417
425
- optionNames := map [string ]any {}
426
- optionValues := map [string ]any {}
427
- if len (v .Option )> 0 {
428
- for _ ,option := range v .Option {
429
- _ ,exists := optionNames [option .Name ]
430
- if exists {
431
- return diag.Diagnostics {{
432
- Severity :diag .Error ,
433
- Summary :"Option names must be unique." ,
434
- Detail :fmt .Sprintf ("multiple options found with the same name %q" ,option .Name ),
435
- },
436
- }
437
- }
438
- _ ,exists = optionValues [option .Value ]
439
- if exists {
440
- return diag.Diagnostics {
441
- {
442
- Severity :diag .Error ,
443
- Summary :"Option values must be unique." ,
444
- Detail :fmt .Sprintf ("multiple options found with the same value %q" ,option .Value ),
445
- },
446
- }
447
- }
448
- err = valueIsType (optionType ,option .Value )
449
- if err != nil {
450
- return diag.Diagnostics {
451
- {
452
- Severity :diag .Error ,
453
- Summary :fmt .Sprintf ("Option %q with value=%q is not of type %q" ,option .Name ,option .Value ,optionType ),
454
- Detail :err .Error (),
455
- },
456
- }
457
- }
458
- optionValues [option .Value ]= nil
459
- optionNames [option .Name ]= nil
460
-
461
- // TODO: Option values should also be validated.
462
- // v.validValue(option.Value, optionType, nil, cty.Path{})
463
- }
418
+ optionValues ,diags := v .ValidOptions (optionType )
419
+ if diags .HasError () {
420
+ return diags
464
421
}
465
422
466
- // Validate the default value
467
- if v .Default != "" {
468
- err := valueIsType (v .Type ,v .Default )
423
+ // TODO: The default value should also be validated
424
+ //if v.Default != "" {
425
+ //err := valueIsType(v.Type, v.Default)
426
+ //if err != nil {
427
+ //return diag.Diagnostics{
428
+ //{
429
+ //Severity: diag.Error,
430
+ //Summary: fmt.Sprintf("Default value is not of type %q", v.Type),
431
+ //Detail: err.Error(),
432
+ //AttributePath: defaultValuePath,
433
+ //},
434
+ //}
435
+ //}
436
+ //
437
+ //d := v.validValue(v.Default, optionType, optionValues, defaultValuePath)
438
+ //if d.HasError() {
439
+ //return d
440
+ //}
441
+ //}
442
+
443
+ // TODO: Move this into 'Parameter.validValue'. It exists as another check outside because
444
+ // the current behavior is to always apply this validation, regardless if the param is set or not.
445
+ // Other validations are only applied if the parameter is set.
446
+ // This behavior should be standardized.
447
+ if len (v .Validation )== 1 {
448
+ empty := ""
449
+ validVal := value
450
+ if value == nil {
451
+ validVal = & empty
452
+ }
453
+ validCheck := & v .Validation [0 ]
454
+ err := validCheck .Valid (v .Type ,* validVal )
469
455
if err != nil {
470
456
return diag.Diagnostics {
471
457
{
472
458
Severity :diag .Error ,
473
- Summary :fmt .Sprintf ("Default value is not of type %q " ,v . Type ),
459
+ Summary :fmt .Sprintf ("Invalid parameter %s according to 'validation' block " ,strings . ToLower ( v . Name ) ),
474
460
Detail :err .Error (),
475
- AttributePath :defaultValuePath ,
461
+ AttributePath :cty. Path {} ,
476
462
},
477
463
}
478
464
}
465
+ }
479
466
480
- d := v .validValue (v .Default ,optionType ,optionValues ,defaultValuePath )
467
+ // Value is only validated if it is set. If it is unset, validation
468
+ // is skipped.
469
+ if value != nil {
470
+ d := v .validValue (* value ,optionType ,optionValues , cty.Path {})
481
471
if d .HasError () {
482
472
return d
483
473
}
484
- }
485
474
486
- // Value must always be validated
487
- d := v .validValue (value ,optionType ,optionValues , cty.Path {})
488
- if d .HasError () {
489
- return d
475
+ err = valueIsType (v .Type ,* value )
476
+ if err != nil {
477
+ return diag.Diagnostics {
478
+ {
479
+ Severity :diag .Error ,
480
+ Summary :fmt .Sprintf ("Parameter value is not of type %q" ,v .Type ),
481
+ Detail :err .Error (),
482
+ },
483
+ }
484
+ }
490
485
}
491
486
492
- err = valueIsType (v .Type ,value )
493
- if err != nil {
494
- return diag.Diagnostics {
495
- {
487
+ return nil
488
+ }
489
+
490
+ func (v * Parameter )ValidOptions (optionType OptionType ) (map [string ]struct {}, diag.Diagnostics ) {
491
+ optionNames := map [string ]struct {}{}
492
+ optionValues := map [string ]struct {}{}
493
+
494
+ var diags diag.Diagnostics
495
+ for _ ,option := range v .Option {
496
+ _ ,exists := optionNames [option .Name ]
497
+ if exists {
498
+ return nil , diag.Diagnostics {{
496
499
Severity :diag .Error ,
497
- Summary :fmt .Sprintf ("Parameter value is not of type %q" ,v .Type ),
500
+ Summary :"Option names must be unique." ,
501
+ Detail :fmt .Sprintf ("multiple options found with the same name %q" ,option .Name ),
502
+ }}
503
+ }
504
+
505
+ _ ,exists = optionValues [option .Value ]
506
+ if exists {
507
+ return nil , diag.Diagnostics {{
508
+ Severity :diag .Error ,
509
+ Summary :"Option values must be unique." ,
510
+ Detail :fmt .Sprintf ("multiple options found with the same value %q" ,option .Value ),
511
+ }}
512
+ }
513
+
514
+ err := valueIsType (optionType ,option .Value )
515
+ if err != nil {
516
+ diags = append (diags , diag.Diagnostic {
517
+ Severity :diag .Error ,
518
+ Summary :fmt .Sprintf ("Option %q with value=%q is not of type %q" ,option .Name ,option .Value ,optionType ),
498
519
Detail :err .Error (),
499
- },
520
+ })
521
+ continue
500
522
}
523
+ optionValues [option .Value ]= struct {}{}
524
+ optionNames [option .Name ]= struct {}{}
525
+
526
+ // TODO: Option values should also be validated.
527
+ // v.validValue(option.Value, optionType, nil, cty.Path{})
501
528
}
502
529
503
- return nil
530
+ if diags .HasError () {
531
+ return nil ,diags
532
+ }
533
+ return optionValues ,nil
504
534
}
505
535
506
- func (v * Parameter )validValue (value string ,optionType OptionType ,optionValues map [string ]any ,path cty.Path ) diag.Diagnostics {
536
+ func (v * Parameter )validValue (value string ,optionType OptionType ,optionValues map [string ]struct {} ,path cty.Path ) diag.Diagnostics {
507
537
// name is used for constructing more precise error messages.
508
538
name := "Value"
509
539
if path .Equals (defaultValuePath ) {
@@ -568,21 +598,6 @@ func (v *Parameter) validValue(value string, optionType OptionType, optionValues
568
598
}
569
599
}
570
600
571
- if len (v .Validation )== 1 {
572
- validCheck := & v .Validation [0 ]
573
- err := validCheck .Valid (v .Type ,value )
574
- if err != nil {
575
- return diag.Diagnostics {
576
- {
577
- Severity :diag .Error ,
578
- Summary :fmt .Sprintf ("Invalid parameter %s according to 'validation' block" ,strings .ToLower (name )),
579
- Detail :err .Error (),
580
- AttributePath :path ,
581
- },
582
- }
583
- }
584
- }
585
-
586
601
return nil
587
602
}
588
603