-
Notifications
You must be signed in to change notification settings - Fork 787
/
aks.go
197 lines (171 loc) · 5.37 KB
/
aks.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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
package aks
import (
b64 "encoding/base64"
"encoding/json"
"github.com/jenkins-x/jx/pkg/log"
"github.com/jenkins-x/jx/pkg/util"
"strings"
)
// AzureRunner an Azure CLI runner to interact with Azure
type AzureRunner struct {
Runner util.Commander
}
type aks struct {
ID string `json:"id"`
URI string `json:"uri"`
Group string `json:"group"`
Name string `json:"name"`
}
type acr struct {
ID string `json:"id"`
URI string `json:"uri"`
Group string `json:"group"`
Name string `json:"name"`
}
type password struct {
Name string `json:"name"`
Value string `json:"value"`
}
type credential struct {
Passwords []password `json:"passwords"`
Username string `json:"username"`
}
type auth struct {
Auth string `json:"auth,omitempty"`
}
type config struct {
Auths map[string]*auth `json:"auths,omitempty"`
}
// NewAzureRunnerWithCommander specific the command runner for Azure CLI.
func NewAzureRunnerWithCommander(runner util.Commander) *AzureRunner {
return &AzureRunner{
Runner: runner,
}
}
// NewAzureRunner return a new AzureRunner
func NewAzureRunner() *AzureRunner {
runner := &util.Command{}
return NewAzureRunnerWithCommander(runner)
}
// GetClusterClient return AKS resource group, name and client ID.
func (az *AzureRunner) GetClusterClient(server string) (string, string, string, error) {
clientID := ""
group := ""
name := ""
clusterstr, err := az.azureCLI("aks", "list", "--query", "[].{uri:fqdn,id:servicePrincipalProfile.clientId,group:resourceGroup,name:name}")
if err != nil {
return group, name, clientID, err
}
clusters := []aks{}
err = json.Unmarshal([]byte(clusterstr), &clusters)
if err != nil {
return group, name, clientID, err
}
for _, v := range clusters {
if "https://"+v.URI+":443" == server {
clientID = v.ID
name = v.Name
group = v.Group
break
}
}
return group, name, clientID, err
}
// GetRegistry Return the docker registry config, registry login server and resource id, error
func (az *AzureRunner) GetRegistry(resourceGroup string, name string, registry string) (string, string, string, error) {
registryID := ""
loginServer := registry
dockerConfig := ""
if registry == "" {
loginServer = name + ".azurecr.io"
}
if !strings.HasSuffix(loginServer, "azurecr.io") {
return dockerConfig, loginServer, registryID, nil
}
acrRG, acrName, registryID, err := az.getRegistryID(loginServer)
if err != nil {
return dockerConfig, loginServer, registryID, err
}
// not exist and create a new one in resourceGroup
if registryID == "" {
acrRG = resourceGroup
acrName = name
registryID, loginServer, err = az.createRegistry(acrRG, acrName)
if err != nil {
return dockerConfig, loginServer, registryID, err
}
}
dockerConfig, err = az.getACRCredential(acrRG, acrName)
return dockerConfig, loginServer, registryID, err
}
// AssignRole Assign the client a reader role for registry.
func (az *AzureRunner) AssignRole(client string, registry string) {
if client == "" || registry == "" {
return
}
az.azureCLI("role", "assignment", "create", "--assignee", client, "--role", "Reader", "--scope", registry)
}
// getRegistryID returns acrRG, acrName, acrID, error
func (az *AzureRunner) getRegistryID(loginServer string) (string, string, string, error) {
acrRG := ""
acrName := ""
acrID := ""
acrList, err := az.azureCLI("acr", "list", "--query", "[].{uri:loginServer,id:id,name:name,group:resourceGroup}")
if err != nil {
log.Infof("Registry %s is not exist\n", util.ColorInfo(loginServer))
} else {
registries := []acr{}
err = json.Unmarshal([]byte(acrList), ®istries)
if err != nil {
return "", "", "", err
}
for _, v := range registries {
if v.URI == loginServer {
acrID = v.ID
acrRG = v.Group
acrName = v.Name
break
}
}
}
return acrRG, acrName, acrID, nil
}
// createRegistry return resource ID, login server and error
func (az *AzureRunner) createRegistry(resourceGroup string, name string) (string, string, error) {
registryID, err := az.azureCLI("acr", "create", "-g", resourceGroup, "-n", name, "--sku", "Standard", "--admin-enabled", "--query", "id", "-o", "tsv")
if err != nil {
log.Infof("Failed to create ACR %s in resource group %s\n", util.ColorInfo(name), util.ColorInfo(resourceGroup))
return "", "", err
}
return string(registryID), formatLoginServer(name), nil
}
// getACRCredential return .dockerconfig value for the ACR
func (az *AzureRunner) getACRCredential(resourceGroup string, name string) (string, error) {
credstr, err := az.azureCLI("acr", "credential", "show", "-g", resourceGroup, "-n", name)
if err != nil {
log.Infof("Failed to get credential for ACR %s in resource group %s\n", util.ColorInfo(name), util.ColorInfo(resourceGroup))
return "", err
}
cred := credential{}
err = json.Unmarshal([]byte(credstr), &cred)
if err != nil {
return "", err
}
newSecret := &auth{}
dockerConfig := &config{}
newSecret.Auth = b64.StdEncoding.EncodeToString([]byte(cred.Username + ":" + cred.Passwords[0].Value))
if dockerConfig.Auths == nil {
dockerConfig.Auths = map[string]*auth{}
}
dockerConfig.Auths[formatLoginServer(name)] = newSecret
dockerConfigStr, err := json.Marshal(dockerConfig)
return string(dockerConfigStr), err
}
func formatLoginServer(name string) string {
return name + ".azurecr.io"
}
func (az *AzureRunner) azureCLI(args ...string) (string, error) {
az.Runner.SetName("az")
az.Runner.SetArgs(args)
return az.Runner.RunWithoutRetry()
}