-
Notifications
You must be signed in to change notification settings - Fork 22
/
resource_id.go
155 lines (136 loc) · 4.69 KB
/
resource_id.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package accounts
import (
"fmt"
"net/url"
"strings"
"github.com/hashicorp/go-azure-helpers/lang/pointer"
"github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids"
)
type SubDomainType string
const (
BlobSubDomainType SubDomainType = "blob"
DataLakeStoreSubDomainType SubDomainType = "dfs"
FileSubDomainType SubDomainType = "file"
QueueSubDomainType SubDomainType = "queue"
TableSubDomainType SubDomainType = "table"
)
func PossibleValuesForSubDomainType() []SubDomainType {
return []SubDomainType{
BlobSubDomainType,
DataLakeStoreSubDomainType,
FileSubDomainType,
QueueSubDomainType,
TableSubDomainType,
}
}
// TODO: update this to implement `resourceids.ResourceId` once
// https://github.com/hashicorp/go-azure-helpers/issues/187 is fixed
var _ resourceids.Id = AccountId{}
type AccountId struct {
AccountName string
ZoneName *string
SubDomainType SubDomainType
DomainSuffix string
IsEdgeZone bool
}
func (a AccountId) ID() string {
components := []string{
a.AccountName,
}
if a.IsEdgeZone {
// Storage Accounts hosted in an Edge Zone
// `{accountname}.{component}.{edgezone}.edgestorage.azure.net`
components = append(components, string(a.SubDomainType))
if a.ZoneName != nil {
components = append(components, *a.ZoneName)
}
} else {
// Storage Accounts using a DNS Zone
// `{accountname}.{dnszone}.{component}.storage.azure.net`
// or a Regular Storage Account
// `{accountname}.{component}.core.windows.net`
if a.ZoneName != nil {
components = append(components, *a.ZoneName)
}
components = append(components, string(a.SubDomainType))
}
components = append(components, a.DomainSuffix)
return fmt.Sprintf("https://%s", strings.Join(components, "."))
}
func (a AccountId) String() string {
components := []string{
fmt.Sprintf("IsEdgeZone %t", a.IsEdgeZone),
fmt.Sprintf("ZoneName %q", pointer.From(a.ZoneName)),
fmt.Sprintf("Subdomain Type %q", string(a.SubDomainType)),
fmt.Sprintf("DomainSuffix %q", a.DomainSuffix),
}
return fmt.Sprintf("Account %q (%s)", a.AccountName, strings.Join(components, " / "))
}
func ParseAccountID(input, domainSuffix string) (*AccountId, error) {
uri, err := url.Parse(input)
if err != nil {
return nil, fmt.Errorf("parsing %q as a URL: %s", input, err)
}
if !strings.HasSuffix(uri.Host, domainSuffix) {
return nil, fmt.Errorf("expected the account %q to use a domain suffix of %q", uri.Host, domainSuffix)
}
// There's 3 different types of Storage Account ID:
// 1. Regular ol' Storage Accounts
// `{name}.{component}.core.windows.net` (e.g. `example1.blob.core.windows.net`)
// 2. Storage Accounts using a DNS Zone
// `{accountname}.{dnszone}.{component}.storage.azure.net`
// 3. Storage Accounts hosted in an Edge Zone
// `{accountname}.{component}.{edgezone}.edgestorage.azure.net`
// since both `dnszone` and `edgezone` are the only two identifiers, we need to check if `domainSuffix` includes `edge`
// to know how to treat these
hostName := strings.TrimSuffix(uri.Host, fmt.Sprintf(".%s", domainSuffix))
components := strings.Split(hostName, ".")
accountId := AccountId{
DomainSuffix: domainSuffix,
IsEdgeZone: strings.Contains(strings.ToLower(domainSuffix), "edge"),
}
if len(components) == 2 {
// this will be a regular Storage Account (e.g. `example1.blob.core.windows.net`)
accountId.AccountName = components[0]
subDomainType, err := parseSubDomainType(components[1])
if err != nil {
return nil, err
}
accountId.SubDomainType = *subDomainType
return &accountId, nil
}
if len(components) == 3 {
// This can either be a Zone'd Storage Account or a Storage Account within an Edge Zone
accountName := ""
subDomainTypeRaw := ""
zone := ""
if accountId.IsEdgeZone {
// `{accountname}.{component}.{edgezone}.edgestorage.azure.net`
accountName = components[0]
subDomainTypeRaw = components[1]
zone = components[2]
} else {
// `{accountname}.{dnszone}.{component}.storage.azure.net`
accountName = components[0]
zone = components[1]
subDomainTypeRaw = components[2]
}
accountId.AccountName = accountName
subDomainType, err := parseSubDomainType(subDomainTypeRaw)
if err != nil {
return nil, err
}
accountId.SubDomainType = *subDomainType
accountId.ZoneName = pointer.To(zone)
return &accountId, nil
}
return nil, fmt.Errorf("unknown storage account domain type %q", input)
}
func parseSubDomainType(input string) (*SubDomainType, error) {
for _, k := range PossibleValuesForSubDomainType() {
if strings.EqualFold(input, string(k)) {
return pointer.To(k), nil
}
}
return nil, fmt.Errorf("expected the subdomain type to be one of [%+v] but got %q", PossibleValuesForSubDomainType(), input)
}