forked from openshift/machine-api-operator
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathaws.go
105 lines (89 loc) · 3.3 KB
/
aws.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
package main
import (
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/ec2/ec2iface"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
)
const (
// AwsCredsSecretIDKey is secret key containing AWS KeyId
AwsCredsSecretIDKey = "awsAccessKeyId"
// AwsCredsSecretAccessKey is secret key containing AWS Secret Key
AwsCredsSecretAccessKey = "awsSecretAccessKey"
)
// NewClient creates our client wrapper object for the actual AWS clients we use.
// For authentication the underlying clients will use either the cluster AWS credentials
// secret if defined (i.e. in the root cluster),
// otherwise the IAM profile of the master where the actuator will run. (target clusters)
func NewClient(kubeClient kubernetes.Interface, secretName, namespace, region string) (*AWSClient, error) {
awsConfig := &aws.Config{Region: aws.String(region)}
if secretName != "" {
secret, err := kubeClient.CoreV1().Secrets(namespace).Get(secretName, metav1.GetOptions{})
if err != nil {
return nil, err
}
accessKeyID, ok := secret.Data[AwsCredsSecretIDKey]
if !ok {
return nil, fmt.Errorf("AWS credentials secret %v did not contain key %v",
secretName, AwsCredsSecretIDKey)
}
secretAccessKey, ok := secret.Data[AwsCredsSecretAccessKey]
if !ok {
return nil, fmt.Errorf("AWS credentials secret %v did not contain key %v",
secretName, AwsCredsSecretAccessKey)
}
awsConfig.Credentials = credentials.NewStaticCredentials(
string(accessKeyID), string(secretAccessKey), "")
}
// Otherwise default to relying on the IAM role of the masters where the actuator is running:
s, err := session.NewSession(awsConfig)
if err != nil {
return nil, err
}
return &AWSClient{
ec2Client: ec2.New(s),
}, nil
}
// AWSClient is the client to retrieve aws instances
type AWSClient struct {
ec2Client ec2iface.EC2API
}
// GetInstances returns all instances that have a tag matching a clsuterid
func (client *AWSClient) getInstances(instanceStateFilter []*string, clusterID string) ([]*ec2.Instance, error) {
requestFilters := []*ec2.Filter{
{
Name: aws.String("tag:openshiftClusterID"),
Values: []*string{aws.String(clusterID)},
},
}
if instanceStateFilter != nil {
requestFilters = append(requestFilters, &ec2.Filter{
Name: aws.String("instance-state-name"),
Values: instanceStateFilter,
})
}
// Query instances with our machine's name, and in running/pending state.
request := &ec2.DescribeInstancesInput{
Filters: requestFilters,
}
result, err := client.ec2Client.DescribeInstances(request)
if err != nil {
return []*ec2.Instance{}, err
}
instances := make([]*ec2.Instance, 0, len(result.Reservations))
for _, reservation := range result.Reservations {
for _, instance := range reservation.Instances {
instances = append(instances, instance)
}
}
return instances, nil
}
// GetRunningInstances returns instances that match InstanceStateNameRunning or InstanceStateNamePending
func (client *AWSClient) GetRunningInstances(clusterID string) ([]*ec2.Instance, error) {
stateFilter := []*string{aws.String(ec2.InstanceStateNameRunning), aws.String(ec2.InstanceStateNamePending)}
return client.getInstances(stateFilter, clusterID)
}