Skip to content

Latest commit

 

History

History
177 lines (156 loc) · 8.24 KB

File metadata and controls

177 lines (156 loc) · 8.24 KB
page_title description
Attribute predefined validators: Migrating from SDKv2 to the Framework
Validations check required syntax, types, and acceptable values. Migrate the predefined ConflictsWith, ExactlyOneOf, AtLeastOneOf and RequiredWith validators to the Framework.

Validators - Predefined

Attribute validators ensure that attributes do or do not contain specific values. You can use predefined validators for many use cases, or implement custom validators. Refer to Schemas - Validators in the Framework documentation for details. Refer to the Attributes - Custom Validators page in this guide to learn how to implement custom validators.

This page explains how to migrate a predefined validator from SDKv2 to the Framework.

SDKv2

In SDKv2, the ConflictsWith, ExactlyOneOf, AtLeastOneOf, and RequiredWith fields on an attribute's schema.Schema struct perform predefined validations on the list of attributes set for these fields.

func resourceExample() *schema.Resource {
    return &schema.Resource{
        /* ... */
        Schema: map[string]*schema.Schema{
            "attribute_example": {
                ConflictsWith:  []string{ /* ... */ },
                ExactlyOneOf:   []string{ /* ... */ },
                AtLeastOneOf:   []string{ /* ... */ },
                RequiredWith:   []string{ /* ... */ },
            /* ... */

Framework

In the Framework, you implement either type of validation by setting the Validators field on the schema.Attribute implementation. Validators that perform the same checks as the predefined validators in SDKv2 are available for the Framework. If the predefined validators do not meet your needs, you must define custom validators.

func (r *resourceExample) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
    resp.Schema = schema.Schema{
        /* ... */
        Attributes: map[string]schema.Attribute{
            "attribute_example": schema.StringAttribute{
                Validators: []validator.String{
                    stringvalidator.ConflictsWith( /* ... */ ),
                    /* ... */

Configuration validators can also be defined for providers, resources and data sources by implementing ProviderWithConfigValidators, ResourceWithConfigValidators, and DataSourceWithConfigValidators interfaces, respectively.

func (r *resourceExample) ConfigValidators(ctx context.Context) []resource.ConfigValidator {
    return []resource.ConfigValidator{
        resourcevalidator.Conflicting(
            /* ... */
        ),
        /* ... */

Migration Notes

Remember the following details when migrating from SDKv2 to the Framework.

  • In SDKv2, ValidateDiagFunc is a field on schema.Schema that you can use to define validation functions. In SDKv2, there are also built-in validations. For example, ConflictsWith is a field on the schema.Schema struct in SDKv2. In the Framework, Validators is a field on each schema.Attribute implementation.
  • Validators replicating the behavior of ConflictsWith, ExactlyOneOf, AtLeastOneOf, and RequiredWith in SDKv2 are available for the Framework in each of the type-specific packages of terraform-plugin-framework-validators.
  • Define custom validators when the predefined validators do not meet your requirements.

Example

SDKv2

The following example shows the implementation of the ConflictsWith field on the provider's example_block block's example_attribute_one attribute. This validator checks that the provider does not use the example_attribute_one attribute when the example_attribute_four is being used. The example also uses the RequiredWith field to ensure that the example_attribute_two attribute is configured when example_attribute_one is, and that the example_attribute_three attribute is configured when example_attribute_two is.

func New() (*schema.Provider, error) {
    return &schema.Provider{
        Schema: map[string]*schema.Schema{
            "example_block": {
                Elem: &schema.Resource{
                    Schema: map[string]*schema.Schema{
                        "example_attribute_one": {
                            ConflictsWith: []string{"example_block.0.example_attribute_four"},
                            /* ... */
                        },
                        "example_attribute_two": {
                            RequiredWith: []string{"example_block.0.example_attribute_one"},
                            /* ... */
                        },
                        "example_attribute_three": {
                            RequiredWith: []string{"example_block.0.example_attribute_two"},
                            /* ... */
                        },
                        "example_attribute_four": {
                            ConflictsWith: []string{
                                "example_block.0.example_attribute_one",
                                "example_block.0.example_attribute_two",
                                "example_block.0.example_attribute_three",
                            },
                            /* ... */
                        },
                    },
                },
            },
        },
    }, nil
}

Framework

The following shows the same section of provider code after the migration.

This code implements the ConflictsWith and AlsoRequires validators with the Framework. The validators are configured via the Validators field of the provider's example_block block's attribute schema.

func (p *TlsProvider) Schema(_ context.Context, _ provider.SchemaRequest, resp *provider.SchemaResponse) {
    resp.Schema = schema.Schema{
        Blocks: map[string]schema.Block{
            "example_block": schema.ListNestedBlock{
                NestedObject: schema.NestedBlockObject{
                    Attributes: map[string]schema.Attribute{
                        "example_attribute_one": schema.StringAttribute{
                            Validators: []validator.String{
                                stringvalidator.ConflictsWith(path.MatchRelative().AtParent().AtName("example_attribute_four")),
                            },
                            /* ... */
                        },
                        "example_attribute_two": schema.StringAttribute{
                            Validators: []validator.String{
                                stringvalidator.AlsoRequires(path.MatchRelative().AtParent().AtName("example_attribute_one")),
                            },
                            /* ... */
                        },
                        "example_attribute_three": schema.StringAttribute{
                            Validators: []validator.String{
                                stringvalidator.AlsoRequires(path.MatchRelative().AtParent().AtName("example_attribute_two")),
                            },
                            /* ... */
                        },
                        "example_attribute_four": schema.BoolAttribute{
                            Validators: []validator.Bool{
                                boolvalidator.ConflictsWith(
                                    path.MatchRelative().AtParent().AtName("example_attribute_one"),
                                    path.MatchRelative().AtParent().AtName("example_attribute_two"),
                                    path.MatchRelative().AtParent().AtName("example_attribute_three"),
                                ),
                            },
                            /* ... */
                        },
                    },
                },
            },
    }
}