-
Notifications
You must be signed in to change notification settings - Fork 99
Description
Module version
v1.2.0
Use-cases
There are times when we want to define multiple distinct SingleNestedBlocks, and would like to make those blocks optional.
In conjunction, there are also cases where we would like to make some attributes of the SingleNestedBlock required.
Here's a specific example of definitions:
schema.Schema{
Blocks: map[string]schema.Block{
"block1": schema.SingleNestedBlock{
Validators: []validator.Object{
objectvalidator.ExactlyOneOf(path.Expressions{
path.MatchRoot("block1"),
path.MatchRoot("block2"),
}...),
},
Attributes: map[string]schema.Attribute{
"attrA": schema.StringAttribute{
Required: true,
},
},
},
"block2": schema.SingleNestedBlock{
Validators: []validator.Object{
objectvalidator.ExactlyOneOf(path.Expressions{
path.MatchRoot("block1"),
path.MatchRoot("block2"),
}...),
},
Attributes: map[string]schema.Attribute{
"attrB": schema.StringAttribute{
Optional: true,
},
},
},
}
}resource "test_resource" "example" {
block2 {
attrB = "exmaple"
}
}However, due to the current specification of SingleNestedBlock, if one or more attributes of the block we want to make optional are required, the parent block also functions as if it were required.
Error: Missing Configuration for Required Attribute
with test_resource.example,
on terraform_plugin_test.tf line 2, in resource "test_resource" "example":
2: resource "test_resource" "example" {
Must set a configuration value for the block1.attrA attribute as the
provider has marked it as required.
Attempted Solutions
schema.Schema{
Blocks: map[string]schema.Block{
"block1": schema.ListNestedBlock{
Validators: []validator.List{
listvalidator.ExactlyOneOf(path.Expressions{
path.MatchRoot("block1"),
path.MatchRoot("block2"),
}...),
listvalidator.SizeAtMost(1),
},
NestedObject: schema.NestedBlockObject{
Attributes: map[string]schema.Attribute{
"attrA": schema.StringAttribute{
Required: true,
},
},
},
},
"block2": schema.SingleNestedBlock{
Validators: []validator.Object{
objectvalidator.ExactlyOneOf(path.Expressions{
path.MatchRoot("block1"),
path.MatchRoot("block2"),
}...),
},
},
}
}This use case can be achieved by using ListNestedBlock. However, for users who will end up using this provider, the internal implementation as a list, such as test_resource.example.block1[0], leaks into the resource interface. This is not a favorable situation for users.
Proposal
type SingleNestedBlock struct {
// ... existing methods ...
Required: bool,
Optional: bool,
}For instance, it could be considered to prepare an attribute that determines whether the SingleNestedBlock is optional or not. If it's optional, then the requirement of the child attributes could be ignored.