Skip to content

Commit

Permalink
Merge pull request #213 from hashicorp/billenracc
Browse files Browse the repository at this point in the history
commonids: add commonid for BillingAccountCustomerId
  • Loading branch information
catriona-m authored Feb 29, 2024
2 parents 4b90d3d + 3ef97de commit e7051a0
Show file tree
Hide file tree
Showing 2 changed files with 332 additions and 0 deletions.
117 changes: 117 additions & 0 deletions resourcemanager/commonids/billing_account_customer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package commonids

import (
"fmt"
"strings"

"github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids"
)

var _ resourceids.ResourceId = &BillingAccountCustomerId{}

// BillingAccountCustomerId is a struct representing the Resource ID for a Billing Account Customer
type BillingAccountCustomerId struct {
BillingAccountName string
CustomerName string
}

// NewBillingAccountCustomerID returns a new BillingAccountCustomerId struct
func NewBillingAccountCustomerID(billingAccountName string, customerName string) BillingAccountCustomerId {
return BillingAccountCustomerId{
BillingAccountName: billingAccountName,
CustomerName: customerName,
}
}

// ParseBillingAccountCustomerID parses 'input' into a BillingAccountCustomerId
func ParseBillingAccountCustomerID(input string) (*BillingAccountCustomerId, error) {
parser := resourceids.NewParserFromResourceIdType(&BillingAccountCustomerId{})
parsed, err := parser.Parse(input, false)
if err != nil {
return nil, fmt.Errorf("parsing %q: %+v", input, err)
}

id := BillingAccountCustomerId{}
if err = id.FromParseResult(*parsed); err != nil {
return nil, err
}

return &id, nil
}

// ParseBillingAccountCustomerIDInsensitively parses 'input' case-insensitively into a BillingAccountCustomerId
// note: this method should only be used for API response data and not user input
func ParseBillingAccountCustomerIDInsensitively(input string) (*BillingAccountCustomerId, error) {
parser := resourceids.NewParserFromResourceIdType(&BillingAccountCustomerId{})
parsed, err := parser.Parse(input, true)
if err != nil {
return nil, fmt.Errorf("parsing %q: %+v", input, err)
}

id := BillingAccountCustomerId{}
if err = id.FromParseResult(*parsed); err != nil {
return nil, err
}

return &id, nil
}

func (id *BillingAccountCustomerId) FromParseResult(input resourceids.ParseResult) error {

var ok bool

if id.BillingAccountName, ok = input.Parsed["billingAccountName"]; !ok {
return resourceids.NewSegmentNotSpecifiedError(id, "billingAccountName", input)
}

if id.CustomerName, ok = input.Parsed["customerName"]; !ok {
return resourceids.NewSegmentNotSpecifiedError(id, "customerName", input)
}

return nil
}

// ValidateBillingAccountCustomerID checks that 'input' can be parsed as a Billing Account Customer ID
func ValidateBillingAccountCustomerID(input interface{}, key string) (warnings []string, errors []error) {
v, ok := input.(string)
if !ok {
errors = append(errors, fmt.Errorf("expected %q to be a string", key))
return
}

if _, err := ParseBillingAccountCustomerID(v); err != nil {
errors = append(errors, err)
}

return
}

// ID returns the formatted Billing Account Customer ID
func (id BillingAccountCustomerId) ID() string {
fmtString := "/providers/Microsoft.Billing/billingAccounts/%s/customers/%s"
return fmt.Sprintf(fmtString, id.BillingAccountName, id.CustomerName)
}

// Segments returns a slice of Resource ID Segments which comprise this Billing Account Customer ID
func (id BillingAccountCustomerId) Segments() []resourceids.Segment {
return []resourceids.Segment{
resourceids.StaticSegment("providers", "providers", "providers"),
resourceids.ResourceProviderSegment("resourceProvider", "Microsoft.Billing", "Microsoft.Billing"),
resourceids.StaticSegment("billingAccounts", "billingAccounts", "billingAccounts"),
resourceids.UserSpecifiedSegment("billingAccountName", "billingAccountValue"),
resourceids.StaticSegment("customers", "customers", "customers"),
resourceids.UserSpecifiedSegment("customerName", "customerValue"),
}
}

// String returns a human-readable description of this Billing Account Customer ID
func (id BillingAccountCustomerId) String() string {
components := []string{
fmt.Sprintf("Billing Account Name: %q", id.BillingAccountName),
fmt.Sprintf("Customer Name: %q", id.CustomerName),
}
return fmt.Sprintf("Billing Account Customer (%s)", strings.Join(components, "\n"))
}
215 changes: 215 additions & 0 deletions resourcemanager/commonids/billing_account_customer_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package commonids

import "testing"

func TestNewBillingAccountCustomerID(t *testing.T) {
id := NewBillingAccountCustomerID("billingAccountNameValue", "customerNameValue")

if id.BillingAccountName != "billingAccountNameValue" {
t.Fatalf("Expected %q but got %q for Segment 'BillingAccountName'", "billingAccountNameValue", id.BillingAccountName)
}

if id.CustomerName != "customerNameValue" {
t.Fatalf("Expected %q but got %q for Segment 'CustomerName'", "customerNameValue", id.CustomerName)
}

}

func TestFormatBillingAccountCustomerID(t *testing.T) {
actual := NewBillingAccountCustomerID("billingAccountNameValue", "customerNameValue").ID()
expected := "/providers/Microsoft.Billing/billingAccounts/billingAccountNameValue/customers/customerNameValue"
if actual != expected {
t.Fatalf("Expected the Formatted ID to be %q but got %q", expected, actual)
}
}

func TestParseBillingAccountCustomerID(t *testing.T) {
testData := []struct {
Input string
Error bool
Expected *BillingAccountCustomerId
}{
{
// Incomplete URI
Input: "",
Error: true,
},
{
// Incomplete URI
Input: "/providers",
Error: true,
},
{
// Incomplete URI
Input: "/providers/Microsoft.Billing",
Error: true,
},
{
// Incomplete URI
Input: "/providers/Microsoft.Billing/billingAccounts",
Error: true,
},
{
// Incomplete URI
Input: "/providers/Microsoft.Billing/billingAccounts/billingAccountNameValue",
Error: true,
},
{
// Valid URI
Input: "/providers/Microsoft.Billing/billingAccounts/billingAccountNameValue/customers/customerNameValue",
Expected: &BillingAccountCustomerId{
BillingAccountName: "billingAccountNameValue",
CustomerName: "customerNameValue",
},
},
{
// Invalid (Valid Uri with Extra segment)
Input: "/providers/Microsoft.Billing/billingAccounts/billingAccountNameValue/customers/customerNameValue/extra",
Error: true,
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing %q", v.Input)

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

t.Fatalf("Expect a value but got an error: %+v", 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.CustomerName != v.Expected.CustomerName {
t.Fatalf("Expected %q but got %q for CustomerName", v.Expected.CustomerName, actual.CustomerName)
}
}
}

func TestParseBillingAccountCustomerIDInsensitively(t *testing.T) {
testData := []struct {
Input string
Error bool
Expected *BillingAccountCustomerId
}{
{
// Incomplete URI
Input: "",
Error: true,
},
{
// Incomplete URI
Input: "/providers",
Error: true,
},
{
// Incomplete URI (Insensitively)
Input: "/pRoVideRs",
Error: true,
},
{
// Incomplete URI
Input: "/providers/Microsoft.Billing",
Error: true,
},
{
// Incomplete URI (Insensitively)
Input: "/ProvIders/MicroSOFT.biLLing",
Error: true,
},
{
// Incomplete URI
Input: "/providers/Microsoft.Billing/billingAccounts",
Error: true,
},
{
// Incomplete URI (Insensitively)
Input: "/pRoVideRs/MiCrOsOfT.biLLing/BillInGAccouNts",
Error: true,
},
{
// Incomplete URI
Input: "/providers/Microsoft.Billing/billingAccounts/billingAccountNameValue",
Error: true,
},
{
// Incomplete URI (Insensitively)
Input: "/pRoVideRs/MiCrOsOfT.biLLing/BillInGAccouNts/BillingAcCOUNTNameValue",
Error: true,
},
{
// Valid URI
Input: "/providers/Microsoft.Billing/billingAccounts/billingAccountNameValue/customers/customerNameValue",
Expected: &BillingAccountCustomerId{
BillingAccountName: "billingAccountNameValue",
CustomerName: "customerNameValue",
},
},
{
// Valid URI (Insensitively)
Input: "/ProvIdErs/MIcroSoft.Billing/billingACcOunts/billingAccOuntNameVaLue/Customers/CustomerNaMevALue",
Expected: &BillingAccountCustomerId{
BillingAccountName: "billingAccOuntNameVaLue",
CustomerName: "CustomerNaMevALue",
},
},
{
// Invalid (Valid Uri with Extra segment)
Input: "/providers/Microsoft.Billing/billingAccounts/billingAccountNameValue/customers/customerNameValue/extra",
Error: true,
},
{
// Invalid (Valid Uri with Extra segment)
Input: "/ProvIdErs/MIcroSoft.Billing/billingACcOunts/billingAccOuntNameVaLue/Customers/CustomerNaMevAlue/exTra",
Error: true,
},
}
for _, v := range testData {
t.Logf("[DEBUG] Testing %q", v.Input)

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

t.Fatalf("Expect a value but got an error: %+v", 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.CustomerName != v.Expected.CustomerName {
t.Fatalf("Expected %q but got %q for CustomerName", v.Expected.CustomerName, actual.CustomerName)
}
}
}

func TestSegmentsForBillingAccountCustomerId(t *testing.T) {
segments := BillingAccountCustomerId{}.Segments()
if len(segments) == 0 {
t.Fatalf("BillingAccountCustomerId has no segments")
}

uniqueNames := make(map[string]struct{}, 0)
for _, segment := range segments {
uniqueNames[segment.Name] = struct{}{}
}
if len(uniqueNames) != len(segments) {
t.Fatalf("Expected the Segments to be unique but got %q unique segments and %d total segments", len(uniqueNames), len(segments))
}
}

0 comments on commit e7051a0

Please sign in to comment.