-
Notifications
You must be signed in to change notification settings - Fork 102
/
gke.go
138 lines (117 loc) · 4.43 KB
/
gke.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 2019 The Crossplane Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package gke
import (
"context"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
"google.golang.org/api/container/v1"
"google.golang.org/api/option"
computev1alpha2 "github.com/crossplaneio/stack-gcp/apis/compute/v1alpha2"
gcp "github.com/crossplaneio/stack-gcp/pkg/clients"
)
const (
// DefaultScope used by the GKE API.
DefaultScope = container.CloudPlatformScope
// TODO(negz): Is this username special? I can't see any ClusterRoleBindings
// that bind it to a role.
adminUser = "admin"
)
// Client interface to perform cluster operations
type Client interface {
CreateCluster(string, computev1alpha2.GKEClusterSpec) (*container.Cluster, error)
GetCluster(zone, name string) (*container.Cluster, error)
DeleteCluster(zone, name string) error
}
// ClusterClient implementation
type ClusterClient struct {
creds *google.Credentials
client *container.Service
}
// NewClusterClient return new instance of the Client based on credentials
func NewClusterClient(ctx context.Context, creds *google.Credentials) (*ClusterClient, error) {
client, err := container.NewService(ctx, option.WithHTTPClient(oauth2.NewClient(context.Background(), creds.TokenSource)))
if err != nil {
return nil, err
}
return &ClusterClient{
creds: creds,
client: client,
}, nil
}
// CreateCluster creates a new GKE cluster.
func (c *ClusterClient) CreateCluster(name string, spec computev1alpha2.GKEClusterSpec) (*container.Cluster, error) {
cr := &container.CreateClusterRequest{
Cluster: &container.Cluster{
Name: name,
InitialClusterVersion: spec.ClusterVersion,
InitialNodeCount: spec.NumNodes,
IpAllocationPolicy: &container.IPAllocationPolicy{
UseIpAliases: spec.EnableIPAlias,
CreateSubnetwork: spec.CreateSubnetwork,
NodeIpv4CidrBlock: spec.NodeIPV4CIDR,
ClusterIpv4CidrBlock: spec.ClusterIPV4CIDR,
ServicesIpv4CidrBlock: spec.ServiceIPV4CIDR,
ServicesSecondaryRangeName: spec.ServicesSecondaryRangeName,
ClusterSecondaryRangeName: spec.ClusterSecondaryRangeName,
},
NodeConfig: &container.NodeConfig{
MachineType: spec.MachineType,
OauthScopes: spec.Scopes,
},
ResourceLabels: spec.Labels,
Zone: spec.Zone,
Network: spec.Network,
Subnetwork: spec.Subnetwork,
// As of Kubernetes 1.12 GKE must be asked to generate a client cert
// that will be available via the GKE MasterAuth API. The certificate is
// generated with CN=client - a user with no RBAC permissions. Instead
// we user basic auth, which is still granted full admin privileges.
MasterAuth: &container.MasterAuth{
Username: adminUser,
ClientCertificateConfig: &container.ClientCertificateConfig{
IssueClientCertificate: false,
},
},
},
ProjectId: c.creds.ProjectID,
Zone: spec.Zone,
}
if _, err := c.client.Projects.Zones.Clusters.Create(cr.ProjectId, spec.Zone, cr).Do(); err != nil {
return nil, err
}
return c.GetCluster(spec.Zone, name)
}
// GetCluster retrieve GKE Cluster based on provided zone and name
func (c *ClusterClient) GetCluster(zone, name string) (*container.Cluster, error) {
return c.client.Projects.Zones.Clusters.Get(c.creds.ProjectID, zone, name).Do()
}
// DeleteCluster in the given zone with the given name
func (c *ClusterClient) DeleteCluster(zone, name string) error {
_, err := c.client.Projects.Zones.Clusters.Delete(c.creds.ProjectID, zone, name).Do()
if err != nil {
if gcp.IsErrorNotFound(err) {
return nil
}
return err
}
return nil
}
// DefaultKubernetesVersion is the default Kubernetes Cluster version supported by GKE for given project/zone
func (c *ClusterClient) DefaultKubernetesVersion(zone string) (string, error) {
sc, err := c.client.Projects.Zones.GetServerconfig(c.creds.ProjectID, zone).Fields("validMasterVersions").Do()
if err != nil {
return "", err
}
return sc.DefaultClusterVersion, nil
}