Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: gcp kubernetes clusters and node pools #332

Merged
merged 6 commits into from
Jul 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ jobs:
go vet .
golint .

- name: Install gke-cloud-auth-plugin
run: |
echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key --keyring /usr/share/keyrings/cloud.google.gpg add -
sudo apt-get update && sudo apt-get install google-cloud-sdk-gke-gcloud-auth-plugin
gke-gcloud-auth-plugin --version

- name: Test
run: go test ./test/e2e -tags=e2e -timeout=180m -parallel 10
env:
Expand Down
14 changes: 13 additions & 1 deletion .github/workflows/pr-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,17 @@ jobs:
go vet .
golint .

- name: Set up Cloud SDK
uses: 'google-github-actions/setup-gcloud@v0'

- name: Authenticate to Gcloud
uses: 'google-github-actions/auth@v0'
with:
credentials_json: '${{ secrets.GOOGLE_CREDENTIALS }}'

- name: Install gke-cloud-auth-plugin
run: gcloud components install gke-gcloud-auth-plugin

- name: Test
run: go test ./test/e2e -tags=e2e -timeout=180m -parallel 10
env:
Expand All @@ -56,4 +67,5 @@ jobs:
ARM_CLIENT_SECRET: ${{ secrets.ARM_CLIENT_SECRET_E2E }}
ARM_SUBSCRIPTION_ID: ${{ secrets.ARM_SUBSCRIPTION_ID }}
ARM_TENANT_ID: ${{ secrets.ARM_TENANT_ID }}
GOOGLE_CREDENTIALS: ${{ secrets.GOOGLE_CREDENTIALS }}
GOOGLE_CREDENTIALS: ${{ secrets.GOOGLE_CREDENTIALS }}
GOOGLE_APPLICATION_CREDENTIALS: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS }}
222 changes: 157 additions & 65 deletions api/proto/resourcespb/kubernetes_cluster.pb.go

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions api/proto/resourcespb/kubernetes_cluster.proto
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,18 @@ message DeleteKubernetesClusterRequest {
string resource_id = 1;
}

message KubernetesClusterOverrides {
string project = 1;
}

message KubernetesClusterArgs {
common.ResourceCommonArgs common_parameters = 1;
string name = 2;
string service_cidr = 3;
string virtual_network_id = 4;

KubernetesNodePoolArgs default_node_pool = 5;
KubernetesClusterOverrides gcp_override = 6;
}

message KubernetesClusterResource {
Expand All @@ -42,6 +47,7 @@ message KubernetesClusterResource {
string service_cidr = 3;
KubernetesNodePoolResource default_node_pool = 4;
string virtual_network_id = 5;
KubernetesClusterOverrides gcp_override = 9;

// outputs
string endpoint = 6;
Expand Down
171 changes: 96 additions & 75 deletions api/proto/resourcespb/kubernetes_node_pool.pb.go

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions api/proto/resourcespb/kubernetes_node_pool.proto
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ message KubernetesNodePoolArgs {
int32 max_node_count = 7;
common.VmSize.Enum vm_size = 8;
int64 disk_size_gb = 9;
repeated int32 availability_zone = 13;

KubernetesNodePoolAwsOverride aws_override = 11;
KubernetesNodePoolAzureOverride azure_override = 12;

Expand All @@ -61,6 +63,8 @@ message KubernetesNodePoolResource {
int32 max_node_count = 7;
common.VmSize.Enum vm_size = 8;
int64 disk_size_gb = 9;
repeated int32 availability_zone = 13;

KubernetesNodePoolAwsOverride aws_override = 11;
KubernetesNodePoolAzureOverride azure_override = 12;

Expand Down
9 changes: 5 additions & 4 deletions resources/common/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,14 @@ func RandomString(n int) string {
// Prefix can be any size but will be sliced if bigger than 16 chars. Suffix can have 4 chars at most.
// Returns a string with at most 24 chars.
func UniqueId(prefix string, suffix string, formatFunc FormatFunc) string {
if len(suffix) > 4 {
validate.LogInternalError("suffix must be shorter than 4 chars")
if len(suffix) > 10 {
validate.LogInternalError("suffix must be shorter than 10 chars")
}
result := ""
formattedPrefix := formatFunc(prefix)
if len(formattedPrefix) > 16 {
result += formattedPrefix[:12] + generateHash(prefix)
maxPrefixLen := 20 - len(suffix)
if len(formattedPrefix) > maxPrefixLen {
result += formattedPrefix[:maxPrefixLen] + generateHash(prefix)
} else {
result += formattedPrefix
}
Expand Down
9 changes: 9 additions & 0 deletions resources/output/iam/gcp_service_account.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package iam

import "github.com/multycloud/multy/resources/common"

type GoogleServiceAccount struct {
*common.GcpResource `hcl:",squash" default:"name=google_service_account"`
AccountId string `hcl:"account_id"`
DisplayName string `hcl:"display_name"`
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ type AzureKubernetesNodePool struct {
EnableAutoScaling bool `hcl:"enable_auto_scaling"`
VmSize string `hcl:"vm_size"`
VirtualNetworkSubnetId string `hcl:"vnet_subnet_id,expr"`
Zones []string `hcl:"zones" hcle:"omitempty"`
}
36 changes: 36 additions & 0 deletions resources/output/kubernetes_node_pool/gcp_gke_node_pool.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package kubernetes_node_pool

import "github.com/multycloud/multy/resources/common"

type GoogleContainerNodePool struct {
*common.GcpResource `hcl:",squash" default:"name=google_container_node_pool"`
Cluster string `hcl:"cluster,expr"` //expr
InitialNodeCount int `hcl:"initial_node_count"`
NodeLocations []string `hcl:"node_locations" hcle:"omitempty"`
Autoscaling GoogleContainerNodePoolAutoScaling `hcl:"autoscaling"`
NodeConfig GoogleContainerNodeConfig `hcl:"node_config"`
NetworkConfig GoogleContainerNetworkConfig `hcl:"network_config" hcle:"omitempty"`
}

type GoogleContainerNodePoolAutoScaling struct {
MinNodeCount int `hcl:"min_node_count"`
MaxNodeCount int `hcl:"max_node_count"`
}

type GoogleContainerNodeConfig struct {
DiskSizeGb int `hcl:"disk_size_gb" hcle:"omitempty"`
DiskType string `hcl:"disk_type" hcle:"omitempty"`
ImageType string `hcl:"image_type" hcle:"omitempty"`
Labels map[string]string `hcl:"labels" hcle:"omitempty"`
MachineType string `hcl:"machine_type"`
Metadata map[string]string `hcl:"metadata" hcle:"omitempty"`
Tags []string `hcl:"tags" hcle:"omitempty"`

ServiceAccount string `hcl:"service_account,expr"`
OAuthScopes []string `hcl:"oauth_scopes"`
}

type GoogleContainerNetworkConfig struct {
CreatePodRange bool `hcl:"create_pod_range"`
PodIpv4CidrBlock string `hcl:"pod_ipv4_cidr_block"`
}
6 changes: 3 additions & 3 deletions resources/output/kubernetes_service/azure_aks.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ type AzureEksCluster struct {
NetworkProfile NetworkProfile `hcl:"network_profile"`

// outputs
KubeConfigRaw string `json:"kube_config_raw" hcle:"omitempty"`
KubeConfig []KubeConfig `json:"kube_config" hcle:"omitempty"`
KubeConfigRaw string `json:"kube_config_raw" hcle:"omitempty"`
KubeConfig []AzureKubeConfig `json:"kube_config" hcle:"omitempty"`
}

type NetworkProfile struct {
Expand All @@ -31,7 +31,7 @@ type NetworkProfile struct {
ServiceCidr string `hcl:"service_cidr"`
}

type KubeConfig struct {
type AzureKubeConfig struct {
Host string `json:"host" hcle:"omitempty"`
ClusterCaCertificate string `json:"cluster_ca_certificate" hcle:"omitempty"`
}
Expand Down
32 changes: 32 additions & 0 deletions resources/output/kubernetes_service/gcp_gke.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package kubernetes_service

import (
"github.com/multycloud/multy/resources/common"
"github.com/multycloud/multy/resources/output/kubernetes_node_pool"
)

type GoogleContainerCluster struct {
*common.GcpResource `hcl:",squash" default:"name=google_container_cluster"`
RemoveDefaultNodePool bool `hcl:"remove_default_node_pool"`
InitialNodeCount int `hcl:"initial_node_count"`
Subnetwork string `hcl:"subnetwork,expr"`
Network string `hcl:"network,expr"`
IpAllocationPolicy GoogleContainerClusterIpAllocationPolicy `hcl:"ip_allocation_policy"`
Location string `hcl:"location"`
NodeConfig kubernetes_node_pool.GoogleContainerNodeConfig `hcl:"node_config"`

// outputs
Endpoint string `json:"endpoint" hcle:"omitempty"`
MasterAuth []GoogleContainerClusterAuth `json:"master_auth" hcle:"omitempty"`
}

type GoogleContainerClusterAuth struct {
ClusterCaCertificate string `json:"cluster_ca_certificate"`
ClientCertificate string `json:"client_certificate"`
ClientKey string `json:"client_key"`
}

type GoogleContainerClusterIpAllocationPolicy struct {
//ClusterIpv4CidrBlock string `hcl:"cluster_ipv_4_cidr_block"`
ServicesIpv4CidrBlock string `hcl:"services_ipv4_cidr_block"`
}
46 changes: 46 additions & 0 deletions resources/output/kubernetes_service/kube_config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package kubernetes_service

type KubeConfig struct {
ApiVersion string `yaml:"apiVersion"`
Clusters []NamedKubeConfigCluster `yaml:"clusters"`
Contexts []NamedKubeConfigContext `yaml:"contexts"`
CurrentContext string `yaml:"current-context"`
Users []KubeConfigUser `yaml:"users"`
Kind string `yaml:"kind"`
}

type NamedKubeConfigCluster struct {
Name string `yaml:"name"`
Cluster KubeConfigCluster `yaml:"cluster"`
}

type KubeConfigCluster struct {
CertificateAuthorityData string `yaml:"certificate-authority-data"`
Server string `yaml:"server"`
}

type NamedKubeConfigContext struct {
Name string `yaml:"name"`
Context KubeConfigContext `yaml:"context"`
}

type KubeConfigContext struct {
User string `yaml:"user"`
Cluster string `yaml:"cluster"`
}

type KubeConfigUser struct {
Name string `yaml:"name"`
User struct {
Exec KubeConfigExec `yaml:"exec"`
} `yaml:"user"`
}

type KubeConfigExec struct {
ApiVersion string `yaml:"apiVersion"`
Command string `yaml:"command"`
Args []string `yaml:"args,omitempty"`
InteractiveMode string `yaml:"interactiveMode"`
ProvideClusterInfo bool `yaml:"provideClusterInfo,omitempty"`
InstallHint string `yaml:"installHint,omitempty"`
}
60 changes: 9 additions & 51 deletions resources/types/aws/kubernetes_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,83 +30,41 @@ func InitKubernetesCluster(r *types.KubernetesCluster) resources.ResourceTransla
return AwsKubernetesCluster{r}
}

type KubeConfig struct {
ApiVersion string `yaml:"apiVersion"`
Clusters []NamedKubeConfigCluster `yaml:"clusters"`
Contexts []NamedKubeConfigContext `yaml:"contexts"`
CurrentContext string `yaml:"current-context"`
Users []KubeConfigUser `yaml:"users"`
Kind string `yaml:"kind"`
}

type NamedKubeConfigCluster struct {
Name string `yaml:"name"`
Cluster KubeConfigCluster `yaml:"cluster"`
}

type KubeConfigCluster struct {
CertificateAuthorityData string `yaml:"certificate-authority-data"`
Server string `yaml:"server"`
}

type NamedKubeConfigContext struct {
Name string `yaml:"name"`
Context KubeConfigContext `yaml:"context"`
}

type KubeConfigContext struct {
User string `yaml:"user"`
Cluster string `yaml:"cluster"`
}

type KubeConfigUser struct {
Name string `yaml:"name"`
User struct {
Exec KubeConfigExec `yaml:"exec"`
} `yaml:"user"`
}

type KubeConfigExec struct {
ApiVersion string `yaml:"apiVersion"`
Command string `yaml:"command"`
Args []string `yaml:"args"`
InteractiveMode string `yaml:"interactiveMode"`
}

func createKubeConfig(clusterName string, certData string, endpoint string, awsRegion string) (string, error) {
username := fmt.Sprintf("clusterUser_%s", clusterName)
kubeConfig := &KubeConfig{
kubeConfig := &kubernetes_service.KubeConfig{
ApiVersion: "v1",
Kind: "Config",
Clusters: []NamedKubeConfigCluster{
Clusters: []kubernetes_service.NamedKubeConfigCluster{
{
Name: clusterName,
Cluster: KubeConfigCluster{
Cluster: kubernetes_service.KubeConfigCluster{
CertificateAuthorityData: certData,
Server: endpoint,
},
},
},
Contexts: []NamedKubeConfigContext{
Contexts: []kubernetes_service.NamedKubeConfigContext{
{
Name: clusterName,
Context: KubeConfigContext{
Context: kubernetes_service.KubeConfigContext{
User: username,
Cluster: clusterName,
},
},
},
Users: []KubeConfigUser{
Users: []kubernetes_service.KubeConfigUser{
{
Name: username,
User: struct {
Exec KubeConfigExec `yaml:"exec"`
Exec kubernetes_service.KubeConfigExec `yaml:"exec"`
}{
Exec: KubeConfigExec{
Exec: kubernetes_service.KubeConfigExec{
ApiVersion: "client.authentication.k8s.io/v1beta1",
Command: "aws",
Args: []string{"--region", awsRegion, "eks", "get-token", "--cluster-name", clusterName},
InteractiveMode: "IfAvailable",
InstallHint: "Install aws cli for use with kubectl by following\n\t\t\t\thttps://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html",
},
},
},
Expand Down
16 changes: 14 additions & 2 deletions resources/types/aws/kubernetes_node_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,26 @@ func (r AwsKubernetesNodePool) FromState(state *output.TfState) (*resourcespb.Ku
MaxNodeCount: r.Args.MaxNodeCount,
VmSize: r.Args.VmSize,
DiskSizeGb: r.Args.DiskSizeGb,
Labels: r.Args.Labels,
AvailabilityZone: r.Args.AvailabilityZone,
AwsOverride: r.Args.AwsOverride,
AzureOverride: r.Args.AzureOverride,
Labels: r.Args.Labels,
}, nil
}

func (r AwsKubernetesNodePool) Translate(_ resources.MultyContext) ([]output.TfBlock, error) {
subnetIds := AwsSubnet{r.Subnet}.GetSubnetIds()
var subnetIds []string
if len(r.Args.AvailabilityZone) == 0 {
subnetIds = AwsSubnet{r.Subnet}.GetSubnetIds()
} else {
for _, zone := range r.Args.AvailabilityZone {
id, err := AwsSubnet{r.Subnet}.GetSubnetId(zone)
if err != nil {
return nil, err
}
subnetIds = append(subnetIds, id)
}
}

var instanceTypes []string
if r.Args.AwsOverride.GetInstanceTypes() != nil {
Expand Down
Loading