Skip to content

Consider only generating one custom type per associated external type #86

@bendbennett

Description

@bendbennett

Currently, the code generator iterates over the spec and generates custom type and value types for each attribute that has an associated_external_type. This could result in the generation of many custom types that provide the same functionality.

For example, given the following spec:

{
  "version": "0.1",
  "datasources": [
    {
      "name": "example",
      "schema": {
        "attributes": [
          {
            "name": "bool_attribute",
            "bool": {
              "associated_external_type": {
                "import": {
                  "path": "github.com/hashicorp/api"
                },
                "type": "*api.ExternalBool"
              },
              "computed_optional_required": "required"
            }
          },
          {
            "name": "another_bool_attribute",
            "bool": {
              "associated_external_type": {
                "import": {
                  "path": "github.com/hashicorp/api"
                },
                "type": "*api.ExternalBool"
              },
              "computed_optional_required": "required"
            }
          }
        ]
      }
    }
  ],
  "provider": {
    "name": "provider"
  }
}

The code generator will produce the following:

	return schema.Schema{
		Attributes: map[string]schema.Attribute{
			"another_bool_attribute": schema.BoolAttribute{
				CustomType: AnotherBoolAttributeType{},
				Required:   true,
			},
			"bool_attribute": schema.BoolAttribute{
				CustomType: BoolAttributeType{},
				Required:   true,
			},
		},
	}
}

type ExampleModel struct {
	AnotherBoolAttribute AnotherBoolAttributeValue `tfsdk:"another_bool_attribute"`
	BoolAttribute        BoolAttributeValue        `tfsdk:"bool_attribute"`
}

func (v AnotherBoolAttributeValue) ToApiExternalBool(ctx context.Context) (*api.ExternalBool, diag.Diagnostics) {
	var diags diag.Diagnostics

	if v.IsNull() {
		return nil, diags
	}

	if v.IsUnknown() {
		diags.Append(diag.NewErrorDiagnostic(
			"AnotherBoolAttributeValue Value Is Unknown",
			`"AnotherBoolAttributeValue" is unknown.`,
		))

		return nil, diags
	}

	a := api.ExternalBool(v.ValueBoolPointer())

	return &a, diags
}

func (v BoolAttributeValue) ToApiExternalBool(ctx context.Context) (*api.ExternalBool, diag.Diagnostics) {
	var diags diag.Diagnostics

	if v.IsNull() {
		return nil, diags
	}

	if v.IsUnknown() {
		diags.Append(diag.NewErrorDiagnostic(
			"BoolAttributeValue Value Is Unknown",
			`"BoolAttributeValue" is unknown.`,
		))

		return nil, diags
	}

	a := api.ExternalBool(v.ValueBoolPointer())

	return &a, diags
}

Consideration should be given to consolidating the generation of custom type and value types in instances where the code contained in the generated functions is essentially identical. For example:

func ExampleDataSourceSchema(ctx context.Context) schema.Schema {
	return schema.Schema{
		Attributes: map[string]schema.Attribute{
			"another_bool_attribute": schema.BoolAttribute{
				CustomType: BoolAttributeType{},
				Required:   true,
			},
			"bool_attribute": schema.BoolAttribute{
				CustomType: BoolAttributeType{},
				Required:   true,
			},
		},
	}
}

type ExampleModel struct {
	AnotherBoolAttribute BoolAttributeValue `tfsdk:"another_bool_attribute"`
	BoolAttribute        BoolAttributeValue `tfsdk:"bool_attribute"`
}

func (v BoolAttributeValue) ToApiExternalBool(ctx context.Context) (*api.ExternalBool, diag.Diagnostics) {
	var diags diag.Diagnostics

	if v.IsNull() {
		return nil, diags
	}

	if v.IsUnknown() {
		diags.Append(diag.NewErrorDiagnostic(
			"BoolAttributeValue Value Is Unknown",
			`"BoolAttributeValue" is unknown.`,
		))

		return nil, diags
	}

	a := api.ExternalBool(v.ValueBoolPointer())

	return &a, diags
}

Handling of the generation of attribute-specific diagnostics would require further consideration under these circumstances, for example:

	if v.IsUnknown() {
		diags.Append(diag.NewErrorDiagnostic(
			"BoolAttributeValue Value Is Unknown",
			`"BoolAttributeValue" is unknown.`,
		))

		return nil, diags
	}

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