Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consider documenting how to share schema between resources and data resources #673

Open
remyleone opened this issue Feb 16, 2023 · 2 comments
Labels
enhancement New feature or request

Comments

@remyleone
Copy link
Contributor

Use-cases

When developing a resource that is evolving during time it could be cumbersome to duplicate fields twice between resource schema and data resource schema. Could it be possible to have a way to have a common abstraction between the two and customize only the changing parts?

Attempted Solutions

We currently use a code similar to this with SDKv2 but I was wondering if terraform framework could do it more natively?

////
// The below methods are imported from Google's terraform provider.
// source: https://github.com/terraform-providers/terraform-provider-google/blob/master/google/datasource_helpers.go
////

// datasourceSchemaFromResourceSchema is a recursive func that
// converts an existing Resource schema to a Datasource schema.
// All schema elements are copied, but certain attributes are ignored or changed:
// - all attributes have Computed = true
// - all attributes have ForceNew, Required = false
// - Validation funcs and attributes (e.g. MaxItems) are not copied
func datasourceSchemaFromResourceSchema(rs map[string]*schema.Schema) map[string]*schema.Schema {
	ds := make(map[string]*schema.Schema, len(rs))
	for k, v := range rs {
		dv := &schema.Schema{
			Computed:    true,
			ForceNew:    false,
			Description: v.Description,
			Type:        v.Type,
		}

		switch v.Type {
		case schema.TypeSet:
			dv.Set = v.Set
			fallthrough
		case schema.TypeList:
			// List & Set types are generally used for 2 cases:
			// - a list/set of simple primitive values (e.g. list of strings)
			// - a sub resource
			if elem, ok := v.Elem.(*schema.Resource); ok {
				// handle the case where the Element is a sub-resource
				dv.Elem = &schema.Resource{
					Schema: datasourceSchemaFromResourceSchema(elem.Schema),
				}
			} else {
				// handle simple primitive case
				dv.Elem = v.Elem
			}

		default:
			// Elem of all other types are copied as-is
			dv.Elem = v.Elem
		}
		ds[k] = dv
	}
	return ds
}

Proposal

Having a standard way or at least patterns and helper functions that are common between data resources and resources. Otherwise it is going to be tedious to duplicate fields and changing whether they are computed or not.

References

@remyleone remyleone added the enhancement New feature or request label Feb 16, 2023
@bflad
Copy link
Contributor

bflad commented Feb 16, 2023

Related: #568

@grenader
Copy link

This is exactly what we need

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants