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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions