-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* listvalidator: add `NoNullValues` validator This validator will iterate over elements in the list, returning an error diagnostic if any null elements are detected. * setvalidator: add `NoNullValues` validator This validator will iterate over elements in the set, returning an error diagnostic if any null elements are detected. * mapvalidator: add `NoNullValues` validator This validator will iterate over elements in the map, returning an error diagnostic if any null elements are detected. * Documentation adjustments * changelogs ---------
- Loading branch information
Showing
12 changed files
with
702 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
kind: FEATURES | ||
body: 'listvalidator: Added `NoNullValues` validator' | ||
time: 2024-12-12T14:05:48.064529-05:00 | ||
custom: | ||
Issue: "245" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
kind: FEATURES | ||
body: 'mapvalidator: Added `NoNullValues` validator' | ||
time: 2024-12-12T14:06:13.229216-05:00 | ||
custom: | ||
Issue: "245" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
kind: FEATURES | ||
body: 'setvalidator: Added `NoNullValues` validator' | ||
time: 2024-12-12T14:06:24.967598-05:00 | ||
custom: | ||
Issue: "245" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
// Copyright (c) HashiCorp, Inc. | ||
// SPDX-License-Identifier: MPL-2.0 | ||
|
||
package listvalidator | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/hashicorp/terraform-plugin-framework/function" | ||
"github.com/hashicorp/terraform-plugin-framework/schema/validator" | ||
) | ||
|
||
var _ validator.List = noNullValuesValidator{} | ||
var _ function.ListParameterValidator = noNullValuesValidator{} | ||
|
||
type noNullValuesValidator struct{} | ||
|
||
func (v noNullValuesValidator) Description(_ context.Context) string { | ||
return "All values in the list must be configured" | ||
} | ||
|
||
func (v noNullValuesValidator) MarkdownDescription(ctx context.Context) string { | ||
return v.Description(ctx) | ||
} | ||
|
||
func (v noNullValuesValidator) ValidateList(_ context.Context, req validator.ListRequest, resp *validator.ListResponse) { | ||
if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() { | ||
return | ||
} | ||
|
||
elements := req.ConfigValue.Elements() | ||
|
||
for _, e := range elements { | ||
// Only evaluate known values for null | ||
if e.IsUnknown() { | ||
continue | ||
} | ||
|
||
if e.IsNull() { | ||
resp.Diagnostics.AddAttributeError( | ||
req.Path, | ||
"Null List Value", | ||
"This attribute contains a null value.", | ||
) | ||
} | ||
} | ||
} | ||
|
||
func (v noNullValuesValidator) ValidateParameterList(ctx context.Context, req function.ListParameterValidatorRequest, resp *function.ListParameterValidatorResponse) { | ||
if req.Value.IsNull() || req.Value.IsUnknown() { | ||
return | ||
} | ||
|
||
elements := req.Value.Elements() | ||
|
||
for _, e := range elements { | ||
// Only evaluate known values for null | ||
if e.IsUnknown() { | ||
continue | ||
} | ||
|
||
if e.IsNull() { | ||
resp.Error = function.ConcatFuncErrors( | ||
resp.Error, | ||
function.NewArgumentFuncError( | ||
req.ArgumentPosition, | ||
"Null List Value: This attribute contains a null value.", | ||
), | ||
) | ||
} | ||
} | ||
} | ||
|
||
// NoNullValues returns a validator which ensures that any configured list | ||
// only contains non-null values. | ||
func NoNullValues() noNullValuesValidator { | ||
return noNullValuesValidator{} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// Copyright (c) HashiCorp, Inc. | ||
// SPDX-License-Identifier: MPL-2.0 | ||
|
||
package listvalidator_test | ||
|
||
import ( | ||
"github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" | ||
"github.com/hashicorp/terraform-plugin-framework/datasource/schema" | ||
"github.com/hashicorp/terraform-plugin-framework/function" | ||
"github.com/hashicorp/terraform-plugin-framework/schema/validator" | ||
"github.com/hashicorp/terraform-plugin-framework/types" | ||
) | ||
|
||
func ExampleNoNullValues() { | ||
// Used within a Schema method of a DataSource, Provider, or Resource | ||
_ = schema.Schema{ | ||
Attributes: map[string]schema.Attribute{ | ||
"example_attr": schema.ListAttribute{ | ||
ElementType: types.StringType, | ||
Required: true, | ||
Validators: []validator.List{ | ||
// Validate this list must contain no null values. | ||
listvalidator.NoNullValues(), | ||
}, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func ExampleNoNullValues_function() { | ||
_ = function.Definition{ | ||
Parameters: []function.Parameter{ | ||
function.ListParameter{ | ||
Name: "example_param", | ||
Validators: []function.ListParameterValidator{ | ||
// Validate this list must contain no null values. | ||
listvalidator.NoNullValues(), | ||
}, | ||
}, | ||
}, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
// Copyright (c) HashiCorp, Inc. | ||
// SPDX-License-Identifier: MPL-2.0 | ||
|
||
package listvalidator_test | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" | ||
"github.com/hashicorp/terraform-plugin-framework/attr" | ||
"github.com/hashicorp/terraform-plugin-framework/function" | ||
"github.com/hashicorp/terraform-plugin-framework/path" | ||
"github.com/hashicorp/terraform-plugin-framework/schema/validator" | ||
"github.com/hashicorp/terraform-plugin-framework/types" | ||
) | ||
|
||
func TestNoNullValuesValidator(t *testing.T) { | ||
t.Parallel() | ||
|
||
type testCase struct { | ||
val types.List | ||
expectError bool | ||
} | ||
tests := map[string]testCase{ | ||
"List unknown": { | ||
val: types.ListUnknown( | ||
types.StringType, | ||
), | ||
expectError: false, | ||
}, | ||
"List null": { | ||
val: types.ListNull( | ||
types.StringType, | ||
), | ||
expectError: false, | ||
}, | ||
"No null values": { | ||
val: types.ListValueMust( | ||
types.StringType, | ||
[]attr.Value{ | ||
types.StringValue("first"), | ||
types.StringValue("second"), | ||
}, | ||
), | ||
expectError: false, | ||
}, | ||
"Unknown value": { | ||
val: types.ListValueMust( | ||
types.StringType, | ||
[]attr.Value{ | ||
types.StringValue("first"), | ||
types.StringUnknown(), | ||
}, | ||
), | ||
expectError: false, | ||
}, | ||
"Null value": { | ||
val: types.ListValueMust( | ||
types.StringType, | ||
[]attr.Value{ | ||
types.StringValue("first"), | ||
types.StringNull(), | ||
}, | ||
), | ||
expectError: true, | ||
}, | ||
} | ||
|
||
for name, test := range tests { | ||
t.Run(fmt.Sprintf("ValidateList - %s", name), func(t *testing.T) { | ||
t.Parallel() | ||
request := validator.ListRequest{ | ||
Path: path.Root("test"), | ||
PathExpression: path.MatchRoot("test"), | ||
ConfigValue: test.val, | ||
} | ||
response := validator.ListResponse{} | ||
listvalidator.NoNullValues().ValidateList(context.TODO(), request, &response) | ||
|
||
if !response.Diagnostics.HasError() && test.expectError { | ||
t.Fatal("expected error, got no error") | ||
} | ||
|
||
if response.Diagnostics.HasError() && !test.expectError { | ||
t.Fatalf("got unexpected error: %s", response.Diagnostics) | ||
} | ||
}) | ||
|
||
t.Run(fmt.Sprintf("ValidateParameterList - %s", name), func(t *testing.T) { | ||
t.Parallel() | ||
request := function.ListParameterValidatorRequest{ | ||
ArgumentPosition: 0, | ||
Value: test.val, | ||
} | ||
response := function.ListParameterValidatorResponse{} | ||
listvalidator.NoNullValues().ValidateParameterList(context.TODO(), request, &response) | ||
|
||
if response.Error == nil && test.expectError { | ||
t.Fatal("expected error, got no error") | ||
} | ||
|
||
if response.Error != nil && !test.expectError { | ||
t.Fatalf("got unexpected error: %s", response.Error) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
// Copyright (c) HashiCorp, Inc. | ||
// SPDX-License-Identifier: MPL-2.0 | ||
|
||
package mapvalidator | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/hashicorp/terraform-plugin-framework/function" | ||
"github.com/hashicorp/terraform-plugin-framework/schema/validator" | ||
) | ||
|
||
var _ validator.Map = noNullValuesValidator{} | ||
var _ function.MapParameterValidator = noNullValuesValidator{} | ||
|
||
type noNullValuesValidator struct{} | ||
|
||
func (v noNullValuesValidator) Description(_ context.Context) string { | ||
return "All values in the map must be configured" | ||
} | ||
|
||
func (v noNullValuesValidator) MarkdownDescription(ctx context.Context) string { | ||
return v.Description(ctx) | ||
} | ||
|
||
func (v noNullValuesValidator) ValidateMap(_ context.Context, req validator.MapRequest, resp *validator.MapResponse) { | ||
if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() { | ||
return | ||
} | ||
|
||
elements := req.ConfigValue.Elements() | ||
|
||
for _, e := range elements { | ||
// Only evaluate known values for null | ||
if e.IsUnknown() { | ||
continue | ||
} | ||
|
||
if e.IsNull() { | ||
resp.Diagnostics.AddAttributeError( | ||
req.Path, | ||
"Null Map Value", | ||
"This attribute contains a null value.", | ||
) | ||
} | ||
} | ||
} | ||
|
||
func (v noNullValuesValidator) ValidateParameterMap(ctx context.Context, req function.MapParameterValidatorRequest, resp *function.MapParameterValidatorResponse) { | ||
if req.Value.IsNull() || req.Value.IsUnknown() { | ||
return | ||
} | ||
|
||
elements := req.Value.Elements() | ||
|
||
for _, e := range elements { | ||
// Only evaluate known values for null | ||
if e.IsUnknown() { | ||
continue | ||
} | ||
|
||
if e.IsNull() { | ||
resp.Error = function.ConcatFuncErrors( | ||
resp.Error, | ||
function.NewArgumentFuncError( | ||
req.ArgumentPosition, | ||
"Null Map Value: This attribute contains a null value.", | ||
), | ||
) | ||
} | ||
} | ||
} | ||
|
||
// NoNullValues returns a validator which ensures that any configured map | ||
// only contains non-null values. | ||
func NoNullValues() noNullValuesValidator { | ||
return noNullValuesValidator{} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// Copyright (c) HashiCorp, Inc. | ||
// SPDX-License-Identifier: MPL-2.0 | ||
|
||
package mapvalidator_test | ||
|
||
import ( | ||
"github.com/hashicorp/terraform-plugin-framework-validators/mapvalidator" | ||
"github.com/hashicorp/terraform-plugin-framework/datasource/schema" | ||
"github.com/hashicorp/terraform-plugin-framework/function" | ||
"github.com/hashicorp/terraform-plugin-framework/schema/validator" | ||
"github.com/hashicorp/terraform-plugin-framework/types" | ||
) | ||
|
||
func ExampleNoNullValues() { | ||
// Used within a Schema method of a DataSource, Provider, or Resource | ||
_ = schema.Schema{ | ||
Attributes: map[string]schema.Attribute{ | ||
"example_attr": schema.MapAttribute{ | ||
ElementType: types.StringType, | ||
Required: true, | ||
Validators: []validator.Map{ | ||
// Validate this map must contain no null values. | ||
mapvalidator.NoNullValues(), | ||
}, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func ExampleNoNullValues_function() { | ||
_ = function.Definition{ | ||
Parameters: []function.Parameter{ | ||
function.MapParameter{ | ||
Name: "example_param", | ||
Validators: []function.MapParameterValidator{ | ||
// Validate this map must contain no null values. | ||
mapvalidator.NoNullValues(), | ||
}, | ||
}, | ||
}, | ||
} | ||
} |
Oops, something went wrong.