-
Notifications
You must be signed in to change notification settings - Fork 4.7k
/
Copy pathhelpers.go
138 lines (107 loc) · 3.36 KB
/
helpers.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
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package client
import (
"context"
"fmt"
"log"
"sync"
"github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2021-09-01/storage" // nolint: staticcheck
"github.com/hashicorp/go-azure-helpers/resourcemanager/commonids"
)
var (
storageAccountsCache = map[string]accountDetails{}
accountsLock = sync.RWMutex{}
credentialsLock = sync.RWMutex{}
)
type accountDetails struct {
ID string
ResourceGroup string
Properties *storage.AccountProperties
accountKey *string
name string
}
func (ad *accountDetails) AccountKey(ctx context.Context, client Client) (*string, error) {
credentialsLock.Lock()
defer credentialsLock.Unlock()
if ad.accountKey != nil {
return ad.accountKey, nil
}
log.Printf("[DEBUG] Cache Miss - looking up the account key for storage account %q..", ad.name)
props, err := client.AccountsClient.ListKeys(ctx, ad.ResourceGroup, ad.name, storage.ListKeyExpandKerb)
if err != nil {
return nil, fmt.Errorf("Listing Keys for Storage Account %q (Resource Group %q): %+v", ad.name, ad.ResourceGroup, err)
}
if props.Keys == nil || len(*props.Keys) == 0 || (*props.Keys)[0].Value == nil {
return nil, fmt.Errorf("Keys were nil for Storage Account %q (Resource Group %q): %+v", ad.name, ad.ResourceGroup, err)
}
keys := *props.Keys
ad.accountKey = keys[0].Value
// force-cache this
storageAccountsCache[ad.name] = *ad
return ad.accountKey, nil
}
func (client Client) AddToCache(accountName string, props storage.Account) error {
accountsLock.Lock()
defer accountsLock.Unlock()
account, err := populateAccountDetails(accountName, props)
if err != nil {
return err
}
storageAccountsCache[accountName] = *account
return nil
}
func (client Client) RemoveAccountFromCache(accountName string) {
accountsLock.Lock()
delete(storageAccountsCache, accountName)
accountsLock.Unlock()
}
func (client Client) FindAccount(ctx context.Context, accountName string) (*accountDetails, error) {
accountsLock.Lock()
defer accountsLock.Unlock()
if existing, ok := storageAccountsCache[accountName]; ok {
return &existing, nil
}
accountsPage, err := client.AccountsClient.List(ctx)
if err != nil {
return nil, fmt.Errorf("retrieving storage accounts: %+v", err)
}
var accounts []storage.Account
for accountsPage.NotDone() {
accounts = append(accounts, accountsPage.Values()...)
err = accountsPage.NextWithContext(ctx)
if err != nil {
return nil, fmt.Errorf("retrieving next page of storage accounts: %+v", err)
}
}
for _, v := range accounts {
if v.Name == nil {
continue
}
account, err := populateAccountDetails(*v.Name, v)
if err != nil {
return nil, err
}
storageAccountsCache[*v.Name] = *account
}
if existing, ok := storageAccountsCache[accountName]; ok {
return &existing, nil
}
return nil, nil
}
func populateAccountDetails(accountName string, props storage.Account) (*accountDetails, error) {
if props.ID == nil {
return nil, fmt.Errorf("`id` was nil for Account %q", accountName)
}
accountId := *props.ID
id, err := commonids.ParseStorageAccountID(accountId)
if err != nil {
return nil, fmt.Errorf("parsing %q as a Resource ID: %+v", accountId, err)
}
return &accountDetails{
name: accountName,
ID: accountId,
ResourceGroup: id.ResourceGroupName,
Properties: props.AccountProperties,
}, nil
}