Validation of NestedAttributeObject attributes

Given the following schema, I’ve assumed that the validators would check if only one of attributes is set in the .hcl file:

rsschema.NestedAttributeObject{
		Validators: []validator.Object{
			objectvalidator.ExactlyOneOf(path.Expressions{
				path.MatchRelative().AtName("ip_netmask"),
				path.MatchRelative().AtName("ip_range"),
				path.MatchRelative().AtName("fqdn"),
				path.MatchRelative().AtName("ip_wildcard"),
			}...),
		},
		Attributes: map[string]rsschema.Attribute{
			"ip_netmask": rsschema.StringAttribute{
				Description: "The IP netmask value.",
				Computed:    false,
				Required:    false,
				Optional:    true,
				Sensitive:   false,
			},

			"ip_range": rsschema.StringAttribute{
				Description: "The IP range value.",
				Computed:    false,
				Required:    false,
				Optional:    true,
				Sensitive:   false,
			},

			"fqdn": rsschema.StringAttribute{
				Description: "The FQDN value.",
				Computed:    false,
				Required:    false,
				Optional:    true,
				Sensitive:   false,
			},

			"ip_wildcard": rsschema.StringAttribute{
				Description: "The IP wildcard value.",
				Computed:    false,
				Required:    false,
				Optional:    true,
				Sensitive:   false,
			},
		},
	}

But that doesn’t seem to be the case, I get errors even if only ip_netmask is set:

│ Error: Invalid Attribute Combination
│ 
│   with example_address_objects.google_dns_servers,
│   on main.tf line 185, in resource "example_address_objects" "google_dns_servers":
│  185:     "google-dns-secondary" = {
│ 
│ 2 attributes specified when one (and only one) of
│ [addresses["google-dns-secondary"].ip_netmask,addresses["google-dns-secondary"].ip_range,addresses["google-dns-secondary"].fqdn,addresses["google-dns-secondary"].ip_wildcard]
│ is required

I can move Validators into one of the attributes, and that works as expected.

The validator considers itself against the caller-specified path.Expressions.

Putting the validator on the Object and enumerating several attributes within that object is saying:

Exactly one of:

  • this object
  • this object’s attribute ip_netmask
  • this object’s attribute ip_range
  • this object’s attribute fqdn
  • this object’s attribute ip_wildcard

…which doesn’t make any sense.

A validator.Object which only considers exclusive child attributes of that object would be reasonable, but I don’t know of one.

This validator’s behavior makes sense if you consider a requirement for specifying exclusivity between top-level attributes. With no parent, we need to put it directly on the attributes.

I can move Validators into one of the attributes, and that works as expected.

Yep, that’s what I do. It always bothers me a little: Specifying exclusivity between attributes A/B/C only on attribute A feels a little funny.