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 - azurerm_cost_management_export #11612

Closed
wants to merge 14 commits into from
Closed
Show file tree
Hide file tree
Changes from 5 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
15 changes: 12 additions & 3 deletions azurerm/helpers/azure/resourceid.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ func ParseAzureResourceIDWithoutSubscription(id string) (*ResourceID, error) {
return nil, fmt.Errorf("The number of path segments is not divisible by 2 in %q", path)
}

var providers string

componentMap := make(map[string]string, len(components)/2)
for current := 0; current < len(components); current += 2 {
key := components[current]
Expand All @@ -124,16 +126,23 @@ func ParseAzureResourceIDWithoutSubscription(id string) (*ResourceID, error) {
if key == "" || value == "" {
return nil, fmt.Errorf("Key/Value cannot be empty strings. Key: '%s', Value: '%s'", key, value)
}
componentMap[key] = value

// Catch the providers before it can be overwritten by another "providers"
// value in the ID which is the case for the Cost Management Export resource
if key == "providers" && providers == "" {
providers = value
} else {
componentMap[key] = value
}
}

// Build up a TargetResourceID from the map
idObj := &ResourceID{}
idObj.Path = componentMap

// It is OK not to have a provider in the case of a resource group
if provider, ok := componentMap["providers"]; ok {
idObj.Provider = provider
if providers != "" {
idObj.Provider = providers
delete(componentMap, "providers")
}

Expand Down
51 changes: 51 additions & 0 deletions azurerm/internal/services/billing/parse/billing_account.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package parse

import (
"fmt"
"strings"

"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
)

type BillingAccountId struct {
Name string
}

func NewBillingAccountID(name string) BillingAccountId {
return BillingAccountId{
Name: name,
}
}

func (id BillingAccountId) String() string {
segments := []string{
fmt.Sprintf("Name %q", id.Name),
}
segmentsStr := strings.Join(segments, " / ")
return fmt.Sprintf("%s: (%s)", "Billing Account", segmentsStr)
}

func (id BillingAccountId) ID() string {
fmtString := "/providers/Microsoft.Billing/billingAccounts/%s"
return fmt.Sprintf(fmtString, id.Name)
}

// BillingAccountID parses a BillingAccount ID into an BillingAccountId struct
func BillingAccountID(input string) (*BillingAccountId, error) {
id, err := azure.ParseAzureResourceIDWithoutSubscription(input)
if err != nil {
return nil, err
}

resourceId := BillingAccountId{}

if resourceId.Name, err = id.PopSegment("billingAccounts"); err != nil {
return nil, err
}

if err := id.ValidateNoEmptySegments(input); err != nil {
return nil, err
}

return &resourceId, nil
}
80 changes: 80 additions & 0 deletions azurerm/internal/services/billing/parse/billing_account_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package parse

// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten

import (
"testing"

"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/resourceid"
)

var _ resourceid.Formatter = BillingAccountId{}

func TestBillingAccountIDFormatter(t *testing.T) {
actual := NewBillingAccountID("123456").ID()
expected := "/providers/Microsoft.Billing/billingAccounts/123456"
if actual != expected {
t.Fatalf("Expected %q but got %q", expected, actual)
}
}

func TestBillingAccountID(t *testing.T) {
testData := []struct {
Input string
Error bool
Expected *BillingAccountId
}{

{
// empty
Input: "",
Error: true,
},

{
// missing Name
Input: "/providers/Microsoft.Billing/",
Error: true,
},

{
// missing value for Name
Input: "/providers/Microsoft.Billing/billingAccounts/",
Error: true,
},

{
// valid
Input: "/providers/Microsoft.Billing/billingAccounts/123456",
Expected: &BillingAccountId{
Name: "123456",
},
},

{
// upper-cased
Input: "/PROVIDERS/MICROSOFT.BILLING/BILLINGACCOUNTS/123456",
Error: true,
},
}

for _, v := range testData {
t.Logf("[DEBUG] Testing %q", v.Input)

actual, err := BillingAccountID(v.Input)
if err != nil {
if v.Error {
continue
}

t.Fatalf("Expect a value but got an error: %s", err)
}
if v.Error {
t.Fatal("Expect an error but didn't get one")
}

if actual.Name != v.Expected.Name {
t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name)
}
}
}
57 changes: 57 additions & 0 deletions azurerm/internal/services/billing/parse/billing_profile.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package parse

import (
"fmt"
"strings"

"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
)

type BillingProfileId struct {
BillingAccountName string
Name string
}

func NewBillingProfileID(billingAccountName, name string) BillingProfileId {
return BillingProfileId{
BillingAccountName: billingAccountName,
Name: name,
}
}

func (id BillingProfileId) String() string {
segments := []string{
fmt.Sprintf("Name %q", id.Name),
fmt.Sprintf("Billing Account Name %q", id.BillingAccountName),
}
segmentsStr := strings.Join(segments, " / ")
return fmt.Sprintf("%s: (%s)", "Billing Profile", segmentsStr)
}

func (id BillingProfileId) ID() string {
fmtString := "/providers/Microsoft.Billing/billingAccounts/%s/billingProfiles/%s"
return fmt.Sprintf(fmtString, id.BillingAccountName, id.Name)
}

// BillingProfileID parses a BillingProfile ID into an BillingProfileId struct
func BillingProfileID(input string) (*BillingProfileId, error) {
id, err := azure.ParseAzureResourceIDWithoutSubscription(input)
if err != nil {
return nil, err
}

resourceId := BillingProfileId{}

if resourceId.BillingAccountName, err = id.PopSegment("billingAccounts"); err != nil {
return nil, err
}
if resourceId.Name, err = id.PopSegment("billingProfiles"); err != nil {
return nil, err
}

if err := id.ValidateNoEmptySegments(input); err != nil {
return nil, err
}

return &resourceId, nil
}
96 changes: 96 additions & 0 deletions azurerm/internal/services/billing/parse/billing_profile_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package parse

// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten

import (
"testing"

"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/resourceid"
)

var _ resourceid.Formatter = BillingProfileId{}

func TestBillingProfileIDFormatter(t *testing.T) {
actual := NewBillingProfileID("123456", "123456").ID()
expected := "/providers/Microsoft.Billing/billingAccounts/123456/billingProfiles/123456"
if actual != expected {
t.Fatalf("Expected %q but got %q", expected, actual)
}
}

func TestBillingProfileID(t *testing.T) {
testData := []struct {
Input string
Error bool
Expected *BillingProfileId
}{

{
// empty
Input: "",
Error: true,
},

{
// missing BillingAccountName
Input: "/providers/Microsoft.Billing/",
Error: true,
},

{
// missing value for BillingAccountName
Input: "/providers/Microsoft.Billing/billingAccounts/",
Error: true,
},

{
// missing Name
Input: "/providers/Microsoft.Billing/billingAccounts/123456/",
Error: true,
},

{
// missing value for Name
Input: "/providers/Microsoft.Billing/billingAccounts/",
Error: true,
},

{
// valid
Input: "/providers/Microsoft.Billing/billingAccounts/123456/billingProfiles/123456",
Expected: &BillingProfileId{
BillingAccountName: "123456",
Name: "123456",
},
},

{
// upper-cased
Input: "/PROVIDERS/MICROSOFT.BILLING/BILLINGACCOUNTS/123456/BILLINGPROFILES/123456",
Error: true,
},
}

for _, v := range testData {
t.Logf("[DEBUG] Testing %q", v.Input)

actual, err := BillingProfileID(v.Input)
if err != nil {
if v.Error {
continue
}

t.Fatalf("Expect a value but got an error: %s", err)
}
if v.Error {
t.Fatal("Expect an error but didn't get one")
}

if actual.BillingAccountName != v.Expected.BillingAccountName {
t.Fatalf("Expected %q but got %q for BillingAccountName", v.Expected.BillingAccountName, actual.BillingAccountName)
}
if actual.Name != v.Expected.Name {
t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name)
}
}
}
57 changes: 57 additions & 0 deletions azurerm/internal/services/billing/parse/customer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package parse

import (
"fmt"
"strings"

"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
)

type CustomerId struct {
BillingAccountName string
Name string
}

func NewCustomerID(billingAccountName, name string) CustomerId {
return CustomerId{
BillingAccountName: billingAccountName,
Name: name,
}
}

func (id CustomerId) String() string {
segments := []string{
fmt.Sprintf("Name %q", id.Name),
fmt.Sprintf("Billing Account Name %q", id.BillingAccountName),
}
segmentsStr := strings.Join(segments, " / ")
return fmt.Sprintf("%s: (%s)", "Customer", segmentsStr)
}

func (id CustomerId) ID() string {
fmtString := "/providers/Microsoft.Billing/billingAccounts/%s/customers/%s"
return fmt.Sprintf(fmtString, id.BillingAccountName, id.Name)
}

// CustomerID parses a Customer ID into an CustomerId struct
func CustomerID(input string) (*CustomerId, error) {
id, err := azure.ParseAzureResourceIDWithoutSubscription(input)
if err != nil {
return nil, err
}

resourceId := CustomerId{}

if resourceId.BillingAccountName, err = id.PopSegment("billingAccounts"); err != nil {
return nil, err
}
if resourceId.Name, err = id.PopSegment("customers"); err != nil {
return nil, err
}

if err := id.ValidateNoEmptySegments(input); err != nil {
return nil, err
}

return &resourceId, nil
}
Loading