Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Made deletion of all budget filter projects be recognized #4731

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions mmv1/products/billingbudget/api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,9 @@ objects:
- !ruby/object:Api::Resource
name: Budget
base_url: billingAccounts/{{billing_account}}/budgets
self_link: '{{name}}'
self_link: 'billingAccounts/{{billing_account}}/budgets/{{name}}'
melinath marked this conversation as resolved.
Show resolved Hide resolved
update_verb: :PATCH
# TODO: investigate why updates are not being handled by the API when this
# is enabled.
# update_mask: true
update_mask: true
description: |
Budget configuration for a billing account.
references: !ruby/object:Api::Resource::ReferenceLinks
Expand Down
16 changes: 7 additions & 9 deletions mmv1/products/billingbudget/terraform.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ overrides: !ruby/object:Overrides::ResourceOverrides
in the provider configuration. Otherwise the Billing Budgets API will return a 403 error.
Your account must have the `serviceusage.services.use` permission on the
`billing_project` you defined.
id_format: '{{name}}'
exclude_import: true
id_format: 'billingAccounts/{{billing_account}}/budgets/{{name}}'
import_format: ["billingAccounts/{{billing_account}}/budgets/{{name}}", "{{name}}"]
schema_version: 1
examples:
- !ruby/object:Provider::Terraform::Examples
name: 'billing_budget_basic'
Expand All @@ -31,23 +32,20 @@ overrides: !ruby/object:Overrides::ResourceOverrides
display_name: 'Example Billing Budget'
test_env_vars:
billing_acct: :BILLING_ACCT
skip_import_test: true
- !ruby/object:Provider::Terraform::Examples
name: 'billing_budget_lastperiod'
primary_resource_id: 'budget'
vars:
display_name: 'Example Billing Budget'
test_env_vars:
billing_acct: :BILLING_ACCT
skip_import_test: true
- !ruby/object:Provider::Terraform::Examples
name: 'billing_budget_filter'
primary_resource_id: 'budget'
vars:
display_name: 'Example Billing Budget'
test_env_vars:
billing_acct: :BILLING_ACCT
skip_import_test: true
- !ruby/object:Provider::Terraform::Examples
name: 'billing_budget_notify'
primary_resource_id: 'budget'
Expand All @@ -56,17 +54,17 @@ overrides: !ruby/object:Overrides::ResourceOverrides
channel_name: 'Example Notification Channel'
test_env_vars:
billing_acct: :BILLING_ACCT
skip_import_test: true
custom_code: !ruby/object:Provider::Terraform::CustomCode
custom_import: templates/terraform/custom_import/self_link_as_name.erb
post_create: templates/terraform/post_create/set_computed_name.erb
properties:
name: !ruby/object:Overrides::Terraform::PropertyOverride
custom_flatten: 'templates/terraform/custom_flatten/name_from_self_link.erb'
allUpdatesRule.schemaVersion: !ruby/object:Overrides::Terraform::PropertyOverride
custom_flatten: templates/terraform/custom_flatten/default_if_empty.erb
budgetFilter.creditTypes: !ruby/object:Overrides::Terraform::PropertyOverride
default_from_api: true
budgetFilter: !ruby/object:Overrides::Terraform::PropertyOverride
default_from_api: true
update_mask_fields:
- "budgetFilter.projects"
budgetFilter.services: !ruby/object:Overrides::Terraform::PropertyOverride
default_from_api: true
budgetFilter.subaccounts: !ruby/object:Overrides::Terraform::PropertyOverride
Expand Down
251 changes: 251 additions & 0 deletions mmv1/templates/terraform/state_migrations/billing_budget.go.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
func resourceBillingBudgetResourceV0() *schema.Resource {
return &schema.Resource{
Schema: map[string]*schema.Schema{
"amount": {
Type: schema.TypeList,
Required: true,
Description: `The budgeted amount for each usage period.`,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"last_period_amount": {
Type: schema.TypeBool,
Optional: true,
Description: `Configures a budget amount that is automatically set to 100% of
last period's spend.
Boolean. Set value to true to use. Do not set to false, instead
use the 'specified_amount' block.`,
ExactlyOneOf: []string{"amount.0.specified_amount", "amount.0.last_period_amount"},
},
"specified_amount": {
Type: schema.TypeList,
Optional: true,
Description: `A specified amount to use as the budget. currencyCode is
optional. If specified, it must match the currency of the
billing account. The currencyCode is provided on output.`,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"currency_code": {
Type: schema.TypeString,
Computed: true,
Optional: true,
Description: `The 3-letter currency code defined in ISO 4217.`,
},
"nanos": {
Type: schema.TypeInt,
Optional: true,
Description: `Number of nano (10^-9) units of the amount.
The value must be between -999,999,999 and +999,999,999
inclusive. If units is positive, nanos must be positive or
zero. If units is zero, nanos can be positive, zero, or
negative. If units is negative, nanos must be negative or
zero. For example $-1.75 is represented as units=-1 and
nanos=-750,000,000.`,
},
"units": {
Type: schema.TypeString,
Optional: true,
Description: `The whole units of the amount. For example if currencyCode
is "USD", then 1 unit is one US dollar.`,
},
},
},
ExactlyOneOf: []string{"amount.0.specified_amount", "amount.0.last_period_amount"},
},
},
},
},
"billing_account": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: `ID of the billing account to set a budget on.`,
},
"threshold_rules": {
Type: schema.TypeList,
Required: true,
Description: `Rules that trigger alerts (notifications of thresholds being
crossed) when spend exceeds the specified percentages of the
budget.`,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"threshold_percent": {
Type: schema.TypeFloat,
Required: true,
Description: `Send an alert when this threshold is exceeded. This is a
1.0-based percentage, so 0.5 = 50%. Must be >= 0.`,
},
"spend_basis": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{"CURRENT_SPEND", "FORECASTED_SPEND", ""}, false),
Description: `The type of basis used to determine if spend has passed
the threshold. Default value: "CURRENT_SPEND" Possible values: ["CURRENT_SPEND", "FORECASTED_SPEND"]`,
Default: "CURRENT_SPEND",
},
},
},
},
"all_updates_rule": {
Type: schema.TypeList,
Optional: true,
Description: `Defines notifications that are sent on every update to the
billing account's spend, regardless of the thresholds defined
using threshold rules.`,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"disable_default_iam_recipients": {
Type: schema.TypeBool,
Optional: true,
Description: `Boolean. When set to true, disables default notifications sent
when a threshold is exceeded. Default recipients are
those with Billing Account Administrators and Billing
Account Users IAM roles for the target account.`,
Default: false,
},
"monitoring_notification_channels": {
Type: schema.TypeList,
Optional: true,
Description: `The full resource name of a monitoring notification
channel in the form
projects/{project_id}/notificationChannels/{channel_id}.
A maximum of 5 channels are allowed.`,
Elem: &schema.Schema{
Type: schema.TypeString,
},
AtLeastOneOf: []string{"all_updates_rule.0.pubsub_topic", "all_updates_rule.0.monitoring_notification_channels"},
},
"pubsub_topic": {
Type: schema.TypeString,
Optional: true,
Description: `The name of the Cloud Pub/Sub topic where budget related
messages will be published, in the form
projects/{project_id}/topics/{topic_id}. Updates are sent
at regular intervals to the topic.`,
AtLeastOneOf: []string{"all_updates_rule.0.pubsub_topic", "all_updates_rule.0.monitoring_notification_channels"},
},
"schema_version": {
Type: schema.TypeString,
Optional: true,
Description: `The schema version of the notification. Only "1.0" is
accepted. It represents the JSON schema as defined in
https://cloud.google.com/billing/docs/how-to/budgets#notification_format.`,
Default: "1.0",
},
},
},
},
"budget_filter": {
Type: schema.TypeList,
Computed: true,
Optional: true,
Description: `Filters that define which resources are used to compute the actual
spend against the budget.`,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"credit_types": {
Type: schema.TypeList,
Computed: true,
Optional: true,
Description: `A set of subaccounts of the form billingAccounts/{account_id},
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.`,
Elem: &schema.Schema{
Type: schema.TypeString,
},
AtLeastOneOf: []string{"budget_filter.0.projects", "budget_filter.0.credit_types_treatment", "budget_filter.0.services", "budget_filter.0.subaccounts", "budget_filter.0.labels"},
},
"credit_types_treatment": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{"INCLUDE_ALL_CREDITS", "EXCLUDE_ALL_CREDITS", "INCLUDE_SPECIFIED_CREDITS", ""}, false),
Description: `Specifies how credits should be treated when determining spend
for threshold calculations. Default value: "INCLUDE_ALL_CREDITS" Possible values: ["INCLUDE_ALL_CREDITS", "EXCLUDE_ALL_CREDITS", "INCLUDE_SPECIFIED_CREDITS"]`,
Default: "INCLUDE_ALL_CREDITS",
AtLeastOneOf: []string{"budget_filter.0.projects", "budget_filter.0.credit_types_treatment", "budget_filter.0.services", "budget_filter.0.subaccounts", "budget_filter.0.labels"},
},
"labels": {
Type: schema.TypeMap,
Computed: true,
Optional: true,
Description: `A single label and value pair specifying that usage from only
this set of labeled resources should be included in the budget.`,
Elem: &schema.Schema{Type: schema.TypeString},
AtLeastOneOf: []string{"budget_filter.0.projects", "budget_filter.0.credit_types_treatment", "budget_filter.0.services", "budget_filter.0.subaccounts", "budget_filter.0.labels"},
},
"projects": {
Type: schema.TypeList,
Optional: true,
Description: `A set of projects of the form projects/{project_number},
specifying that usage from only this set of projects should be
included in the budget. If omitted, the report will include
all usage for the billing account, regardless of which project
the usage occurred on.`,
Elem: &schema.Schema{
Type: schema.TypeString,
},
AtLeastOneOf: []string{"budget_filter.0.projects", "budget_filter.0.credit_types_treatment", "budget_filter.0.services", "budget_filter.0.subaccounts", "budget_filter.0.labels"},
},
"services": {
Type: schema.TypeList,
Computed: true,
Optional: true,
Description: `A set of services of the form services/{service_id},
specifying that usage from only this set of services should be
included in the budget. If omitted, the report will include
usage for all the services. The service names are available
through the Catalog API:
https://cloud.google.com/billing/v1/how-tos/catalog-api.`,
Elem: &schema.Schema{
Type: schema.TypeString,
},
AtLeastOneOf: []string{"budget_filter.0.projects", "budget_filter.0.credit_types_treatment", "budget_filter.0.services", "budget_filter.0.subaccounts", "budget_filter.0.labels"},
},
"subaccounts": {
Type: schema.TypeList,
Computed: true,
Optional: true,
Description: `A set of subaccounts of the form billingAccounts/{account_id},
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.`,
Elem: &schema.Schema{
Type: schema.TypeString,
},
AtLeastOneOf: []string{"budget_filter.0.projects", "budget_filter.0.credit_types_treatment", "budget_filter.0.services", "budget_filter.0.subaccounts", "budget_filter.0.labels"},
},
},
},
},
"display_name": {
Type: schema.TypeString,
Optional: true,
Description: `User data for display name in UI. Must be <= 60 chars.`,
},
"name": {
Type: schema.TypeString,
Computed: true,
Description: `Resource name of the budget. The resource name
implies the scope of a budget. Values are of the form
billingAccounts/{billingAccountId}/budgets/{budgetId}.`,
},
},
}
}

func resourceBillingBudgetUpgradeV0(_ context.Context, rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) {
log.Printf("[DEBUG] Attributes before migration: %#v", rawState)

rawState["name"] = GetResourceNameFromSelfLink(rawState["name"].(string))

log.Printf("[DEBUG] Attributes after migration: %#v", rawState)
return rawState, nil
}
Loading