Skip to content

Commit 7fca700

Browse files
authored
Merge branch 'FEATURE-BRANCH-resource-identity' into sync-main-dec-8-FEATURE-BRANCH-resource-identity
2 parents e05a490 + 81d3031 commit 7fca700

File tree

14 files changed

+234
-15
lines changed

14 files changed

+234
-15
lines changed

mmv1/api/resource.go

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,11 @@ type Resource struct {
249249
// used for maintaining state stability with resources first provisioned on older api versions.
250250
SchemaVersion int `yaml:"schema_version,omitempty"`
251251

252+
// The version of the identity schema for the resource.
253+
IdentitySchemaVersion int `yaml:"identity_schema_version,omitempty"`
254+
255+
IdentityUpgraders bool `yaml:"identity_upgraders,omitempty"`
256+
252257
// From this schema version on, state_upgrader code is generated for the resource.
253258
// When unset, state_upgrade_base_schema_version defauts to 0.
254259
// Normally, it is not needed to be set.
@@ -660,6 +665,32 @@ func (r Resource) AllNestedProperties(props []*Type) []*Type {
660665
return nested
661666
}
662667

668+
func (r Resource) IdentityProperties() []*Type {
669+
props := make([]*Type, 0)
670+
importFormat := r.ExtractIdentifiers(ImportIdFormats(r.ImportFormat, r.Identity, r.BaseUrl)[0])
671+
optionalValues := map[string]bool{"project": false, "zone": false, "region": false}
672+
for _, p := range r.AllProperties() {
673+
if slices.Contains(importFormat, google.Underscore(p.Name)) {
674+
props = append(props, p)
675+
optionalValues[p.Name] = true
676+
}
677+
}
678+
679+
for _, field := range []string{"project", "zone", "region"} { // prevents duplicates
680+
if slices.Contains(importFormat, field) && !optionalValues[field] {
681+
props = append(props, &Type{Name: field, Type: "string"})
682+
}
683+
}
684+
685+
if len(r.CustomCode.CustomIdentity) > 0 {
686+
for _, fieldName := range r.CustomCode.CustomIdentity {
687+
props = append(props, &Type{Name: google.Underscore(fieldName), Type: "string", Required: true})
688+
}
689+
}
690+
691+
return props
692+
}
693+
663694
func (r Resource) SensitiveProps() []*Type {
664695
props := r.AllNestedProperties(r.RootProperties())
665696
return google.Select(props, func(p *Type) bool {
@@ -1089,6 +1120,10 @@ func (r Resource) StateMigrationFile() string {
10891120
return fmt.Sprintf("templates/terraform/state_migrations/%s_%s.go.tmpl", google.Underscore(r.ProductMetadata.Name), google.Underscore(r.Name))
10901121
}
10911122

1123+
func (r Resource) IdentityUpgraderFile() string {
1124+
return fmt.Sprintf("templates/terraform/identity_upgraders/%s_%s.go.tmpl", google.Underscore(r.ProductMetadata.Name), google.Underscore(r.Name))
1125+
}
1126+
10921127
// ====================
10931128
// Version-related methods
10941129
// ====================
@@ -1348,7 +1383,6 @@ func ImportIdFormats(importFormat, identity []string, baseUrl string) []string {
13481383
// short id: {{project}}/{{zone}}/{{name}}
13491384
fieldMarkers := regexp.MustCompile(`{{[[:word:]]+}}`).FindAllString(idFormats[0], -1)
13501385
shortIdFormat := strings.Join(fieldMarkers, "/")
1351-
13521386
// short ids without fields with provider-level defaults:
13531387

13541388
// without project
@@ -1394,6 +1428,7 @@ func ImportIdFormats(importFormat, identity []string, baseUrl string) []string {
13941428
uniq = google.Reject(slices.Compact(uniq), func(i string) bool {
13951429
return i == ""
13961430
})
1431+
13971432
return uniq
13981433
}
13991434

@@ -2153,6 +2188,21 @@ func (r Resource) StateUpgradersCount() []int {
21532188
return nums
21542189
}
21552190

2191+
func (r Resource) IdentityUpgradersCount() []int {
2192+
var nums []int
2193+
for i := 1; i < r.IdentitySchemaVersion; i++ {
2194+
nums = append(nums, i)
2195+
}
2196+
return nums
2197+
}
2198+
2199+
func (r Resource) GetIdentitySchemaVersion() int {
2200+
if r.IdentitySchemaVersion == 0 { // default to 1 if not set; a resource with no identity support has a version of 0
2201+
return 1
2202+
}
2203+
return r.IdentitySchemaVersion
2204+
}
2205+
21562206
func (r Resource) CaiProductBaseUrl() string {
21572207
return r.ProductMetadata.ServiceBaseUrl()
21582208
}

mmv1/api/resource/custom_code.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,10 @@ type CustomCode struct {
128128
// inserts that for you - do not include it in your custom code.
129129
CustomImport string `yaml:"custom_import,omitempty"`
130130

131+
// This code replaces the entire identity schema method. Since the identity schema method's function header can't be changed, the template
132+
// inserts that for you - do not include it in your custom code.
133+
CustomIdentity []string `yaml:"custom_identity,omitempty"`
134+
131135
// This code is run just after the import method succeeds - it
132136
// is useful for parsing attributes that are necessary for
133137
// the Read() method to succeed.

mmv1/products/apigee/AddonsConfig.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ async:
4141
custom_code:
4242
custom_import: 'templates/terraform/custom_import/apigee_addons.go.tmpl'
4343
test_check_destroy: 'templates/terraform/custom_check_destroy/apigee_addons_override.go.tmpl'
44+
custom_identity:
45+
- 'org'
4446
examples:
4547
- name: 'apigee_addons_basic'
4648
exclude_test: true

mmv1/products/iap/Brand.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ identity:
5757
- name
5858
custom_code:
5959
custom_import: 'templates/terraform/custom_import/iap_brand.go.tmpl'
60+
custom_identity:
61+
- 'project'
6062
examples:
6163
- name: 'iap_brand'
6264
primary_resource_id: 'project_brand'

mmv1/templates/terraform/examples/base_configs/test_file.go.tmpl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,12 @@ func TestAcc{{ $e.TestSlug $.Res.ProductMetadata.Name $.Res.Name }}(t *testing.T
110110
ImportStateVerifyIgnore: {{ $.Res.IgnoreReadPropertiesToStringLegacy $e }},
111111
{{- end }}
112112
},
113+
{
114+
ResourceName: "{{ $.Res.TerraformName }}.{{ $e.PrimaryResourceId }}",
115+
RefreshState: true,
116+
ExpectNonEmptyPlan: true,
117+
ImportStateKind: resource.ImportBlockWithResourceIdentity,
118+
},
113119
{{- end }}
114120
},
115121
})

mmv1/templates/terraform/resource.go.tmpl

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,34 @@ func Resource{{ $.ResourceName -}}() *schema.Resource {
163163
DeprecationMessage: "{{ $.DeprecationMessage -}}",
164164
{{- end}}
165165

166+
Identity: &schema.ResourceIdentity{
167+
Version: {{ $.GetIdentitySchemaVersion }},
168+
SchemaFunc: func() map[string]*schema.Schema {
169+
return map[string]*schema.Schema{
170+
{{- range $p := .IdentityProperties }}
171+
"{{ underscore $p.Name}}": {
172+
Type: schema.TypeString,
173+
{{- if or $p.Required $p.Output }}
174+
RequiredForImport: true,
175+
{{- else }}
176+
OptionalForImport: true,
177+
{{- end }}
178+
},
179+
{{- end }}
180+
}
181+
},
182+
{{- if $.IdentityUpgraders }}
183+
IdentityUpgraders: []schema.IdentityUpgrader{
184+
{{- range $v := $.IdentityUpgradersCount }}
185+
{
186+
Type: identity{{ $.ResourceName }}ResourceV{{$v}}(),
187+
Upgrade: Identity{{ $.ResourceName }}UpgradeV{{$v}},
188+
Version: {{$v}},
189+
},
190+
{{- end }}
191+
},
192+
{{- end }}
193+
},
166194
Schema: map[string]*schema.Schema{
167195
{{- range $prop := $.OrderProperties $.AllUserProperties }}
168196
{{template "SchemaFields" $prop -}}
@@ -718,8 +746,21 @@ func resource{{ $.ResourceName -}}Read(d *schema.ResourceData, meta interface{})
718746
}
719747
{{- end}}
720748

749+
identity, err := d.Identity()
750+
if err != nil && identity != nil {
751+
{{- range $p := $.IdentityProperties }}
752+
if v, ok := identity.GetOk("{{ underscore $p.Name}}"); ok && v != "" {
753+
err = identity.Set("{{ underscore $p.Name}}", d.Get("{{ underscore $p.Name}}").(string))
754+
if err != nil {
755+
return fmt.Errorf("Error setting {{ underscore $p.Name}}: %s", err)
756+
}
757+
}
758+
{{- end }}
759+
} else {
760+
log.Printf("[DEBUG] identity not set: %s", err)
761+
}
762+
{{- end }}
721763
return nil
722-
{{ end -}}
723764
}
724765

725766
{{if $.Updatable -}}
@@ -1254,6 +1295,12 @@ func resource{{ $.ResourceName -}}PostCreateFailure(d *schema.ResourceData, meta
12541295

12551296
{{ customTemplate $ $.StateMigrationFile false -}}
12561297
{{- end }}
1298+
1299+
{{- if and $.IdentitySchemaVersion $.IdentityUpgraders }}
1300+
1301+
{{ $.CustomTemplate $.IdentityUpgraderFile false -}}
1302+
{{- end }}
1303+
12571304
{{- if and $.HasPostCreateComputedFields (or (or (not $.GetAsync) (not ($.GetAsync.Allow "Create"))) (and $.GetAsync (and ($.GetAsync.IsA "PollAsync") ($.GetAsync.Allow "Create"))))}}
12581305
func resource{{ $.ResourceName -}}PostCreateSetComputedFields(d *schema.ResourceData, meta interface{}, res map[string]interface{}) error {
12591306
config := meta.(*transport_tpg.Config)

mmv1/templates/terraform/resource.html.markdown.tmpl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,18 @@ This resource does not support import.
191191
* `{{replaceAll $idFormat "%" "" }}`
192192
{{- end }}
193193

194+
In Terraform v1.12.0 and later, use an [`identity` block](https://developer.hashicorp.com/terraform/language/resources/identities) to import {{$.Name}} using identity values. For example:
195+
196+
```tf
197+
import {
198+
identity = {
199+
{{- range $identity := $.IdentityProperties }}
200+
{{ $identity.Name }} = "<-{{ if $identity.Required }}required{{ else }}optional{{ end }} value->"
201+
{{- end }}
202+
}
203+
to = {{$.TerraformName}}.default
204+
}
205+
```
194206

195207
In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import {{$.Name}} using one of the formats above. For example:
196208

mmv1/third_party/terraform/go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ require (
2626
github.com/hashicorp/terraform-plugin-log v0.9.0
2727
github.com/hashicorp/terraform-plugin-mux v0.20.0
2828
github.com/hashicorp/terraform-plugin-sdk/v2 v2.38.1
29-
github.com/hashicorp/terraform-plugin-testing v1.5.1
29+
github.com/hashicorp/terraform-plugin-testing v1.13.3
3030
github.com/mitchellh/go-homedir v1.1.0
3131
github.com/mitchellh/hashstructure v1.1.0
3232
github.com/sirupsen/logrus v1.8.1
@@ -99,7 +99,7 @@ require (
9999
github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect
100100
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
101101
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
102-
github.com/zclconf/go-cty v1.17.0 // indirect
102+
github.com/zclconf/go-cty v1.16.3 // indirect
103103
github.com/zeebo/errs v1.4.0 // indirect
104104
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
105105
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 // indirect

mmv1/third_party/terraform/go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,10 +179,10 @@ github.com/hashicorp/terraform-plugin-mux v0.20.0 h1:3QpBnI9uCuL0Yy2Rq/kR9cOdmOF
179179
github.com/hashicorp/terraform-plugin-mux v0.20.0/go.mod h1:wSIZwJjSYk86NOTX3fKUlThMT4EAV1XpBHz9SAvjQr4=
180180
github.com/hashicorp/terraform-plugin-sdk/v2 v2.38.1 h1:mlAq/OrMlg04IuJT7NpefI1wwtdpWudnEmjuQs04t/4=
181181
github.com/hashicorp/terraform-plugin-sdk/v2 v2.38.1/go.mod h1:GQhpKVvvuwzD79e8/NZ+xzj+ZpWovdPAe8nfV/skwNU=
182-
github.com/hashicorp/terraform-plugin-testing v1.5.1 h1:T4aQh9JAhmWo4+t1A7x+rnxAJHCDIYW9kXyo4sVO92c=
183-
github.com/hashicorp/terraform-plugin-testing v1.5.1/go.mod h1:dg8clO6K59rZ8w9EshBmDp1CxTIPu3yA4iaDpX1h5u0=
184182
github.com/hashicorp/terraform-registry-address v0.4.0 h1:S1yCGomj30Sao4l5BMPjTGZmCNzuv7/GDTDX99E9gTk=
185183
github.com/hashicorp/terraform-registry-address v0.4.0/go.mod h1:LRS1Ay0+mAiRkUyltGT+UHWkIqTFvigGn/LbMshfflE=
184+
github.com/hashicorp/terraform-plugin-testing v1.13.3 h1:QLi/khB8Z0a5L54AfPrHukFpnwsGL8cwwswj4RZduCo=
185+
github.com/hashicorp/terraform-plugin-testing v1.13.3/go.mod h1:WHQ9FDdiLoneey2/QHpGM/6SAYf4A7AZazVg7230pLE=
186186
github.com/hashicorp/terraform-svchost v0.1.1 h1:EZZimZ1GxdqFRinZ1tpJwVxxt49xc/S52uzrw4x0jKQ=
187187
github.com/hashicorp/terraform-svchost v0.1.1/go.mod h1:mNsjQfZyf/Jhz35v6/0LWcv26+X7JPS+buii2c9/ctc=
188188
github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8=

0 commit comments

Comments
 (0)