From 1e8b6a565c2e1815109ade7f0cc8a6f23b298fa3 Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Tue, 22 Aug 2023 14:11:40 -0700 Subject: [PATCH] Support provider default labels for DCL resources --- tpgtools/property.go | 33 ++++++++++++++++++++++++++++- tpgtools/resource.go | 10 +++++++-- tpgtools/templates/resource.go.tmpl | 19 +++++++++++++++-- 3 files changed, 57 insertions(+), 5 deletions(-) diff --git a/tpgtools/property.go b/tpgtools/property.go index 0292c3124857..d3718c4bfc1c 100644 --- a/tpgtools/property.go +++ b/tpgtools/property.go @@ -897,7 +897,14 @@ func createPropertiesFromSchema(schema *openapi.Schema, typeFetcher *TypeFetcher note := "**Note**: This field is non-authoritative, and will only manage the labels present in your configuration. " + "Please refer to the field `effective_labels` for all of the labels present on the resource." p.Description = fmt.Sprintf("%s\n\n%s", p.Description, note) + p.Settable = false + p.StateGetter = nil + props = append(props, build_effective_labels_field(p, resource, parent)) + + if p.IsResourceLabels() { + props = append(props, build_terraform_labels_field(p, resource, parent)) + } } props = append(props, p) @@ -929,7 +936,7 @@ func build_effective_labels_field(p Property, resource *Resource, parent *Proper description := fmt.Sprintf("All of %s (key/value pairs) present on the resource in GCP, including the %s configured through Terraform, other clients and services.", p.title, p.title) stateSetter := fmt.Sprintf("d.Set(%q, res.%s)", title, p.PackageName) - return Property{ + effectiveLabels := Property{ title: title, Type: p.Type, Description: description, @@ -937,6 +944,30 @@ func build_effective_labels_field(p Property, resource *Resource, parent *Proper parent: parent, Optional: false, Computed: true, + PackageName: p.PackageName, + Settable: true, + StateSetter: &stateSetter, + } + + stateGetter := effectiveLabels.DefaultStateGetter() + effectiveLabels.StateGetter = &stateGetter + return effectiveLabels +} + +func build_terraform_labels_field(p Property, resource *Resource, parent *Property) Property { + title := fmt.Sprintf("terraform_%s", p.title) + description := fmt.Sprintf("The combination of %s configured directly on the resource and default %s configured on the provider.", p.title, p.title) + stateSetter := fmt.Sprintf("d.Set(%q, flatten%sTerraform%s(res.%s, d))", title, p.resource.PathType(), p.PackagePath(), p.PackageName) + + terraformLabels := Property{ + title: title, + Type: p.Type, + Description: description, + resource: resource, + parent: parent, + Computed: true, + PackageName: p.PackageName, StateSetter: &stateSetter, } + return terraformLabels } diff --git a/tpgtools/resource.go b/tpgtools/resource.go index 1e6f6e7a1498..3384789a787f 100644 --- a/tpgtools/resource.go +++ b/tpgtools/resource.go @@ -586,6 +586,12 @@ func createResource(schema *openapi.Schema, info *openapi.Info, typeFetcher *Typ res.CustomizeDiff = cdiff.Functions } + if res.HasLabels() { + res.CustomizeDiff = append(res.CustomizeDiff, "tpgresource.SetLabelsDiff") + } else if res.HasAnnotations() { + res.CustomizeDiff = append(res.CustomizeDiff, "tpgresource.SetAnnotationsDiff") + } + // ListFields if parameters, ok := typeFetcher.doc.Paths["list"]; ok { for _, param := range parameters.Parameters { @@ -835,7 +841,7 @@ func (r *Resource) loadHandWrittenSamples() []Sample { // During importing, as the configuration is unavailableafter, the "labels" and "annotations" fields in the state will be empty. // So add the "labels" and the "annotations" fields to the ImportStateVerifyIgnore list. if r.HasLabels() { - sample.IgnoreRead = append(sample.IgnoreRead, "labels") + sample.IgnoreRead = append(sample.IgnoreRead, "labels", "terraform_labels") } if r.HasAnnotations() { @@ -930,7 +936,7 @@ func (r *Resource) loadDCLSamples() []Sample { sample.TestSlug = RenderedString(sampleNameToTitleCase(*sample.Name).titlecase()) // The "labels" and "annotations" fields in the state are decided by the configuration. - // During importing, as the configuration is unavailableafter, the "labels" and "annotations" fields in the state will be empty. + // During importing, as the configuration is unavailable, the "labels" and "annotations" fields in the state will be empty. // So add the "labels" and the "annotations" fields to the ImportStateVerifyIgnore list. if r.HasLabels() { sample.IgnoreRead = append(sample.IgnoreRead, "labels") diff --git a/tpgtools/templates/resource.go.tmpl b/tpgtools/templates/resource.go.tmpl index a3f10f2db10b..db1eeb4d6aea 100644 --- a/tpgtools/templates/resource.go.tmpl +++ b/tpgtools/templates/resource.go.tmpl @@ -723,7 +723,22 @@ func flatten{{$.PathType}}Labels(v map[string]string, d *schema.ResourceData) in transformed := make(map[string]interface{}) if l, ok := d.Get("labels").(map[string]interface{}); ok { for k, _ := range l { - transformed[k] = l[k] + transformed[k] = v[k] + } + } + + return transformed +} + +func flatten{{$.PathType}}TerraformLabels(v map[string]string, d *schema.ResourceData) interface{} { + if v == nil { + return nil + } + + transformed := make(map[string]interface{}) + if l, ok := d.Get("terraform_labels").(map[string]interface{}); ok { + for k, _ := range l { + transformed[k] = v[k] } } @@ -740,7 +755,7 @@ func flatten{{$.PathType}}Annotations(v map[string]string, d *schema.ResourceDat transformed := make(map[string]interface{}) if l, ok := d.Get("annotations").(map[string]interface{}); ok { for k, _ := range l { - transformed[k] = l[k] + transformed[k] = v[k] } }