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

New Resource: azure_consumption_budget_* #9201

Merged
merged 50 commits into from
May 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
c627fab
Add consumption budgets client
marc-sensenich Nov 6, 2020
4ff0ac7
Add expand and flatten for UUID slices
marc-sensenich Nov 7, 2020
9336775
Add consumption budget name validation and ID parsing
marc-sensenich Nov 7, 2020
67d5d27
Add consumption budget expand and flatten funcs
marc-sensenich Nov 7, 2020
b1b08e4
Add DiffSuppressFunc for Azure Consumption time_period.end_date
marc-sensenich Nov 7, 2020
bfaa9a6
Add validation for time_period.start_date
marc-sensenich Nov 7, 2020
c86db60
fixup! Add expand and flatten for UUID slices
marc-sensenich Nov 10, 2020
42d33bb
Add resource azurerm_consumption_budget_subscription
marc-sensenich Nov 10, 2020
d11a4b7
Add resource azurerm_consumption_budget_subscription documentation
marc-sensenich Nov 10, 2020
a33d4d8
fixup! Add resource azurerm_consumption_budget_subscription documenta…
marc-sensenich Nov 10, 2020
3e19ab8
fixup! Add resource azurerm_consumption_budget_subscription
marc-sensenich Nov 10, 2020
e4db287
fixup! Add resource azurerm_consumption_budget_subscription documenta…
marc-sensenich Nov 10, 2020
0f68fd7
Add resource azurerm_consumption_budget_resource_group
marc-sensenich Nov 10, 2020
f658b89
fixup! Add resource azurerm_consumption_budget_subscription
marc-sensenich Dec 1, 2020
cde0853
fixup! Add resource azurerm_consumption_budget_resource_group
marc-sensenich Dec 1, 2020
d782c9d
Add Computed to end_date
marc-sensenich Dec 2, 2020
cf64e1e
Move Consumption Budget tests
marc-sensenich Feb 6, 2021
5d647f7
Convert consumption budget tests to testshim
marc-sensenich Feb 6, 2021
e72ef0d
Move consumption budget helpers out of azure/helpers
marc-sensenich Feb 6, 2021
8eecbfe
fixup! Convert consumption budget tests to testshim
marc-sensenich Feb 6, 2021
7236af6
run go mod vendor
marc-sensenich Feb 6, 2021
385259e
run make goimports
marc-sensenich Feb 6, 2021
de482fb
fixup! Add expand and flatten for UUID slices
marc-sensenich Mar 4, 2021
bafdd31
Run go mod tidy and go mod vendor
marc-sensenich Mar 4, 2021
9177685
Update to Consumption API version 2019-10-01
marc-sensenich Mar 13, 2021
9d3b291
Add not block to consumption budgets
marc-sensenich Mar 14, 2021
c4c48fb
fixup! Add not block to consumption budgets
marc-sensenich Mar 14, 2021
8338591
Return []interface{} in Consumption Flatten functions
marc-sensenich May 7, 2021
4938439
Fix typo in error for expanding time_period in common
marc-sensenich May 7, 2021
0e2a63d
Add nil checks in Flattens/Expands for Consuption helpers
marc-sensenich May 7, 2021
fa6b63a
Clean up and sort imports for azurerm/internal/services/consumption
marc-sensenich May 7, 2021
1ddea1c
Use validating importers for Consumption resources
marc-sensenich May 7, 2021
3412d12
Add ID method to ConsumptionBudgetId
marc-sensenich May 7, 2021
b41cbc6
Use ConsumptionBudgetId.ID for setting the resource ID on read
marc-sensenich May 7, 2021
241fee5
Use Resource Group ID instead of name and sub for Resource Group Cons…
marc-sensenich May 7, 2021
25f650d
Remove website/azurerm.erb as this is no longer used
marc-sensenich May 7, 2021
fd6074e
fixup! Use Resource Group ID instead of name and sub for Resource Gro…
marc-sensenich May 7, 2021
7d6da36
fixup! Add ID method to ConsumptionBudgetId
marc-sensenich May 7, 2021
884f53b
Run go mod vendor
marc-sensenich May 7, 2021
fab7a12
Run terrafmt fmt on consumption_budget_resource_group_resource_test.go
marc-sensenich May 8, 2021
8eb5683
Remove UUID slice expand and flatten functions
marc-sensenich May 11, 2021
61d4529
fixup! Use Resource Group ID instead of name and sub for Resource Gro…
marc-sensenich May 11, 2021
7da9f12
Remove DiffSuppressFuncConsumptionBudgetTimePeriodEndDate as the end_…
marc-sensenich May 11, 2021
2a6d556
Add comments around why Consumption Budget resource names are consts
marc-sensenich May 11, 2021
926f618
Check that resp.Amount is not nil before setting Consumption Budget a…
marc-sensenich May 11, 2021
25e2561
Remove category from Consumption Budget schema as it has only 1 possi…
marc-sensenich May 11, 2021
21c34bc
fixup! Use Resource Group ID instead of name and sub for Resource Gro…
marc-sensenich May 13, 2021
60f9fd3
Use generated resource IDs for Consumption Budget resources
marc-sensenich May 13, 2021
cae3cdb
Change id generation in delete for resource group
mbfrahry May 13, 2021
98f948e
Update id generation for delete with subscription
mbfrahry May 13, 2021
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
1 change: 1 addition & 0 deletions .teamcity/components/generated/services.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ var services = mapOf(
"cognitive" to "Cognitive Services",
"communication" to "Communication",
"compute" to "Compute",
"consumption" to "Consumption",
"containers" to "Container Services",
"cosmos" to "CosmosDB",
"costmanagement" to "Cost Management",
Expand Down
3 changes: 3 additions & 0 deletions azurerm/internal/clients/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
cognitiveServices "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/cognitive/client"
communication "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/communication/client"
compute "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/compute/client"
consumption "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/consumption/client"
containerServices "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/containers/client"
cosmosdb "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/cosmos/client"
costmanagement "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/costmanagement/client"
Expand Down Expand Up @@ -123,6 +124,7 @@ type Client struct {
Cognitive *cognitiveServices.Client
Communication *communication.Client
Compute *compute.Client
Consumption *consumption.Client
Containers *containerServices.Client
Cosmos *cosmosdb.Client
CostManagement *costmanagement.Client
Expand Down Expand Up @@ -225,6 +227,7 @@ func (client *Client) Build(ctx context.Context, o *common.ClientOptions) error
client.Cognitive = cognitiveServices.NewClient(o)
client.Communication = communication.NewClient(o)
client.Compute = compute.NewClient(o)
client.Consumption = consumption.NewClient(o)
client.Containers = containerServices.NewClient(o)
client.Cosmos = cosmosdb.NewClient(o)
client.CostManagement = costmanagement.NewClient(o)
Expand Down
2 changes: 2 additions & 0 deletions azurerm/internal/provider/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/cognitive"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/communication"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/compute"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/consumption"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/containers"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/cosmos"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/costmanagement"
Expand Down Expand Up @@ -127,6 +128,7 @@ func SupportedUntypedServices() []sdk.UntypedServiceRegistration {
communication.Registration{},
compute.Registration{},
containers.Registration{},
consumption.Registration{},
cosmos.Registration{},
costmanagement.Registration{},
customproviders.Registration{},
Expand Down
19 changes: 19 additions & 0 deletions azurerm/internal/services/consumption/client/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package client

import (
"github.com/Azure/azure-sdk-for-go/services/consumption/mgmt/2019-10-01/consumption"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/common"
)

type Client struct {
BudgetsClient *consumption.BudgetsClient
}

func NewClient(o *common.ClientOptions) *Client {
budgetsClient := consumption.NewBudgetsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&budgetsClient.Client, o.ResourceManagerAuthorizer)

return &Client{
BudgetsClient: &budgetsClient,
}
}
110 changes: 110 additions & 0 deletions azurerm/internal/services/consumption/consumption_budget_common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package consumption

import (
"fmt"

"github.com/Azure/azure-sdk-for-go/services/consumption/mgmt/2019-10-01/consumption"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/shopspring/decimal"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

func resourceArmConsumptionBudgetRead(d *schema.ResourceData, meta interface{}, scope, name string) error {
client := meta.(*clients.Client).Consumption.BudgetsClient
ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d)
defer cancel()

resp, err := client.Get(ctx, scope, name)
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
d.SetId("")
return nil
}
return fmt.Errorf("error making read request on Azure Consumption Budget %q for scope %q: %+v", name, scope, err)
}

d.Set("name", resp.Name)
if resp.Amount != nil {
amount, _ := resp.Amount.Float64()
d.Set("amount", amount)
}
d.Set("time_grain", string(resp.TimeGrain))
d.Set("time_period", FlattenConsumptionBudgetTimePeriod(resp.TimePeriod))
d.Set("notification", schema.NewSet(schema.HashResource(SchemaConsumptionBudgetNotificationElement()), FlattenConsumptionBudgetNotifications(resp.Notifications)))
d.Set("filter", FlattenConsumptionBudgetFilter(resp.Filter))

return nil
}

func resourceArmConsumptionBudgetDelete(d *schema.ResourceData, meta interface{}, scope string) error {
client := meta.(*clients.Client).Consumption.BudgetsClient
ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d)
defer cancel()

name := d.Get("name").(string)
resp, err := client.Delete(ctx, scope, name)

if err != nil {
if !utils.ResponseWasNotFound(resp) {
return fmt.Errorf("error issuing delete request on Azure Consumption Budget %q for scope %q: %+v", name, scope, err)
}
}

return nil
}

func resourceArmConsumptionBudgetCreateUpdate(d *schema.ResourceData, meta interface{}, resourceName, scope string) error {
client := meta.(*clients.Client).Consumption.BudgetsClient
ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d)
defer cancel()

name := d.Get("name").(string)

if d.IsNewResource() {
existing, err := client.Get(ctx, scope, name)
if err != nil {
if !utils.ResponseWasNotFound(existing.Response) {
return fmt.Errorf("error checking for presence of existing Consumption Budget %q for scope %q: %s", name, scope, err)
}
}

if existing.ID != nil && *existing.ID != "" {
return tf.ImportAsExistsError(resourceName, *existing.ID)
}
}

amount := decimal.NewFromFloat(d.Get("amount").(float64))
timePeriod, err := ExpandConsumptionBudgetTimePeriod(d.Get("time_period").([]interface{}))
if err != nil {
return fmt.Errorf("error expanding `time_period`: %+v", err)
}

// The Consumption Budget API requires the category type field to be set in a budget's properties.
// 'Cost' is the only valid Budget type today according to the API spec.
category := "Cost"
parameters := consumption.Budget{
Name: utils.String(name),
BudgetProperties: &consumption.BudgetProperties{
Amount: &amount,
Category: &category,
Filter: ExpandConsumptionBudgetFilter(d.Get("filter").([]interface{})),
Notifications: ExpandConsumptionBudgetNotifications(d.Get("notification").(*schema.Set).List()),
TimeGrain: consumption.TimeGrainType(d.Get("time_grain").(string)),
TimePeriod: timePeriod,
},
}

read, err := client.CreateOrUpdate(ctx, scope, name, parameters)
if err != nil {
return err
}

if read.ID == nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than setting the ID through this check. We've been generating the ID and then setting that. That lets us avoid issues where ID is nil.

return fmt.Errorf("cannot read Azure Consumption Budget %q for scope %q", name, scope)
}

return nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package consumption

import (
"time"

"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/consumption/parse"
resourceParse "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/resource/parse"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/pluginsdk"
)

func resourceArmConsumptionBudgetResourceGroup() *schema.Resource {
return &schema.Resource{
Create: resourceArmConsumptionBudgetResourceGroupCreateUpdate,
Read: resourceArmConsumptionBudgetResourceGroupRead,
Update: resourceArmConsumptionBudgetResourceGroupCreateUpdate,
Delete: resourceArmConsumptionBudgetResourceGroupDelete,
Importer: pluginsdk.ImporterValidatingResourceId(func(id string) error {
_, err := parse.ConsumptionBudgetResourceGroupID(id)
return err
}),

Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(30 * time.Minute),
Read: schema.DefaultTimeout(5 * time.Minute),
Update: schema.DefaultTimeout(30 * time.Minute),
Delete: schema.DefaultTimeout(30 * time.Minute),
},

Schema: SchemaConsumptionBudgetResourceGroupResource(),
}
}

func resourceArmConsumptionBudgetResourceGroupCreateUpdate(d *schema.ResourceData, meta interface{}) error {
name := d.Get("name").(string)
resourceGroupId, err := resourceParse.ResourceGroupID(d.Get("resource_group_id").(string))
if err != nil {
return err
}

err = resourceArmConsumptionBudgetCreateUpdate(d, meta, consumptionBudgetResourceGroupName, resourceGroupId.ID())
if err != nil {
return err
}

d.SetId(parse.NewConsumptionBudgetResourceGroupID(resourceGroupId.SubscriptionId, resourceGroupId.ResourceGroup, name).ID())

return resourceArmConsumptionBudgetResourceGroupRead(d, meta)
}

func resourceArmConsumptionBudgetResourceGroupRead(d *schema.ResourceData, meta interface{}) error {
consumptionBudgetId, err := parse.ConsumptionBudgetResourceGroupID(d.Id())
if err != nil {
return err
}

resourceGroupId := resourceParse.NewResourceGroupID(consumptionBudgetId.SubscriptionId, consumptionBudgetId.ResourceGroup)

err = resourceArmConsumptionBudgetRead(d, meta, resourceGroupId.ID(), consumptionBudgetId.BudgetName)
if err != nil {
return err
}

// The scope of a Resource Group consumption budget is the Resource Group ID
d.Set("resource_group_id", resourceGroupId.ID())

return nil
}

func resourceArmConsumptionBudgetResourceGroupDelete(d *schema.ResourceData, meta interface{}) error {
consumptionBudgetId, err := parse.ConsumptionBudgetResourceGroupID(d.Id())
if err != nil {
return err
}

resourceGroupId := resourceParse.NewResourceGroupID(consumptionBudgetId.SubscriptionId, consumptionBudgetId.ResourceGroup)

return resourceArmConsumptionBudgetDelete(d, meta, resourceGroupId.ID())
}
Loading