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

commonids: add commonid for BillingAccountCustomerId #213

Merged
merged 1 commit into from
Feb 29, 2024
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
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))
}
}