From 886d117dd0930cc0f29aebae22d673db3daf9758 Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Thu, 22 Dec 2022 11:59:39 -0800 Subject: [PATCH] Make billing budget filter credit_types and subaccounts updatable --- mmv1/products/billingbudget/api.yaml | 8 +- mmv1/products/billingbudget/terraform.yaml | 2 + .../examples/billing_budget_filter.tf.erb | 7 +- .../tests/resource_billing_budget_test.go | 123 +++++++++++++++++- 4 files changed, 132 insertions(+), 8 deletions(-) diff --git a/mmv1/products/billingbudget/api.yaml b/mmv1/products/billingbudget/api.yaml index 5b2a5e001779..84b70385ef1f 100644 --- a/mmv1/products/billingbudget/api.yaml +++ b/mmv1/products/billingbudget/api.yaml @@ -123,8 +123,10 @@ objects: description: | Optional. If creditTypesTreatment is INCLUDE_SPECIFIED_CREDITS, this is a list of credit types to be subtracted from gross cost to determine the spend for threshold calculations. See a list of acceptable credit type values. - If creditTypesTreatment is not INCLUDE_SPECIFIED_CREDITS, this field must be empty. - item_type: Api::Type::String + If creditTypesTreatment is not INCLUDE_SPECIFIED_CREDITS, this field must be empty. + + **Note:** If the field has a value in the config and needs to be removed, the field has to be an emtpy array in the config. + item_type: Api::Type::String at_least_one_of: - budget_filter.0.projects - budget_filter.0.credit_types_treatment @@ -142,6 +144,8 @@ objects: the parent account, usage from the parent account will be included. If the field is omitted, the report will include usage from the parent account and all subaccounts, if they exist. + + **Note:** If the field has a value in the config and needs to be removed, the field has to be an emtpy array in the config. item_type: Api::Type::String at_least_one_of: - budget_filter.0.projects diff --git a/mmv1/products/billingbudget/terraform.yaml b/mmv1/products/billingbudget/terraform.yaml index a74341a7122a..050dd3db8d45 100644 --- a/mmv1/products/billingbudget/terraform.yaml +++ b/mmv1/products/billingbudget/terraform.yaml @@ -104,6 +104,8 @@ overrides: !ruby/object:Overrides::ResourceOverrides - "budgetFilter.customPeriod" - "budgetFilter.services" - "budgetFilter.creditTypesTreatment" + - "budgetFilter.creditTypes" + - "budgetFilter.subaccounts" budgetFilter.services: !ruby/object:Overrides::Terraform::PropertyOverride default_from_api: true budgetFilter.subaccounts: !ruby/object:Overrides::Terraform::PropertyOverride diff --git a/mmv1/templates/terraform/examples/billing_budget_filter.tf.erb b/mmv1/templates/terraform/examples/billing_budget_filter.tf.erb index fa59a38f8ba7..b5af323ed1c4 100644 --- a/mmv1/templates/terraform/examples/billing_budget_filter.tf.erb +++ b/mmv1/templates/terraform/examples/billing_budget_filter.tf.erb @@ -10,9 +10,10 @@ resource "google_billing_budget" "<%= ctx[:primary_resource_id] %>" { display_name = "<%= ctx[:vars]['display_name'] %>" budget_filter { - projects = ["projects/${data.google_project.project.number}"] - credit_types_treatment = "EXCLUDE_ALL_CREDITS" - services = ["services/24E6-581D-38E5"] # Bigquery + projects = ["projects/${data.google_project.project.number}"] + credit_types_treatment = "INCLUDE_SPECIFIED_CREDITS" + services = ["services/24E6-581D-38E5"] # Bigquery + credit_types = ["PROMOTION", "FREE_TIER"] } amount { diff --git a/mmv1/third_party/terraform/tests/resource_billing_budget_test.go b/mmv1/third_party/terraform/tests/resource_billing_budget_test.go index e1255188fb13..e4ccc3cf3773 100644 --- a/mmv1/third_party/terraform/tests/resource_billing_budget_test.go +++ b/mmv1/third_party/terraform/tests/resource_billing_budget_test.go @@ -122,6 +122,121 @@ func TestAccBillingBudget_billingBudgetUpdate(t *testing.T) { }) } +func TestAccBillingBudget_billingFilterSubaccounts(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "master_billing_acct": getTestMasterBillingAccountFromEnv(t), + "random_suffix": randString(t, 10), + } + + vcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckBillingBudgetDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccBillingBudget_billingFilterSubaccounts(context), + }, + { + ResourceName: "google_billing_budget.budget", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccBillingBudget_billingFilterRemoveSubaccounts(context), + }, + { + ResourceName: "google_billing_budget.budget", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccBillingBudget_billingFilterSubaccounts(context map[string]interface{}) string { + return Nprintf(` +data "google_billing_account" "account" { + billing_account = "%{master_billing_acct}" +} + +data "google_project" "project" { +} + +resource "google_billing_subaccount" "subaccount" { + display_name = "My Billing Account" + master_billing_account = data.google_billing_account.account.id +} + +resource "google_billing_budget" "budget" { + billing_account = data.google_billing_account.account.id + display_name = "Example Billing Budget%{random_suffix}" + + budget_filter { + projects = ["projects/${data.google_project.project.number}"] + labels = { + label = "bar" + } + + subaccounts = ["billingAccounts/${google_billing_subaccount.subaccount.billing_account_id}"] + } + + amount { + specified_amount { + units = "100000" + } + } + + threshold_rules { + threshold_percent = 1.0 + } + threshold_rules { + threshold_percent = 1.0 + spend_basis = "FORECASTED_SPEND" + } +} +`, context) +} + +func testAccBillingBudget_billingFilterRemoveSubaccounts(context map[string]interface{}) string { + return Nprintf(` +data "google_billing_account" "account" { + billing_account = "%{master_billing_acct}" +} + +data "google_project" "project" { +} + +resource "google_billing_budget" "budget" { + billing_account = data.google_billing_account.account.id + display_name = "Example Billing Budget%{random_suffix}" + + budget_filter { + projects = ["projects/${data.google_project.project.number}"] + labels = { + label = "bar" + } + subaccounts = [] + } + + amount { + specified_amount { + units = "100000" + } + } + + threshold_rules { + threshold_percent = 1.0 + } + threshold_rules { + threshold_percent = 1.0 + spend_basis = "FORECASTED_SPEND" + } +} +`, context) +} + func testAccBillingBudget_billingBudgetUpdateStart(context map[string]interface{}) string { return Nprintf(` resource "google_pubsub_topic" "topic1" { @@ -242,8 +357,9 @@ resource "google_billing_budget" "budget" { labels = { label1 = "bar2" } - credit_types_treatment = "INCLUDE_ALL_CREDITS" - services = ["services/24E6-581D-38E5"] # Bigquery + credit_types_treatment = "INCLUDE_SPECIFIED_CREDITS" + services = ["services/24E6-581D-38E5"] # Bigquery + credit_types = ["PROMOTION", "FREE_TIER"] } amount { @@ -350,8 +466,9 @@ resource "google_billing_budget" "budget" { year = 2023 month = 12 day = 31 - } + } } + credit_types = [] } amount {