Skip to content

Proposal: Child attribute validators for Objects #274

Open
@gdavison

Description

@gdavison

Terraform CLI and Framework Versions

All

Use Cases or Problem Statement

Currently, there isn't a standard method for cleanly validating the child members of an Object. For example, to require exactly one of a set of attributes we need add an ExactlyOneOf validator on one of the child attributes, as below. Until #118 is resolved, we also have to add path.MatchRelative() as a self-reference.

func (r *resourceBucketLifecycleConfiguration) Schema(ctx context.Context, request resource.SchemaRequest, response *resource.SchemaResponse) {
	response.Schema = schema.Schema{
		Version: 1,
		Attributes: map[string]schema.Attribute{
			// ...
		},
		Blocks: map[string]schema.Block{
			names.AttrRule: schema.ListNestedBlock{
				CustomType: fwtypes.NewListNestedObjectTypeOf[lifecycleRuleModel](ctx),
				Validators: []validator.List{
					listvalidator.SizeAtLeast(1),
				},
				NestedObject: schema.NestedBlockObject{
					Attributes: map[string]schema.Attribute{
						// ...
					},
					Blocks: map[string]schema.Block{
						// ...
						"expiration": schema.ListNestedBlock{
							CustomType: fwtypes.NewListNestedObjectTypeOf[lifecycleExpirationModel](ctx),
							Validators: []validator.List{
								listvalidator.SizeAtMost(1),
							},
							NestedObject: schema.NestedBlockObject{
								Attributes: map[string]schema.Attribute{
									"date": schema.StringAttribute{
										CustomType: timetypes.RFC3339Type{},
										Optional:   true,
									},
									"days": schema.Int32Attribute{
										Optional: true,
										Validators: []validator.Int32{
											int32validator.AtLeast(1),
										},
									},
									"expired_object_delete_marker": schema.BoolAttribute{
										Optional: true,
										Validators: []validator.Bool{
                      boolvalidator.ExactlyOneOf(
                        path.MatchRelative(), // Required until #118 is addressed
                        path.MatchRelative().AtParent().AtName("date"),
                        path.MatchRelative().AtParent().AtName("days"),
                      ),
										},
									},
								},
							},
						},
						// ...
					},
				},
			},
		},
	}
}

However, the error message displayed is

No attribute specified when one (and only one) of
[rule[0].expiration[0].expired_object_delete_marker,rule[0].expiration[0].expired_object_delete_marker.<.date,rule[0].expiration[0].expired_object_delete_marker.<.days]

which is hard to read, especially the references to the attributes with the AtParent relationship, such as rule[0].expiration[0].expired_object_delete_marker.<.days. I would also recommend adding a space after the , and possibly demarcate the individual attributes with some form of quotation marks.

Using objectvalidator.ExactlyOneOf on the Object includes the object itself in the count, so cannot be used.

Proposal

Add validators such as objectvalidator.ExactlyOneOfChildren which would act like the non-Children version but not count itself. For example, in the case above, the following validator would be set on the Object

objectvalidator.ExactlyOneOfChildren(
    path.MatchRelative().AtName("date"),
    path.MatchRelative().AtName("days"),
    path.MatchRelative().AtName("expired_object_delete_marker"),
)

Additional Information

No response

Code of Conduct

  • I agree to follow this project's Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions