goterraformterraform-provider

how to implement this terraform schema?


I'm using the terraform-plugin-framework.

This is a contrived example, but say I have a resource like:

type R struct {

IsAdmin types.Bool `tfsdk:"isAdmin"`

F1 types.String `tfsdk:"f1"`

}

How do I define a schema such that:

a. if IsAdmin is true, F1 must be empty string

b. if IsAdmin is false, F1 must not be empty string

A simple way would be set F1 as Optional in schema, then in say Create handler do validation there. I don't think this is the right way. Shouldn't Schema function do this ?


Solution

  • You can accomplish this with ValidateConfig:

    func (_ *RResource) ValidateConfig(ctx context.Context, req resource.ValidateConfigRequest, resp *resource.ValidateConfigResponse) {
      // determine input values
      var state R
      resp.Diagnostics.Append(req.Config.Get(ctx, &state)...)
      if resp.Diagnostics.HasError() {
        return
      }
    
      // return if either field member/attribute is unknown
      if state.IsAdmin.IsUnknown() || state.F1.IsUnknown() {
        return
      }
    
      // validate F1
      if state.IsAdmin.ValueBool() && len(state.F1.ValueString()) > 0 {
        resp.Diagnostics.AddAttributeError(
          path.Root("f1"),
          "Invalid Attribute Value",
          "Parameter 'f1' cannot be assigned a value if parameter isAdmin is assigned a value of 'true'",
        )
      } else {
        if !state.IsAdmin.ValueBool() && len(state.F1.ValueString()) == 0 {
          resp.Diagnostics.AddAttributeError(
            path.Root("f1"),
            "Invalid Attribute Value",
            "Parameter 'f1' must be assigned a value if parameter isAdmin is assigned a value of 'false'",
          )
        }
      }
    }
    

    This solution makes the assumption that the attribute schema for the resource follows the typical convention of lowercase for the data model struct field members as it was not shared in the question.

    Normally it would be easier to accomplish multiple resource attribute validation with the resource validator, but in your situation the above would be easier and cleaner.