-
Notifications
You must be signed in to change notification settings - Fork 24
/
aks.go
144 lines (121 loc) · 3.72 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
// Package aks provides a datagatherer for AKS.
package aks
import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
aks "github.com/Azure/aks-engine/pkg/api/agentPoolOnlyApi/v20180331"
"github.com/jetstack/preflight/pkg/datagatherer"
)
// Config is the configuration for an AKS DataGatherer.
type Config struct {
// ClusterName is the name of the cluster in AKS.
ClusterName string `yaml:"cluster-name"`
// ResourceGroup is the resource group the cluster belongs to.
ResourceGroup string `yaml:"resource-group"`
// CredentialsPath is the path to the json file containing the credentials to access Azure APIs.
CredentialsPath string `yaml:"credentials-path"`
}
// validate checks if a Config is valid.
func (c *Config) validate() error {
errs := []string{}
msg := "%s should be a non empty string."
if c.ClusterName == "" {
errs = append(errs, fmt.Sprintf(msg, "ClusterName"))
}
if c.ResourceGroup == "" {
errs = append(errs, fmt.Sprintf(msg, "ResourceGroup"))
}
if c.CredentialsPath == "" {
errs = append(errs, fmt.Sprintf(msg, "CredentialsPath"))
}
if len(errs) == 0 {
return nil
}
return fmt.Errorf("invalid configuration: %s", strings.Join(errs, ";"))
}
// NewDataGatherer creates a new AKS DataGatherer. It performs a config validation.
func (c *Config) NewDataGatherer(ctx context.Context) (datagatherer.DataGatherer, error) {
if err := c.validate(); err != nil {
return nil, err
}
credentials, err := readCredentials(c.CredentialsPath)
if err != nil {
return nil, err
}
return &DataGatherer{
resourceGroup: c.ResourceGroup,
clusterName: c.ClusterName,
credentials: credentials,
}, nil
}
// AzureCredentials contains credentials needed to authenticate against Azure APIs.
type AzureCredentials struct {
AccessToken string `json:"accessToken"`
ExpiresOn string `json:"expiresOn"`
Subscription string `json:"subscription"`
Tenant string `json:"tenant"`
TokenType string `json:"tokenType"`
}
func readCredentials(path string) (*AzureCredentials, error) {
b, err := ioutil.ReadFile(path)
if err != nil {
return nil, err
}
var creds AzureCredentials
err = json.Unmarshal(b, &creds)
if err != nil {
return nil, err
}
if len(creds.Subscription) == 0 {
return nil, fmt.Errorf("'subscription' must not be empty")
}
if creds.TokenType != "Bearer" {
return nil, fmt.Errorf("'tokenType' %s is not supported", creds.TokenType)
}
return &creds, nil
}
// DataGatherer is a data-gatherer for AKS.
type DataGatherer struct {
resourceGroup string
clusterName string
credentials *AzureCredentials
}
// Info contains the data retrieved from AKS.
type Info struct {
// Cluster represents an AKS cluster.
Cluster *aks.ManagedCluster
}
// Fetch retrieves cluster information from AKS.
func (g *DataGatherer) Fetch() (interface{}, error) {
client := &http.Client{}
req, err := http.NewRequest("GET", fmt.Sprintf("https://management.azure.com/subscriptions/%s/resourceGroups/%s/providers/Microsoft.ContainerService/managedClusters/%s?api-version=2019-08-01", g.credentials.Subscription, g.resourceGroup, g.clusterName), nil)
if err != nil {
return nil, err
}
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", g.credentials.AccessToken))
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
errorBody, _ := ioutil.ReadAll(resp.Body)
return nil, fmt.Errorf("error retrieving cluster information (status code %d): %v", resp.StatusCode, string(errorBody))
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
var cluster aks.ManagedCluster
err = json.Unmarshal(body, &cluster)
if err != nil {
return nil, err
}
return &Info{
Cluster: &cluster,
}, nil
}