Skip to content

Commit

Permalink
Merge pull request #12540 from gro1m/d/azurerm_consumption_budget_sub…
Browse files Browse the repository at this point in the history
…scription

New data source: azurerm_consumption_budget_subscription
  • Loading branch information
stephybun authored Oct 14, 2021
2 parents 421a900 + bf04a7e commit 99e17f6
Show file tree
Hide file tree
Showing 4 changed files with 431 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
package consumption

import (
"fmt"
"time"

"github.com/hashicorp/terraform-provider-azurerm/internal/clients"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/consumption/parse"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/consumption/validate"
subscriptionParse "github.com/hashicorp/terraform-provider-azurerm/internal/services/subscription/parse"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/timeouts"
"github.com/hashicorp/terraform-provider-azurerm/utils"
)

func resourceArmConsumptionBudgetSubscriptionDataSource() *pluginsdk.Resource {
return &pluginsdk.Resource{
Read: resourceArmConsumptionBudgetSubscriptionDataSourceRead,
Timeouts: &pluginsdk.ResourceTimeout{
Read: pluginsdk.DefaultTimeout(5 * time.Minute),
},
Schema: map[string]*pluginsdk.Schema{
"name": {
Type: pluginsdk.TypeString,
Required: true,
ValidateFunc: validate.ConsumptionBudgetName(),
},

"subscription_id": {
Type: pluginsdk.TypeString,
Required: true,
},

"amount": {
Type: pluginsdk.TypeFloat,
Computed: true,
},

"filter": {
Type: pluginsdk.TypeList,
Computed: true,
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"dimension": {
Type: pluginsdk.TypeList,
Computed: true,
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"name": {
Type: pluginsdk.TypeString,
Computed: true,
},
"operator": {
Type: pluginsdk.TypeString,
Computed: true,
},
"values": {
Type: pluginsdk.TypeList,
Computed: true,
Elem: &pluginsdk.Schema{
Type: pluginsdk.TypeString,
},
},
},
},
},
"tag": {
Type: pluginsdk.TypeList,
Computed: true,
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"name": {
Type: pluginsdk.TypeString,
Computed: true,
},
"operator": {
Type: pluginsdk.TypeString,
Computed: true,
},
"values": {
Type: pluginsdk.TypeList,
Computed: true,
Elem: &pluginsdk.Schema{
Type: pluginsdk.TypeString,
},
},
},
},
},
"not": {
Type: pluginsdk.TypeList,
Computed: true,
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"dimension": {
Type: pluginsdk.TypeList,
Computed: true,
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"name": {
Type: pluginsdk.TypeString,
Computed: true,
},
"operator": {
Type: pluginsdk.TypeString,
Computed: true,
},
"values": {
Type: pluginsdk.TypeList,
Computed: true,
Elem: &pluginsdk.Schema{
Type: pluginsdk.TypeString,
},
},
},
},
},
"tag": {
Type: pluginsdk.TypeList,
Computed: true,
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"name": {
Type: pluginsdk.TypeString,
Computed: true,
},
"operator": {
Type: pluginsdk.TypeString,
Computed: true,
},
"values": {
Type: pluginsdk.TypeList,
Computed: true,
Elem: &pluginsdk.Schema{
Type: pluginsdk.TypeString,
},
},
},
},
},
},
},
},
},
},
},

"notification": {
Type: pluginsdk.TypeList,
Computed: true,
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"enabled": {
Type: pluginsdk.TypeBool,
Computed: true,
},
"threshold": {
Type: pluginsdk.TypeInt,
Computed: true,
},
"operator": {
Type: pluginsdk.TypeString,
Computed: true,
},

"contact_emails": {
Type: pluginsdk.TypeList,
Computed: true,
Elem: &pluginsdk.Schema{
Type: pluginsdk.TypeString,
},
},

"contact_groups": {
Type: pluginsdk.TypeList,
Computed: true,
Elem: &pluginsdk.Schema{
Type: pluginsdk.TypeString,
},
},

"contact_roles": {
Type: pluginsdk.TypeList,
Computed: true,
Elem: &pluginsdk.Schema{
Type: pluginsdk.TypeString,
},
},
},
},
},

"time_grain": {
Type: pluginsdk.TypeString,
Computed: true,
},

"time_period": {
Type: pluginsdk.TypeList,
Computed: true,
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"start_date": {
Type: pluginsdk.TypeString,
Computed: true,
},
"end_date": {
Type: pluginsdk.TypeString,
Computed: true,
},
},
},
},
},
}
}

func resourceArmConsumptionBudgetSubscriptionDataSourceRead(d *pluginsdk.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).Consumption.BudgetsClient
ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d)
defer cancel()

subscriptionId, err := subscriptionParse.SubscriptionID(d.Get("subscription_id").(string))
if err != nil {
return err
}

id := parse.NewConsumptionBudgetSubscriptionID(subscriptionId.SubscriptionID, d.Get("name").(string))
d.SetId(id.ID())

resp, err := client.Get(ctx, subscriptionId.ID(), id.BudgetName)
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
d.SetId("")
return nil
}
return fmt.Errorf("making read request on %s: %+v", id, 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", FlattenConsumptionBudgetNotifications(resp.Notifications))
d.Set("filter", FlattenConsumptionBudgetFilter(resp.Filter))

// The scope of a Subscription budget resource is the Subscription budget ID
d.Set("subscription_id", d.Get("subscription_id").(string))

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

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-provider-azurerm/internal/acceptance"
"github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check"
)

type ConsumptionBudgetSubscriptionDataSource struct{}

func TestAccDataSourceConsumptionBudgetSubscription_basic(t *testing.T) {
data := acceptance.BuildTestData(t, "data.azurerm_consumption_budget_subscription", "test")
r := ConsumptionBudgetSubscriptionDataSource{}

data.DataSourceTest(t, []acceptance.TestStep{
{
Config: r.basic(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).Key("subscription_id").HasValue(data.Client().SubscriptionID),
check.That(data.ResourceName).Key("name").Exists(),
check.That(data.ResourceName).Key("amount").HasValue("1000"),
check.That(data.ResourceName).Key("time_grain").HasValue("Monthly"),
check.That(data.ResourceName).Key("time_period.#").Exists(),
check.That(data.ResourceName).Key("time_period.0.start_date").Exists(),
check.That(data.ResourceName).Key("filter.#").Exists(),
check.That(data.ResourceName).Key("filter.0.tag.0.name").HasValue("foo"),
check.That(data.ResourceName).Key("filter.0.tag.0.values.#").Exists(),
check.That(data.ResourceName).Key("notification.#").Exists(),
check.That(data.ResourceName).Key("notification.0.threshold").HasValue("90"),
check.That(data.ResourceName).Key("notification.0.operator").HasValue("EqualTo"),
check.That(data.ResourceName).Key("notification.0.enabled").Exists(),
check.That(data.ResourceName).Key("notification.0.contact_emails.0").HasValue("[email protected]"),
check.That(data.ResourceName).Key("notification.0.contact_emails.1").HasValue("[email protected]"),
),
},
})
}

func (d ConsumptionBudgetSubscriptionDataSource) basic(data acceptance.TestData) string {
config := ConsumptionBudgetSubscriptionResource{}.basic(data)
return fmt.Sprintf(`
%s
data "azurerm_consumption_budget_subscription" "test" {
name = azurerm_consumption_budget_subscription.test.name
subscription_id = azurerm_consumption_budget_subscription.test.subscription_id
}
`, config)
}
9 changes: 6 additions & 3 deletions internal/services/consumption/registration.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ const (
// as the core logic for the Consumption Budget resources is generic and has been
// extracted out of the specific Consumption Budget resources. These constants are
// used when the generic Consumption Budget functions require a resource name.
consumptionBudgetResourceGroupName = "azurerm_consumption_budget_resource_group"
consumptionBudgetSubscriptionName = "azurerm_consumption_budget_subscription"
consumptionBudgetResourceGroupName = "azurerm_consumption_budget_resource_group"
consumptionBudgetSubscriptionName = "azurerm_consumption_budget_subscription"
consumptionBudgetSubscriptionDataSourceName = "azurerm_consumption_budget_subscription"
)

type Registration struct{}
Expand All @@ -29,7 +30,9 @@ func (r Registration) WebsiteCategories() []string {

// SupportedDataSources returns the supported Data Sources supported by this Service
func (r Registration) SupportedDataSources() map[string]*pluginsdk.Resource {
return map[string]*pluginsdk.Resource{}
return map[string]*pluginsdk.Resource{
consumptionBudgetSubscriptionDataSourceName: resourceArmConsumptionBudgetSubscriptionDataSource(),
}
}

// SupportedResources returns the supported Resources supported by this Service
Expand Down
Loading

0 comments on commit 99e17f6

Please sign in to comment.