Skip to content

Commit

Permalink
Add an optional provider level label "goog-terraform-provisioned" (Go…
Browse files Browse the repository at this point in the history
…ogleCloudPlatform#9808)

* Add an optional provider level label indicating a resource was provisioned by Terraform

* Fix TestAccComputeAddress_withAttributionRemoved to reflect actual behavior

* Fix a bad merge

* Skip tests that change provider config when running under VCR

* Fix some tabs that should have been spaces

* Update mmv1/third_party/terraform/website/docs/guides/provider_reference.html.markdown

Co-authored-by: Riley Karson <rileykarson@google.com>

* Update mmv1/third_party/terraform/website/docs/guides/provider_reference.html.markdown

Co-authored-by: Riley Karson <rileykarson@google.com>

* Change skip_terraform_attribution_label to add_terraform_attribution_label

* Fix a test that was missed in the change to add_terraform_attribution_label

---------

Co-authored-by: Riley Karson <rileykarson@google.com>
  • Loading branch information
2 people authored and pengq-google committed May 21, 2024
1 parent b8acc8c commit 4c3ed51
Show file tree
Hide file tree
Showing 13 changed files with 1,590 additions and 32 deletions.
32 changes: 17 additions & 15 deletions mmv1/third_party/terraform/fwmodels/provider_model.go.erb
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,23 @@ import (

// ProviderModel describes the provider config data model.
type ProviderModel struct {
Credentials types.String `tfsdk:"credentials"`
AccessToken types.String `tfsdk:"access_token"`
ImpersonateServiceAccount types.String `tfsdk:"impersonate_service_account"`
ImpersonateServiceAccountDelegates types.List `tfsdk:"impersonate_service_account_delegates"`
Project types.String `tfsdk:"project"`
BillingProject types.String `tfsdk:"billing_project"`
Region types.String `tfsdk:"region"`
Zone types.String `tfsdk:"zone"`
Scopes types.List `tfsdk:"scopes"`
Batching types.List `tfsdk:"batching"`
UserProjectOverride types.Bool `tfsdk:"user_project_override"`
RequestTimeout types.String `tfsdk:"request_timeout"`
RequestReason types.String `tfsdk:"request_reason"`
UniverseDomain types.String `tfsdk:"universe_domain"`
DefaultLabels types.Map `tfsdk:"default_labels"`
Credentials types.String `tfsdk:"credentials"`
AccessToken types.String `tfsdk:"access_token"`
ImpersonateServiceAccount types.String `tfsdk:"impersonate_service_account"`
ImpersonateServiceAccountDelegates types.List `tfsdk:"impersonate_service_account_delegates"`
Project types.String `tfsdk:"project"`
BillingProject types.String `tfsdk:"billing_project"`
Region types.String `tfsdk:"region"`
Zone types.String `tfsdk:"zone"`
Scopes types.List `tfsdk:"scopes"`
Batching types.List `tfsdk:"batching"`
UserProjectOverride types.Bool `tfsdk:"user_project_override"`
RequestTimeout types.String `tfsdk:"request_timeout"`
RequestReason types.String `tfsdk:"request_reason"`
UniverseDomain types.String `tfsdk:"universe_domain"`
DefaultLabels types.Map `tfsdk:"default_labels"`
AddTerraformAttributionLabel types.Bool `tfsdk:"add_terraform_attribution_label"`
TerraformAttributionLabelAdditionStrategy types.String `tfsdk:"terraform_attribution_label_addition_strategy"`

// Generated Products
<% products.each do |product| -%>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,12 @@ func (p *FrameworkProvider) Schema(_ context.Context, _ provider.SchemaRequest,
Optional: true,
ElementType: types.StringType,
},
"add_terraform_attribution_label": schema.BoolAttribute{
Optional: true,
},
"terraform_attribution_label_addition_strategy": schema.StringAttribute{
Optional: true,
},
// Generated Products
<% products.each do |product| -%>
"<%= product[:definitions].name.underscore -%>_custom_endpoint": &schema.StringAttribute{
Expand Down
24 changes: 24 additions & 0 deletions mmv1/third_party/terraform/provider/provider.go.erb
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,16 @@ func Provider() *schema.Provider {
Elem: &schema.Schema{Type: schema.TypeString},
},

"add_terraform_attribution_label": {
Type: schema.TypeBool,
Optional: true,
},

"terraform_attribution_label_addition_strategy": {
Type: schema.TypeString,
Optional: true,
},

// Generated Products
<% products.each do |product| -%>
"<%= product[:definitions].name.underscore -%>_custom_endpoint": {
Expand Down Expand Up @@ -341,6 +351,20 @@ func ProviderConfigure(ctx context.Context, d *schema.ResourceData, p *schema.Pr
config.DefaultLabels[k] = v.(string)
}

// Attribution label is opt-in; if unset, the default for AddTerraformAttributionLabel is false.
config.AddTerraformAttributionLabel = d.Get("add_terraform_attribution_label").(bool)
if config.AddTerraformAttributionLabel {
config.TerraformAttributionLabelAdditionStrategy = transport_tpg.CreateOnlyAttributionStrategy
if v, ok := d.GetOk("terraform_attribution_label_addition_strategy"); ok {
config.TerraformAttributionLabelAdditionStrategy = v.(string)
}
switch config.TerraformAttributionLabelAdditionStrategy {
case transport_tpg.CreateOnlyAttributionStrategy, transport_tpg.ProactiveAttributionStrategy:
default:
return nil, diag.FromErr(fmt.Errorf("unrecognized terraform_attribution_label_addition_strategy %q", config.TerraformAttributionLabelAdditionStrategy))
}
}

batchCfg, err := transport_tpg.ExpandProviderBatchingConfig(d.Get("batching"))
if err != nil {
return nil, diag.FromErr(err)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -276,3 +276,258 @@ resource "google_clouddeploy_target" "primary" {
}
`, context)
}

func TestAccClouddeployTarget_withCreationOnlyAttribution(t *testing.T) {
t.Parallel()

context := map[string]interface{}{
"project_name": envvar.GetTestProjectFromEnv(),
"region": envvar.GetTestRegionFromEnv(),
"random_suffix": acctest.RandString(t, 10),
"add_attribution": "true",
"attribution_strategy": "CREATION_ONLY",
}

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
CheckDestroy: testAccCheckClouddeployTargetDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccClouddeployTarget_createWithAttribution(context),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "labels.%", "2"),
resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "labels.my_first_label", "example-label-1"),
resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "labels.my_second_label", "example-label-2"),

resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.%", "4"),
resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.my_first_label", "example-label-1"),
resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.my_second_label", "example-label-2"),
resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.default_key1", "default_value1"),
resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.goog-terraform-provisioned", "true"),

resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "effective_labels.%", "4"),
),
},
{
ResourceName: "google_clouddeploy_target.primary",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"labels", "terraform_labels", "annotations"},
},
{
Config: testAccClouddeployTarget_updateWithAttribution(context),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "labels.%", "2"),
resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "labels.my_first_label", "example-label-updated-1"),
resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "labels.my_second_label", "example-label-updated-2"),

resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.%", "4"),
resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.my_first_label", "example-label-updated-1"),
resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.my_second_label", "example-label-updated-2"),
resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.default_key1", "default_value1"),
resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.goog-terraform-provisioned", "true"),

resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "effective_labels.%", "4"),
),
},
{
ResourceName: "google_clouddeploy_target.primary",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"labels", "terraform_labels", "annotations"},
},
{
Config: testAccClouddeployTarget_clearWithAttribution(context),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckNoResourceAttr("google_clouddeploy_target.primary", "labels.%"),

resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.%", "2"),
resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.default_key1", "default_value1"),
resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.goog-terraform-provisioned", "true"),

resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "effective_labels.%", "2"),
),
},
},
})
}

func TestAccClouddeployTarget_withProactiveAttribution(t *testing.T) {
// VCR tests cache provider configuration between steps, this test changes provider configuration and fails under VCR.
acctest.SkipIfVcr(t)
t.Parallel()

suffix := acctest.RandString(t, 10)
disabledContext := map[string]interface{}{
"project_name": envvar.GetTestProjectFromEnv(),
"region": envvar.GetTestRegionFromEnv(),
"random_suffix": suffix,
"add_attribution": "false",
"attribution_strategy": "PROACTIVE",
}
enabledContext := map[string]interface{}{
"project_name": envvar.GetTestProjectFromEnv(),
"region": envvar.GetTestRegionFromEnv(),
"random_suffix": suffix,
"add_attribution": "true",
"attribution_strategy": "PROACTIVE",
}

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
CheckDestroy: testAccCheckClouddeployTargetDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccClouddeployTarget_createWithAttribution(disabledContext),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "labels.%", "2"),
resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "labels.my_first_label", "example-label-1"),
resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "labels.my_second_label", "example-label-2"),

resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.%", "3"),
resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.my_first_label", "example-label-1"),
resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.my_second_label", "example-label-2"),
resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.default_key1", "default_value1"),

resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "effective_labels.%", "3"),
),
},
{
Config: testAccClouddeployTarget_updateWithAttribution(enabledContext),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "labels.%", "2"),
resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "labels.my_first_label", "example-label-updated-1"),
resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "labels.my_second_label", "example-label-updated-2"),

resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.%", "4"),
resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.my_first_label", "example-label-updated-1"),
resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.my_second_label", "example-label-updated-2"),
resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.default_key1", "default_value1"),
resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.goog-terraform-provisioned", "true"),

resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "effective_labels.%", "4"),
),
},
},
})
}

func testAccClouddeployTarget_createWithAttribution(context map[string]interface{}) string {
return acctest.Nprintf(`
provider "google" {
default_labels = {
default_key1 = "default_value1"
}
add_terraform_attribution_label = %{add_attribution}
terraform_attribution_label_addition_strategy = "%{attribution_strategy}"
}
resource "google_clouddeploy_target" "primary" {
location = "%{region}"
name = "tf-test-target%{random_suffix}"
deploy_parameters = {
deployParameterKey = "deployParameterValue"
}
description = "basic description"
gke {
cluster = "projects/%{project_name}/locations/%{region}/clusters/example-cluster-name"
}
project = "%{project_name}"
require_approval = false
annotations = {
my_first_annotation = "example-annotation-1"
my_second_annotation = "example-annotation-2"
}
labels = {
my_first_label = "example-label-1"
my_second_label = "example-label-2"
}
}
`, context)
}

func testAccClouddeployTarget_updateWithAttribution(context map[string]interface{}) string {
return acctest.Nprintf(`
provider "google" {
default_labels = {
default_key1 = "default_value1"
}
add_terraform_attribution_label = %{add_attribution}
terraform_attribution_label_addition_strategy = "%{attribution_strategy}"
}
resource "google_clouddeploy_target" "primary" {
location = "%{region}"
name = "tf-test-target%{random_suffix}"
deploy_parameters = {
deployParameterKey = "deployParameterValue"
}
description = "basic description"
gke {
cluster = "projects/%{project_name}/locations/%{region}/clusters/example-cluster-name"
}
project = "%{project_name}"
require_approval = false
annotations = {
my_first_annotation = "example-annotation-1"
my_second_annotation = "example-annotation-2"
}
labels = {
my_first_label = "example-label-updated-1"
my_second_label = "example-label-updated-2"
}
}
`, context)
}

func testAccClouddeployTarget_clearWithAttribution(context map[string]interface{}) string {
return acctest.Nprintf(`
provider "google" {
default_labels = {
default_key1 = "default_value1"
}
add_terraform_attribution_label = %{add_attribution}
terraform_attribution_label_addition_strategy = "%{attribution_strategy}"
}
resource "google_clouddeploy_target" "primary" {
location = "%{region}"
name = "tf-test-target%{random_suffix}"
deploy_parameters = {
deployParameterKey = "deployParameterValue"
}
description = "basic description"
gke {
cluster = "projects/%{project_name}/locations/%{region}/clusters/example-cluster-name"
}
project = "%{project_name}"
require_approval = false
annotations = {
my_first_annotation = "example-annotation-1"
my_second_annotation = "example-annotation-2"
}
}
`, context)
}
Loading

0 comments on commit 4c3ed51

Please sign in to comment.