Skip to content

Commit dee0dd6

Browse files
authored
TFECO-9166: Add support for ResourceIdentity#SchemaFunc to allow providers to save RAM (#1459)
* Add support for ResourceIdentity#SchemaFunc to allow providers to save RAM * handle nil ResourceIdentity for SchemaMap() and simplify code
1 parent 6666040 commit dee0dd6

File tree

6 files changed

+65
-49
lines changed

6 files changed

+65
-49
lines changed

helper/schema/core_schema.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -389,11 +389,11 @@ func (r *Resource) CoreIdentitySchema() (*configschema.Block, error) {
389389
}
390390

391391
func (r *Resource) coreIdentitySchema() (*configschema.Block, error) {
392-
if r.Identity == nil || r.Identity.Schema == nil {
392+
if r.Identity.SchemaMap() == nil {
393393
return nil, fmt.Errorf("resource does not have an identity schema")
394394
}
395395
// while there is schemaMapWithIdentity, we don't need to use it here
396396
// as we're only interested in the existing CoreConfigSchema() method
397397
// to convert our schema
398-
return schemaMap(r.Identity.Schema).CoreConfigSchema(), nil
398+
return schemaMap(r.Identity.SchemaMap()).CoreConfigSchema(), nil
399399
}

helper/schema/grpc_provider_test.go

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3319,25 +3319,27 @@ func TestGRPCProviderServerGetResourceIdentitySchemas(t *testing.T) {
33193319
},
33203320
"test_resource2": {
33213321
Identity: &ResourceIdentity{
3322-
Schema: map[string]*Schema{
3323-
"test2": {
3324-
Type: TypeString,
3325-
RequiredForImport: false,
3326-
OptionalForImport: true,
3327-
Description: "test resource 2",
3328-
},
3329-
"test2-2": {
3330-
Type: TypeList,
3331-
RequiredForImport: false,
3332-
OptionalForImport: true,
3333-
Description: "test resource 2-2",
3334-
},
3335-
"test2-3": {
3336-
Type: TypeInt,
3337-
RequiredForImport: false,
3338-
OptionalForImport: true,
3339-
Description: "test resource 2-3",
3340-
},
3322+
SchemaFunc: func() map[string]*Schema {
3323+
return map[string]*Schema{
3324+
"test2": {
3325+
Type: TypeString,
3326+
RequiredForImport: false,
3327+
OptionalForImport: true,
3328+
Description: "test resource 2",
3329+
},
3330+
"test2-2": {
3331+
Type: TypeList,
3332+
RequiredForImport: false,
3333+
OptionalForImport: true,
3334+
Description: "test resource 2-2",
3335+
},
3336+
"test2-3": {
3337+
Type: TypeInt,
3338+
RequiredForImport: false,
3339+
OptionalForImport: true,
3340+
Description: "test resource 2-3",
3341+
},
3342+
}
33413343
},
33423344
},
33433345
},

helper/schema/resource.go

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -728,11 +728,7 @@ func (r *Resource) ShimInstanceStateFromValue(state cty.Value) (*terraform.Insta
728728

729729
// We now rebuild the state through the ResourceData, so that the set indexes
730730
// match what helper/schema expects.
731-
var identity map[string]*Schema
732-
if r.Identity != nil {
733-
identity = r.Identity.Schema
734-
}
735-
data, err := schemaMapWithIdentity{r.SchemaMap(), identity}.Data(s, nil)
731+
data, err := schemaMapWithIdentity{r.SchemaMap(), r.Identity.SchemaMap()}.Data(s, nil)
736732
if err != nil {
737733
return nil, err
738734
}
@@ -905,11 +901,7 @@ func (r *Resource) Apply(
905901
s *terraform.InstanceState,
906902
d *terraform.InstanceDiff,
907903
meta interface{}) (*terraform.InstanceState, diag.Diagnostics) {
908-
var identity map[string]*Schema
909-
if r.Identity != nil {
910-
identity = r.Identity.Schema
911-
}
912-
schema := schemaMapWithIdentity{r.SchemaMap(), identity}
904+
schema := schemaMapWithIdentity{r.SchemaMap(), r.Identity.SchemaMap()}
913905
data, err := schema.Data(s, d)
914906
if err != nil {
915907
return s, diag.FromErr(err)
@@ -1033,12 +1025,8 @@ func (r *Resource) SimpleDiff(
10331025
c *terraform.ResourceConfig,
10341026
meta interface{}) (*terraform.InstanceDiff, error) {
10351027

1036-
var identity map[string]*Schema
1037-
if r.Identity != nil {
1038-
identity = r.Identity.Schema
1039-
}
10401028
// TODO: figure out if it makes sense to be able to set identity in CustomizeDiff at all
1041-
instanceDiff, err := schemaMapWithIdentity{r.SchemaMap(), identity}.Diff(ctx, s, c, r.CustomizeDiff, meta, false)
1029+
instanceDiff, err := schemaMapWithIdentity{r.SchemaMap(), r.Identity.SchemaMap()}.Diff(ctx, s, c, r.CustomizeDiff, meta, false)
10421030
if err != nil {
10431031
return instanceDiff, err
10441032
}
@@ -1127,11 +1115,7 @@ func (r *Resource) RefreshWithoutUpgrade(
11271115
}
11281116
}
11291117

1130-
var identity map[string]*Schema
1131-
if r.Identity != nil {
1132-
identity = r.Identity.Schema
1133-
}
1134-
schema := schemaMapWithIdentity{r.SchemaMap(), identity}
1118+
schema := schemaMapWithIdentity{r.SchemaMap(), r.Identity.SchemaMap()}
11351119

11361120
if r.Exists != nil {
11371121
// Make a copy of data so that if it is modified it doesn't
@@ -1442,7 +1426,7 @@ func (r *Resource) Data(s *terraform.InstanceState) *ResourceData {
14421426
func (r *Resource) TestResourceData() *ResourceData {
14431427
return &ResourceData{
14441428
schema: r.SchemaMap(),
1445-
identitySchema: r.Identity.Schema,
1429+
identitySchema: r.Identity.SchemaMap(),
14461430
}
14471431
}
14481432

@@ -1489,11 +1473,11 @@ func (r *ResourceIdentity) InternalIdentityValidate() error {
14891473
return fmt.Errorf(`The resource identity is empty`)
14901474
}
14911475

1492-
if len(r.Schema) == 0 {
1476+
if len(r.SchemaMap()) == 0 {
14931477
return fmt.Errorf(`The resource identity schema is empty`)
14941478
}
14951479

1496-
for k, v := range r.Schema {
1480+
for k, v := range r.SchemaMap() {
14971481
if !v.OptionalForImport && !v.RequiredForImport {
14981482
return fmt.Errorf(`OptionalForImport or RequiredForImport must be set for resource identity`)
14991483
}

helper/schema/resource_identity.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ type ResourceIdentity struct {
3737
// previous resource schemas.
3838
Schema map[string]*Schema
3939

40+
// SchemaFunc is an optional function that returns the schema for the
41+
// identity. Use this field instead of Schema on resource identity
42+
// declarations to prevent storing all identity schema information in
43+
// memory for the lifecycle of a provider.
44+
SchemaFunc func() map[string]*Schema
45+
4046
// New struct, will be similar to (Resource).StateUpgraders
4147
IdentityUpgraders []IdentityUpgrader
4248
}
@@ -70,3 +76,18 @@ type ResourceIdentity struct {
7076
// identity schema version data for a managed resource instance. Values must
7177
// align to the typing mentioned above.
7278
type ResourceIdentityUpgradeFunc func(ctx context.Context, rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error)
79+
80+
// SchemaMap returns the schema information for this Resource whether it is
81+
// defined via the SchemaFunc field or Schema field. The SchemaFunc field, if
82+
// defined, takes precedence over the Schema field.
83+
func (ri *ResourceIdentity) SchemaMap() map[string]*Schema {
84+
if ri == nil {
85+
return nil
86+
}
87+
88+
if ri.SchemaFunc != nil {
89+
return ri.SchemaFunc()
90+
}
91+
92+
return ri.Schema
93+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package schema
5+
6+
import "testing"
7+
8+
func TestResourceIdentity_SchemaMap_handles_nil_identity(t *testing.T) {
9+
var ri *ResourceIdentity
10+
if ri.SchemaMap() != nil {
11+
t.Fatal("expected nil schema map")
12+
}
13+
}

helper/schema/shims.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,7 @@ func diffFromValues(ctx context.Context, prior, planned, config cty.Value, res *
4343
removeConfigUnknowns(cfg.Config)
4444
removeConfigUnknowns(cfg.Raw)
4545

46-
var identity map[string]*Schema
47-
if res.Identity != nil {
48-
identity = res.Identity.Schema
49-
}
50-
diff, err := schemaMapWithIdentity{res.SchemaMap(), identity}.Diff(ctx, instanceState, cfg, cust, nil, false)
46+
diff, err := schemaMapWithIdentity{res.SchemaMap(), res.Identity.SchemaMap()}.Diff(ctx, instanceState, cfg, cust, nil, false)
5147
if err != nil {
5248
return nil, err
5349
}

0 commit comments

Comments
 (0)