diff --git a/.changelog/7035.txt b/.changelog/7035.txt new file mode 100644 index 00000000000..a80ca2a4bb9 --- /dev/null +++ b/.changelog/7035.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +billingbudget: Make fields `credit_types` and `subaccounts` updatable for `google_billing_budget` +``` diff --git a/google/resource_billing_budget.go b/google/resource_billing_budget.go index f7c259a4cc8..52d63af9ba7 100644 --- a/google/resource_billing_budget.go +++ b/google/resource_billing_budget.go @@ -203,7 +203,9 @@ Exactly one of 'calendar_period', 'custom_period' must be provided. Possible val Optional: true, 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.`, +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.`, Elem: &schema.Schema{ Type: schema.TypeString, }, @@ -336,7 +338,9 @@ specifying that usage from only this set of subaccounts should be included in the budget. If a subaccount is set to the name of 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.`, +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.`, Elem: &schema.Schema{ Type: schema.TypeString, }, @@ -564,7 +568,9 @@ func resourceBillingBudgetUpdate(d *schema.ResourceData, meta interface{}) error "budgetFilter.calendarPeriod", "budgetFilter.customPeriod", "budgetFilter.services", - "budgetFilter.creditTypesTreatment") + "budgetFilter.creditTypesTreatment", + "budgetFilter.creditTypes", + "budgetFilter.subaccounts") } if d.HasChange("amount") { diff --git a/google/resource_billing_budget_generated_test.go b/google/resource_billing_budget_generated_test.go index 22fee894575..2fe21dca080 100644 --- a/google/resource_billing_budget_generated_test.go +++ b/google/resource_billing_budget_generated_test.go @@ -168,9 +168,10 @@ resource "google_billing_budget" "budget" { display_name = "Example Billing Budget%{random_suffix}" 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/google/resource_billing_budget_test.go b/google/resource_billing_budget_test.go index e1255188fb1..e4ccc3cf377 100644 --- a/google/resource_billing_budget_test.go +++ b/google/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 { diff --git a/website/docs/r/billing_budget.html.markdown b/website/docs/r/billing_budget.html.markdown index 1def457a707..a6db45c88cf 100644 --- a/website/docs/r/billing_budget.html.markdown +++ b/website/docs/r/billing_budget.html.markdown @@ -104,9 +104,10 @@ resource "google_billing_budget" "budget" { display_name = "Example Billing Budget" 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 { @@ -338,6 +339,7 @@ The following arguments are supported: 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. + **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. * `subaccounts` - (Optional) @@ -347,6 +349,7 @@ The following arguments are supported: 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. * `labels` - (Optional)