From d00419a5ddce713bfecd778a1ecd3f569306b586 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20M=C3=BCller?= Date: Sat, 11 Aug 2018 00:41:08 +0200 Subject: [PATCH 1/9] add template files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Manuel Müller --- .../templates/kubespray-aws-create-infra.tf | 193 ++++++++++++++++++ .../kubespray-aws-credentials.tfvars | 6 + configs/templates/kubespray-aws-output.tf | 28 +++ .../templates/kubespray-aws-terraform.tfvars | 23 +++ configs/templates/kubespray-aws-variables.tf | 105 ++++++++++ 5 files changed, 355 insertions(+) create mode 100644 configs/templates/kubespray-aws-create-infra.tf create mode 100644 configs/templates/kubespray-aws-credentials.tfvars create mode 100644 configs/templates/kubespray-aws-output.tf create mode 100644 configs/templates/kubespray-aws-terraform.tfvars create mode 100644 configs/templates/kubespray-aws-variables.tf diff --git a/configs/templates/kubespray-aws-create-infra.tf b/configs/templates/kubespray-aws-create-infra.tf new file mode 100644 index 0000000..50fe3a3 --- /dev/null +++ b/configs/templates/kubespray-aws-create-infra.tf @@ -0,0 +1,193 @@ +{{define "DistOS"}} +terraform { + required_version = ">= 0.8.7" +} + +provider "aws" { + access_key = "${var.AWS_ACCESS_KEY_ID}" + secret_key = "${var.AWS_SECRET_ACCESS_KEY}" + region = "${var.AWS_DEFAULT_REGION}" +} + +data "aws_availability_zones" "available" {} + +/* +* Calling modules who create the initial AWS VPC / AWS ELB +* and AWS IAM Roles for Kubernetes Deployment +*/ + +module "aws-vpc" { + source = "modules/vpc" + + aws_cluster_name = "${var.aws_cluster_name}" + aws_vpc_cidr_block = "${var.aws_vpc_cidr_block}" + aws_avail_zones="${slice(data.aws_availability_zones.available.names,0,2)}" + aws_cidr_subnets_private="${var.aws_cidr_subnets_private}" + aws_cidr_subnets_public="${var.aws_cidr_subnets_public}" + default_tags="${var.default_tags}" + +} + + +module "aws-elb" { + source = "modules/elb" + + aws_cluster_name="${var.aws_cluster_name}" + aws_vpc_id="${module.aws-vpc.aws_vpc_id}" + aws_avail_zones="${slice(data.aws_availability_zones.available.names,0,2)}" + aws_subnet_ids_public="${module.aws-vpc.aws_subnet_ids_public}" + aws_elb_api_port = "${var.aws_elb_api_port}" + k8s_secure_api_port = "${var.k8s_secure_api_port}" + default_tags="${var.default_tags}" + +} + +module "aws-iam" { + source = "modules/iam" + + aws_cluster_name="${var.aws_cluster_name}" +} + +/* +* Create Bastion Instances in AWS +* +*/ + +resource "aws_instance" "bastion-server" { + ami = {{.OS}} + instance_type = "${var.aws_bastion_size}" + count = "${length(var.aws_cidr_subnets_public)}" + associate_public_ip_address = true + availability_zone = "${element(slice(data.aws_availability_zones.available.names,0,2),count.index)}" + subnet_id = "${element(module.aws-vpc.aws_subnet_ids_public,count.index)}" + + + vpc_security_group_ids = [ "${module.aws-vpc.aws_security_group}" ] + + key_name = "${var.AWS_SSH_KEY_NAME}" + + tags = "${merge(var.default_tags, map( + "Name", "kubernetes-${var.aws_cluster_name}-bastion-${count.index}", + "Cluster", "${var.aws_cluster_name}", + "Role", "bastion-${var.aws_cluster_name}-${count.index}" + ))}" +} + + +/* +* Create K8s Master and worker nodes and etcd instances +* +*/ + +resource "aws_instance" "k8s-master" { + ami = {{.OS}} + instance_type = "${var.aws_kube_master_size}" + + count = "${var.aws_kube_master_num}" + + + availability_zone = "${element(slice(data.aws_availability_zones.available.names,0,2),count.index)}" + subnet_id = "${element(module.aws-vpc.aws_subnet_ids_private,count.index)}" + + + vpc_security_group_ids = [ "${module.aws-vpc.aws_security_group}" ] + + + iam_instance_profile = "${module.aws-iam.kube-master-profile}" + key_name = "${var.AWS_SSH_KEY_NAME}" + + + tags = "${merge(var.default_tags, map( + "Name", "kubernetes-${var.aws_cluster_name}-master${count.index}", + "kubernetes.io/cluster/${var.aws_cluster_name}", "member", + "Role", "master" + ))}" +} + +resource "aws_elb_attachment" "attach_master_nodes" { + count = "${var.aws_kube_master_num}" + elb = "${module.aws-elb.aws_elb_api_id}" + instance = "${element(aws_instance.k8s-master.*.id,count.index)}" +} + + +resource "aws_instance" "k8s-etcd" { + ami = {{.OS}} + instance_type = "${var.aws_etcd_size}" + + count = "${var.aws_etcd_num}" + + + availability_zone = "${element(slice(data.aws_availability_zones.available.names,0,2),count.index)}" + subnet_id = "${element(module.aws-vpc.aws_subnet_ids_private,count.index)}" + + + vpc_security_group_ids = [ "${module.aws-vpc.aws_security_group}" ] + + key_name = "${var.AWS_SSH_KEY_NAME}" + + tags = "${merge(var.default_tags, map( + "Name", "kubernetes-${var.aws_cluster_name}-etcd${count.index}", + "kubernetes.io/cluster/${var.aws_cluster_name}", "member", + "Role", "etcd" + ))}" + +} + + +resource "aws_instance" "k8s-worker" { + ami = {{.OS}} + instance_type = "${var.aws_kube_worker_size}" + + count = "${var.aws_kube_worker_num}" + + availability_zone = "${element(slice(data.aws_availability_zones.available.names,0,2),count.index)}" + subnet_id = "${element(module.aws-vpc.aws_subnet_ids_private,count.index)}" + + vpc_security_group_ids = [ "${module.aws-vpc.aws_security_group}" ] + + iam_instance_profile = "${module.aws-iam.kube-worker-profile}" + key_name = "${var.AWS_SSH_KEY_NAME}" + + + tags = "${merge(var.default_tags, map( + "Name", "kubernetes-${var.aws_cluster_name}-worker${count.index}", + "kubernetes.io/cluster/${var.aws_cluster_name}", "member", + "Role", "worker" + ))}" + +} + + + +/* +* Create Kubespray Inventory File +* +*/ +data "template_file" "inventory" { + template = "${file("${path.module}/templates/inventory.tpl")}" + + vars { + public_ip_address_bastion = "${join("\n",formatlist("bastion ansible_host=%s" , aws_instance.bastion-server.*.public_ip))}" + connection_strings_master = "${join("\n",formatlist("%s ansible_host=%s",aws_instance.k8s-master.*.tags.Name, aws_instance.k8s-master.*.private_ip))}" + connection_strings_node = "${join("\n", formatlist("%s ansible_host=%s", aws_instance.k8s-worker.*.tags.Name, aws_instance.k8s-worker.*.private_ip))}" + connection_strings_etcd = "${join("\n",formatlist("%s ansible_host=%s", aws_instance.k8s-etcd.*.tags.Name, aws_instance.k8s-etcd.*.private_ip))}" + list_master = "${join("\n",aws_instance.k8s-master.*.tags.Name)}" + list_node = "${join("\n",aws_instance.k8s-worker.*.tags.Name)}" + list_etcd = "${join("\n",aws_instance.k8s-etcd.*.tags.Name)}" + elb_api_fqdn = "apiserver_loadbalancer_domain_name=\"${module.aws-elb.aws_elb_api_fqdn}\"" + } + +} + +resource "null_resource" "inventories" { + provisioner "local-exec" { + command = "echo '${data.template_file.inventory.rendered}' > ../../../inventory/hosts" + } + + triggers { + template = "${data.template_file.inventory.rendered}" + } + +} +{{end}} \ No newline at end of file diff --git a/configs/templates/kubespray-aws-credentials.tfvars b/configs/templates/kubespray-aws-credentials.tfvars new file mode 100644 index 0000000..effd659 --- /dev/null +++ b/configs/templates/kubespray-aws-credentials.tfvars @@ -0,0 +1,6 @@ +{{define "AwsCredentials"}} +AWS_ACCESS_KEY_ID = {{.AwsAccessKeyID}} +AWS_SECRET_ACCESS_KEY = {{.AwsSecretKey}} +AWS_SSH_KEY_NAME = {{.AwsAccessSSHKey}} +AWS_DEFAULT_REGION = {{.AwsDefaultRegion}} +{{end}} \ No newline at end of file diff --git a/configs/templates/kubespray-aws-output.tf b/configs/templates/kubespray-aws-output.tf new file mode 100644 index 0000000..5125030 --- /dev/null +++ b/configs/templates/kubespray-aws-output.tf @@ -0,0 +1,28 @@ +output "bastion_ip" { + value = "${join("\n", aws_instance.bastion-server.*.public_ip)}" +} + +output "masters" { + value = "${join("\n", aws_instance.k8s-master.*.private_ip)}" +} + +output "workers" { + value = "${join("\n", aws_instance.k8s-worker.*.private_ip)}" +} + +output "etcd" { + value = "${join("\n", aws_instance.k8s-etcd.*.private_ip)}" +} + + +output "aws_elb_api_fqdn" { + value = "${module.aws-elb.aws_elb_api_fqdn}:${var.aws_elb_api_port}" +} + +output "inventory" { + value = "${data.template_file.inventory.rendered}" +} + +output "default_tags" { + value = "${var.default_tags}" +} diff --git a/configs/templates/kubespray-aws-terraform.tfvars b/configs/templates/kubespray-aws-terraform.tfvars new file mode 100644 index 0000000..0c16376 --- /dev/null +++ b/configs/templates/kubespray-aws-terraform.tfvars @@ -0,0 +1,23 @@ +{{define "ClusterConfig"}} +aws_cluster_name = {{.AwsClusterName}} +aws_vpc_cidr_block = {{.AwsVpcCidrBlock}} +aws_cidr_subnets_private = {{.AwsCidrSubnetsPrivat}} +aws_cidr_subnets_public = {{.AwsCidrSubnetsPubli}} + +aws_bastion_size = {{.AwsBastionSize}} +aws_kube_master_num = {{.AwsKubeMasterNu}} +aws_kube_master_size = {{.AwsKubeMasterSize}} +aws_etcd_num = {{.AwsEtcdNu}} + +aws_etcd_size = {{.AwsEtcdSize}} +aws_kube_worker_num = {{.AwsKubeWorkerNu}} +aws_kube_worker_size = {{.AwsKubeWorkerSize}} +aws_elb_api_port = {{.AwsElbAPIPor}} +k8s_secure_api_port = {{.K8sSecureAPIPor}} +kube_insecure_apiserver_address = {{.KubeInsecureApiserverAddress}} + +default_tags = { + Env = 'devtest', + Product = 'kubernetes' +} +{{end}} \ No newline at end of file diff --git a/configs/templates/kubespray-aws-variables.tf b/configs/templates/kubespray-aws-variables.tf new file mode 100644 index 0000000..567a3f2 --- /dev/null +++ b/configs/templates/kubespray-aws-variables.tf @@ -0,0 +1,105 @@ +variable "AWS_ACCESS_KEY_ID" { + description = "AWS Access Key" +} + +variable "AWS_SECRET_ACCESS_KEY" { + description = "AWS Secret Key" +} + +variable "AWS_SSH_KEY_NAME" { + description = "Name of the SSH keypair to use in AWS." +} + +variable "AWS_DEFAULT_REGION" { + description = "AWS Region" +} + +//General Cluster Settings + +variable "aws_cluster_name" { + description = "Name of AWS Cluster" +} +{{define "DistOS"}} +data "aws_ami" "distro" { + most_recent = true + + filter { + name = "name" + values = [{{.OS}}] + } + + filter { + name = "virtualization-type" + values = ["hvm"] + } + + owners = [{{.AmiOwner}}] #CoreOS +} +{{end}} +//AWS VPC Variables + +variable "aws_vpc_cidr_block" { + description = "CIDR Block for VPC" +} + +variable "aws_cidr_subnets_private" { + description = "CIDR Blocks for private subnets in Availability Zones" + type = "list" +} + +variable "aws_cidr_subnets_public" { + description = "CIDR Blocks for public subnets in Availability Zones" + type = "list" +} + +//AWS EC2 Settings + +variable "aws_bastion_size" { + description = "EC2 Instance Size of Bastion Host" +} + +/* +* AWS EC2 Settings +* The number should be divisable by the number of used +* AWS Availability Zones without an remainder. +*/ +variable "aws_kube_master_num" { + description = "Number of Kubernetes Master Nodes" +} + +variable "aws_kube_master_size" { + description = "Instance size of Kube Master Nodes" +} + +variable "aws_etcd_num" { + description = "Number of etcd Nodes" +} + +variable "aws_etcd_size" { + description = "Instance size of etcd Nodes" +} + +variable "aws_kube_worker_num" { + description = "Number of Kubernetes Worker Nodes" +} + +variable "aws_kube_worker_size" { + description = "Instance size of Kubernetes Worker Nodes" +} + +/* +* AWS ELB Settings +* +*/ +variable "aws_elb_api_port" { + description = "Port for AWS ELB" +} + +variable "k8s_secure_api_port" { + description = "Secure Port of K8S API Server" +} + +variable "default_tags" { + description = "Default tags for all resources" + type = "map" +} From c330aedb26e18dbc7e0a7c590e83f8d9240216d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20M=C3=BCller?= Date: Sat, 11 Aug 2018 00:42:02 +0200 Subject: [PATCH 2/9] add os helper functions for unix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Manuel Müller --- internal/cluster/oshelper/helper.go | 17 ++++++++ internal/cluster/oshelper/unixhelper.go | 53 +++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 internal/cluster/oshelper/helper.go create mode 100644 internal/cluster/oshelper/unixhelper.go diff --git a/internal/cluster/oshelper/helper.go b/internal/cluster/oshelper/helper.go new file mode 100644 index 0000000..9c37ba4 --- /dev/null +++ b/internal/cluster/oshelper/helper.go @@ -0,0 +1,17 @@ +package oshelper + +import "os/exec" + +type OSHelper interface { + GetOs() string + CheckDependency(dependecy string) bool + FatalLog(...interface{}) + Log(...interface{}) + Shell(...string) (*exec.Cmd, error) + FileInfo(file string) (string, error) +} + +func NewOSHelper() OSHelper { + // TODO check os and return the Helper + return UnixHelper{} +} diff --git a/internal/cluster/oshelper/unixhelper.go b/internal/cluster/oshelper/unixhelper.go new file mode 100644 index 0000000..fa77351 --- /dev/null +++ b/internal/cluster/oshelper/unixhelper.go @@ -0,0 +1,53 @@ +package oshelper + +import ( + "encoding/json" + "log" + "os" + "os/exec" + "strings" +) + +// UnixHelper provied some methods for unix +type UnixHelper struct { +} + +func (h UnixHelper) FatalLog(v ...interface{}) { + log.Fatal(v) +} + +func (h UnixHelper) Log(v ...interface{}) { + log.Print(v) +} + +func (h UnixHelper) FileInfo(file string) (string, error) { + fileInfo, err := os.Stat(file) + fileInfoJson, _ := json.Marshal(fileInfo) + return string(fileInfoJson), err +} + +func (h UnixHelper) Shell(v ...string) (*exec.Cmd, error) { + rr := exec.Command(strings.Join(v, " ")) + logString, err := rr.Output() + if err != nil { + h.FatalLog(err) + return rr, err + } + h.Log(string(logString)) + return rr, err +} + +func (h UnixHelper) GetOs() string { + return "unix" +} + +func (h UnixHelper) CheckDependency(dependecy string) bool { + _, err := exec.LookPath(dependecy) + if err != nil { + h.FatalLog(dependecy, " command not found, kindly check") + return false + } + + h.Log("Found", dependecy) + return true +} From dc8eb4742e8520537593329f4a5af5ab414f2dda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20M=C3=BCller?= Date: Sat, 11 Aug 2018 00:45:29 +0200 Subject: [PATCH 3/9] add general cluster stuff MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Manuel Müller --- internal/cluster/aws.go | 356 +++++++++++++++++++++--------------- internal/cluster/cluster.go | 47 +++++ 2 files changed, 257 insertions(+), 146 deletions(-) create mode 100644 internal/cluster/cluster.go diff --git a/internal/cluster/aws.go b/internal/cluster/aws.go index fbf0795..a1a003e 100644 --- a/internal/cluster/aws.go +++ b/internal/cluster/aws.go @@ -17,138 +17,134 @@ package cluster import ( "bufio" "fmt" + "html/template" "log" "net" "os" "os/exec" - "strconv" "strings" + "github.com/kubernauts/tk8/internal/cluster/oshelper" "github.com/spf13/viper" ) -var ec2IP string +// AWS is the main structer of the platform controller +type AWS struct { + Dists map[string]DistOS + Ec2IP string + Namespace string + OSHelper oshelper.OSHelper +} -func distSelect() (string, string) { - var sshUser, osLabel string +type AwsCredentials struct { + AwsAccessKeyID string + AwsSecretKey string + AwsAccessSSHKey string + AwsDefaultRegion string +} - centos := map[string]string{ - "user": "centos", - "ami_owner": "688023202711", - "os": "dcos-centos7", +// Init prepare some configs for the aws deployment +func (aws *AWS) Init() { + aws.Dists = DistOSMap + aws.OSHelper = oshelper.NewOSHelper() +} + +// create config files from templates +func (aws *AWS) createFileFromTemplate(templateName string, targetFileName string, awsInstanceOS string, data interface{}) bool { + file, err := os.Create(targetFileName) + if err != nil { + aws.OSHelper.FatalLog("Cannot create file", err) + return false } + defer file.Close() - ubuntu := map[string]string{ - "user": "ubuntu", - "ami_owner": "099720109477", - "os": "ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64", + template := template.New(awsInstanceOS) + template, err = template.Parse(templateName) + if err != nil { + aws.OSHelper.FatalLog(templateName, "for", awsInstanceOS, "could not parsed") + return false + } + if data == nil { + template.Execute(file, aws.Dists[awsInstanceOS]) + return true } + template.Execute(file, data) + return true + //TODO save StdOut as targetFileName +} +// load configs from viper +func (aws *AWS) getConfig() (string, string, string) { //Read Configuration File viper.SetConfigName("config") viper.AddConfigPath(".") verr := viper.ReadInConfig() // Find and read the config file if verr != nil { // Handle errors reading the config file - panic(fmt.Errorf("fatal error config file: %s", verr)) + log.Fatal("config could not readed") + return "", "", "" } - awsAmiID := viper.GetString("aws.ami_id") awsInstanceOS := viper.GetString("aws.os") - sshUser = viper.GetString("aws.ssh_user") - - // Think of a better way to do this - if awsInstanceOS != "" { - fmt.Println(awsInstanceOS) - switch awsInstanceOS { - case "centos": - exec.Command("sh", "-c", "sed -i \"\" -e 's/dcos-centos7/"+centos["os"]+"/g' ./kubespray/contrib/terraform/aws/variables.tf").Run() - exec.Command("sh", "-c", "sed -i \"\" -e 's/688023202711/"+centos["ami_owner"]+"/g' ./kubespray/contrib/terraform/aws/variables.tf").Run() - sshUser = centos["user"] - osLabel = "centos" - case "ubuntu": - exec.Command("sh", "-c", "sed -i \"\" -e 's#dcos-centos7#"+ubuntu["os"]+"#g' ./kubespray/contrib/terraform/aws/variables.tf").Run() - exec.Command("sh", "-c", "sed -i \"\" -e 's/688023202711/"+ubuntu["ami_owner"]+"/g' ./kubespray/contrib/terraform/aws/variables.tf").Run() - sshUser = ubuntu["user"] - osLabel = "ubuntu" - // Will only work with 'https://github.com/kubernetes-incubator/kubespray' - default: - sshUser = "core" - osLabel = "coreos" - return sshUser, osLabel - } - } else if awsAmiID != "" && sshUser != "" { - err := exec.Command("sh", "-c", "sed -i \"\" -e 's/${data.aws_ami.distro.id}/"+awsAmiID+"/g' ./kubespray/contrib/terraform/aws/create-infrastructure.tf").Run() - if err != nil { - log.Fatal("Cannot replace AMI ID in Infrastructure template", err) - } - osLabel = "Custom-AMI" - } else if awsAmiID != "" && sshUser == "" { - log.Fatal("SSH Username is required when using custom AMI") - return "", "" - } else { - log.Fatal("Provide either of AMI ID or OS in the config file.") - return "", "" - } - - return sshUser, osLabel + sshUser := viper.GetString("aws.ssh_user") + return awsAmiID, awsInstanceOS, sshUser } -func AWSCreate() { - // check if terraform is installed - terr, err := exec.LookPath("terraform") - if err != nil { - log.Fatal("Terraform command not found, kindly check") - } - fmt.Printf("Found terraform at %s\n", terr) - rr, err := exec.Command("terraform", "version").Output() - if err != nil { - log.Fatal(err) - } - fmt.Printf(string(rr)) - - // Check if credentials file exist, if it exists skip asking to input the AWS values - if _, err := os.Stat("./kubespray/contrib/terraform/aws/credentials.tfvars"); err == nil { - fmt.Println("Credentials file already exists, creation skipped") - } else { +// DistSelect choose the Dist and return sshUser and osLabel +func (aws *AWS) DistSelect() (string, string) { - //Read Configuration File - viper.SetConfigName("config") + awsAmiID, awsInstanceOS, sshUser := aws.getConfig() - viper.AddConfigPath(".") - viper.AddConfigPath("/tk8") - verr := viper.ReadInConfig() // Find and read the config file - if verr != nil { // Handle errors reading the config file - panic(fmt.Errorf("fatal error config file: %s", verr)) + if awsAmiID != "" && sshUser != "" { + awsInstanceOS = "custom" + aws.Dists[awsInstanceOS] = DistOS{ + User: sshUser, + AmiOwner: "", + OS: awsAmiID, } + } - awsAccessKeyID := viper.GetString("aws.aws_access_key_id") - - awsSecretKey := viper.GetString("aws.aws_secret_access_key") - - awsAccessSSHKey := viper.GetString("aws.aws_ssh_keypair") + // TODO: clean up debug + aws.OSHelper.Log(awsInstanceOS) - awsDefaultRegion := viper.GetString("aws.aws_default_region") + if awsInstanceOS == "" && awsAmiID == "" { + log.Fatal("Provide either of AMI ID or OS in the config file.") + return "", "" + } + if awsAmiID != "" && sshUser == "" { + log.Fatal("SSH Username is required when using custom AMI") + return "", "" + } + // prepare config + if !aws.createFileFromTemplate("/configs/templates/kubespray-aws-variables.tf", "./"+aws.Namespace+"/variables.tf", awsInstanceOS, nil) { + return "", "" + } + if !aws.createFileFromTemplate("/configs/templates/kubespray-aws-create-infra.tf", "./"+aws.Namespace+"/create-infrastructure.tf", awsInstanceOS, nil) { + return "", "" + } - file, err := os.Create("./kubespray/contrib/terraform/aws/credentials.tfvars") - if err != nil { - log.Fatal("Cannot create file", err) - } - defer file.Close() + return sshUser, awsInstanceOS +} - fmt.Fprintf(file, "AWS_ACCESS_KEY_ID = %s\n", strconv.Quote(awsAccessKeyID)) - fmt.Fprintf(file, "AWS_SECRET_ACCESS_KEY = %s\n", strconv.Quote(awsSecretKey)) - fmt.Fprintf(file, "AWS_SSH_KEY_NAME = %s\n", strconv.Quote(awsAccessSSHKey)) - fmt.Fprintf(file, "AWS_DEFAULT_REGION = %s\n", strconv.Quote(awsDefaultRegion)) +func (aws *AWS) GetCredentials() AwsCredentials { + //Read Configuration File + viper.SetConfigName("config") + viper.AddConfigPath(".") + viper.AddConfigPath("/tk8") + verr := viper.ReadInConfig() // Find and read the config file + if verr != nil { // Handle errors reading the config file + panic(fmt.Errorf("fatal error config file: %s", verr)) } - // Remove tftvars file - - err = os.Remove("./kubespray/contrib/terraform/aws/terraform.tfvars") - if err != nil { - fmt.Println(err) + return AwsCredentials{ + AwsAccessKeyID: viper.GetString("aws.aws_access_key_id"), + AwsSecretKey: viper.GetString("aws.aws_secret_access_key"), + AwsAccessSSHKey: viper.GetString("aws.aws_ssh_keypair"), + AwsDefaultRegion: viper.GetString("aws.aws_default_region"), } +} +func (aws *AWS) GetClusterConfig() ClusterConfig { //Read Configuration File viper.SetConfigName("config") @@ -157,76 +153,69 @@ func AWSCreate() { if verr != nil { // Handle errors reading the config file panic(fmt.Errorf("fatal error config file: %s", verr)) } - - awsClusterName := viper.GetString("aws.clustername") - awsVpcCidrBlock := viper.GetString("aws.aws_vpc_cidr_block") - awsCidrSubnetsPrivate := viper.GetString("aws.aws_cidr_subnets_private") - awsCidrSubnetsPublic := viper.GetString("aws.aws_cidr_subnets_public") - awsBastionSize := viper.GetString("aws.aws_bastion_size") - awsKubeMasterNum := viper.GetString("aws.aws_kube_master_num") - awsKubeMasterSize := viper.GetString("aws.aws_kube_master_size") - awsEtcdNum := viper.GetString("aws.aws_etcd_num") - awsEtcdSize := viper.GetString("aws.aws_etcd_size") - awsKubeWorkerNum := viper.GetString("aws.aws_kube_worker_num") - awsKubeWorkerSize := viper.GetString("aws.aws_kube_worker_size") - awsElbAPIPort := viper.GetString("aws.aws_elb_api_port") - k8sSecureAPIPort := viper.GetString("aws.k8s_secure_api_port") - kubeInsecureApiserverAddress := viper.GetString("aws.") - - tfile, err := os.Create("./kubespray/contrib/terraform/aws/terraform.tfvars") - if err != nil { - log.Fatal("Cannot create file", err) + return ClusterConfig{ + AwsClusterName: viper.GetString("aws.clustername"), + AwsVpcCidrBlock: viper.GetString("aws.aws_vpc_cidr_block"), + AwsCidrSubnetsPrivate: viper.GetString("aws.aws_cidr_subnets_private"), + AwsCidrSubnetsPublic: viper.GetString("aws.aws_cidr_subnets_public"), + AwsBastionSize: viper.GetString("aws.aws_bastion_size"), + AwsKubeMasterNum: viper.GetString("aws.aws_kube_master_num"), + AwsKubeMasterSize: viper.GetString("aws.aws_kube_master_size"), + AwsEtcdNum: viper.GetString("aws.aws_etcd_num"), + AwsEtcdSize: viper.GetString("aws.aws_etcd_size"), + AwsKubeWorkerNum: viper.GetString("aws.aws_kube_worker_num"), + AwsKubeWorkerSize: viper.GetString("aws.aws_kube_worker_size"), + AwsElbAPIPort: viper.GetString("aws.aws_elb_api_port"), + K8sSecureAPIPort: viper.GetString("aws.k8s_secure_api_port"), + KubeInsecureApiserverAddress: viper.GetString("aws."), } - defer tfile.Close() - - fmt.Fprintf(tfile, "aws_cluster_name = %s\n", strconv.Quote(awsClusterName)) - fmt.Fprintf(tfile, "aws_vpc_cidr_block = %s\n", strconv.Quote(awsVpcCidrBlock)) - fmt.Fprintf(tfile, "aws_cidr_subnets_private = %s\n", awsCidrSubnetsPrivate) - fmt.Fprintf(tfile, "aws_cidr_subnets_public = %s\n", awsCidrSubnetsPublic) - - fmt.Fprintf(tfile, "aws_bastion_size = %s\n", strconv.Quote(awsBastionSize)) - fmt.Fprintf(tfile, "aws_kube_master_num = %s\n", awsKubeMasterNum) - fmt.Fprintf(tfile, "aws_kube_master_size = %s\n", strconv.Quote(awsKubeMasterSize)) - fmt.Fprintf(tfile, "aws_etcd_num = %s\n", awsEtcdNum) - - fmt.Fprintf(tfile, "aws_etcd_size = %s\n", strconv.Quote(awsEtcdSize)) - fmt.Fprintf(tfile, "aws_kube_worker_num = %s\n", awsKubeWorkerNum) - fmt.Fprintf(tfile, "aws_kube_worker_size = %s\n", strconv.Quote(awsKubeWorkerSize)) - fmt.Fprintf(tfile, "aws_elb_api_port = %s\n", awsElbAPIPort) - fmt.Fprintf(tfile, "k8s_secure_api_port = %s\n", k8sSecureAPIPort) - fmt.Fprintf(tfile, "kube_insecure_apiserver_address = %s\n", strconv.Quote(kubeInsecureApiserverAddress)) +} - fmt.Fprintf(tfile, "default_tags = {\n") - fmt.Fprintf(tfile, "# Env = 'devtest'\n") - fmt.Fprintf(tfile, "# Product = 'kubernetes'\n") - fmt.Fprintf(tfile, "}") +func (aws *AWS) Create() { + if aws.OSHelper == nil { + aws.Init() + } + if !aws.OSHelper.CheckDependency("terraform") { + return + } - distSelect() + _, err := aws.OSHelper.Shell("terraform", "version") + if err != nil { + return // cancel process + } + if _, err := aws.OSHelper.FileInfo("/configs/templates/credentials.tfvars"); err != nil { + if !aws.createFileFromTemplate("/configs/templates/kubespray-aws-credentials.tfvars", "./"+aws.Namespace+"/credentials.tfvars", aws.Namespace, aws.GetCredentials()) { + return // cancel process + } + } + if !aws.createFileFromTemplate("/configs/templates/kubespray-aws-terraform.tfvars", "./"+aws.Namespace+"/terraform.tfvars", aws.Namespace, aws.GetClusterConfig()) { + return // cancel process + } - terrInit := exec.Command("terraform", "init") - terrInit.Dir = "./kubespray/contrib/terraform/aws/" + //TODO: extract to a builder same like oshelper + terrInit, _ := aws.OSHelper.Shell("terraform", "init") + terrInit.Dir = "./" + aws.Namespace + "/" out, _ := terrInit.StdoutPipe() terrInit.Start() scanInit := bufio.NewScanner(out) for scanInit.Scan() { m := scanInit.Text() - fmt.Println(m) - //log.Printf(m) + aws.OSHelper.Log(m) } terrInit.Wait() - terrSet := exec.Command("terraform", "apply", "-var-file=credentials.tfvars", "-auto-approve") - terrSet.Dir = "./kubespray/contrib/terraform/aws/" - stdout, err := terrSet.StdoutPipe() + terrSet, _ := aws.OSHelper.Shell("terraform", "apply", "-var-file=credentials.tfvars", "-auto-approve") + + terrSet.Dir = "./" + aws.Namespace + "/" + stdout, _ := terrSet.StdoutPipe() terrSet.Stderr = terrSet.Stdout terrSet.Start() scanner := bufio.NewScanner(stdout) for scanner.Scan() { m := scanner.Text() - fmt.Println(m) - //log.Printf(m) + aws.OSHelper.Log(m) } terrSet.Wait() @@ -234,6 +223,12 @@ func AWSCreate() { } +// NewAWS is the AWS Constructor +func NewAWS(namespace string) AWS { + + aws := AWS{Namespace: namespace} + return aws +} func AWSInstall() { // check if ansible is installed terr, err := exec.LookPath("ansible") @@ -413,3 +408,72 @@ func AWSDestroy() { os.Exit(0) } + +// depricated +var ec2IP string + +// depricated +func distSelect() (string, string) { + var sshUser, osLabel string + + centos := map[string]string{ + "user": "centos", + "ami_owner": "688023202711", + "os": "dcos-centos7", + } + + ubuntu := map[string]string{ + "user": "ubuntu", + "ami_owner": "099720109477", + "os": "ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64", + } + + //Read Configuration File + viper.SetConfigName("config") + + viper.AddConfigPath(".") + verr := viper.ReadInConfig() // Find and read the config file + if verr != nil { // Handle errors reading the config file + panic(fmt.Errorf("fatal error config file: %s", verr)) + } + + awsAmiID := viper.GetString("aws.ami_id") + awsInstanceOS := viper.GetString("aws.os") + sshUser = viper.GetString("aws.ssh_user") + + // Think of a better way to do this + if awsInstanceOS != "" { + fmt.Println(awsInstanceOS) + switch awsInstanceOS { + case "centos": + exec.Command("sh", "-c", "sed -i \"\" -e 's/dcos-centos7/"+centos["os"]+"/g' ./kubespray/contrib/terraform/aws/variables.tf").Run() + exec.Command("sh", "-c", "sed -i \"\" -e 's/688023202711/"+centos["ami_owner"]+"/g' ./kubespray/contrib/terraform/aws/variables.tf").Run() + sshUser = centos["user"] + osLabel = "centos" + case "ubuntu": + exec.Command("sh", "-c", "sed -i \"\" -e 's#dcos-centos7#"+ubuntu["os"]+"#g' ./kubespray/contrib/terraform/aws/variables.tf").Run() + exec.Command("sh", "-c", "sed -i \"\" -e 's/688023202711/"+ubuntu["ami_owner"]+"/g' ./kubespray/contrib/terraform/aws/variables.tf").Run() + sshUser = ubuntu["user"] + osLabel = "ubuntu" + // Will only work with 'https://github.com/kubernetes-incubator/kubespray' + default: + sshUser = "core" + osLabel = "coreos" + return sshUser, osLabel + } + } else if awsAmiID != "" && sshUser != "" { + err := exec.Command("sh", "-c", "sed -i \"\" -e 's/${data.aws_ami.distro.id}/"+awsAmiID+"/g' ./kubespray/contrib/terraform/aws/create-infrastructure.tf").Run() + if err != nil { + log.Fatal("Cannot replace AMI ID in Infrastructure template", err) + } + osLabel = "Custom-AMI" + } else if awsAmiID != "" && sshUser == "" { + log.Fatal("SSH Username is required when using custom AMI") + return "", "" + } else { + log.Fatal("Provide either of AMI ID or OS in the config file.") + return "", "" + } + + return sshUser, osLabel +} diff --git a/internal/cluster/cluster.go b/internal/cluster/cluster.go new file mode 100644 index 0000000..68dd34b --- /dev/null +++ b/internal/cluster/cluster.go @@ -0,0 +1,47 @@ +package cluster + +/* + DistOs struct holds the main dist OS information + It is possible easly extend the list of OS + Append new DistOS to cluster.DistOSMap and use the key(string) in the config +*/ +type DistOS struct { + User string + AmiOwner string + OS string +} + +var DistOSMap = map[string]DistOS{ + "centos": DistOS{ + User: "centos", + AmiOwner: "688023202711", + OS: "dcos-centos7-*", + }, + "ubuntu": DistOS{ + User: "ubuntu", + AmiOwner: "099720109477", + OS: "ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64-*", + }, + "coreos": DistOS{ + User: "core", + AmiOwner: "688023202711", + OS: "CoreOS-stable-*", + }, +} + +type ClusterConfig struct { + AwsClusterName string + AwsVpcCidrBlock string + AwsCidrSubnetsPrivate string + AwsCidrSubnetsPublic string + AwsBastionSize string + AwsKubeMasterNum string + AwsKubeMasterSize string + AwsEtcdNum string + AwsEtcdSize string + AwsKubeWorkerNum string + AwsKubeWorkerSize string + AwsElbAPIPort string + K8sSecureAPIPort string + KubeInsecureApiserverAddress string +} From c6889e1bc9109513ef1916c3e180f0cf5235dcf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20M=C3=BCller?= Date: Sat, 11 Aug 2018 00:46:41 +0200 Subject: [PATCH 4/9] changed aws create to new structure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Manuel Müller --- cmd/aws.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/aws.go b/cmd/aws.go index 1ad19a9..c351f22 100644 --- a/cmd/aws.go +++ b/cmd/aws.go @@ -32,13 +32,13 @@ Create, delete and show current status of the deployment that is running on AWS. Kindly ensure that terraform is installed also.`, Args: cobra.NoArgs, Run: func(cmd *cobra.Command, args []string) { - + aws := cluster.NewAWS("DefineWorkspace") if install { cluster.AWSInstall() } if create { - cluster.AWSCreate() + aws.Create() } if destroy { From 2c465a439f35085e8feaa6289a4c217be7e086e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20M=C3=BCller?= Date: Sat, 11 Aug 2018 10:45:34 +0200 Subject: [PATCH 5/9] remove init to get testable version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Manuel Müller --- cmd/aws.go | 6 +++++- internal/cluster/aws.go | 18 +++++------------- internal/cluster/oshelper/helper.go | 5 +++-- internal/cluster/oshelper/unixhelper.go | 18 +++++++++--------- 4 files changed, 22 insertions(+), 25 deletions(-) diff --git a/cmd/aws.go b/cmd/aws.go index c351f22..8b74465 100644 --- a/cmd/aws.go +++ b/cmd/aws.go @@ -17,6 +17,8 @@ package cmd import ( "os" + "github.com/kubernauts/tk8/internal/cluster/oshelper" + "github.com/kubernauts/tk8/internal/cluster" "github.com/spf13/cobra" ) @@ -32,7 +34,9 @@ Create, delete and show current status of the deployment that is running on AWS. Kindly ensure that terraform is installed also.`, Args: cobra.NoArgs, Run: func(cmd *cobra.Command, args []string) { - aws := cluster.NewAWS("DefineWorkspace") + + aws := cluster.NewAWS("DefineWorkspace", cluster.DistOSMap, oshelper.NewOSHelper()) + if install { cluster.AWSInstall() } diff --git a/internal/cluster/aws.go b/internal/cluster/aws.go index a1a003e..dcf3ef1 100644 --- a/internal/cluster/aws.go +++ b/internal/cluster/aws.go @@ -43,14 +43,9 @@ type AwsCredentials struct { AwsDefaultRegion string } -// Init prepare some configs for the aws deployment -func (aws *AWS) Init() { - aws.Dists = DistOSMap - aws.OSHelper = oshelper.NewOSHelper() -} - // create config files from templates func (aws *AWS) createFileFromTemplate(templateName string, targetFileName string, awsInstanceOS string, data interface{}) bool { + _ = os.Mkdir("./"+aws.Namespace+"/variables.tf", os.ModePerm) file, err := os.Create(targetFileName) if err != nil { aws.OSHelper.FatalLog("Cannot create file", err) @@ -74,7 +69,7 @@ func (aws *AWS) createFileFromTemplate(templateName string, targetFileName strin } // load configs from viper -func (aws *AWS) getConfig() (string, string, string) { +func (aws *AWS) GetConfig() (string, string, string) { //Read Configuration File viper.SetConfigName("config") @@ -93,7 +88,7 @@ func (aws *AWS) getConfig() (string, string, string) { // DistSelect choose the Dist and return sshUser and osLabel func (aws *AWS) DistSelect() (string, string) { - awsAmiID, awsInstanceOS, sshUser := aws.getConfig() + awsAmiID, awsInstanceOS, sshUser := aws.GetConfig() if awsAmiID != "" && sshUser != "" { awsInstanceOS = "custom" @@ -172,9 +167,6 @@ func (aws *AWS) GetClusterConfig() ClusterConfig { } func (aws *AWS) Create() { - if aws.OSHelper == nil { - aws.Init() - } if !aws.OSHelper.CheckDependency("terraform") { return } @@ -224,9 +216,9 @@ func (aws *AWS) Create() { } // NewAWS is the AWS Constructor -func NewAWS(namespace string) AWS { +func NewAWS(namespace string, distOS map[string]DistOS, oshelper oshelper.OSHelper) AWS { - aws := AWS{Namespace: namespace} + aws := AWS{Namespace: namespace, Dists: distOS, OSHelper: oshelper} return aws } func AWSInstall() { diff --git a/internal/cluster/oshelper/helper.go b/internal/cluster/oshelper/helper.go index 9c37ba4..d240d43 100644 --- a/internal/cluster/oshelper/helper.go +++ b/internal/cluster/oshelper/helper.go @@ -2,15 +2,16 @@ package oshelper import "os/exec" +// OSHelper to support differnet OS type OSHelper interface { - GetOs() string CheckDependency(dependecy string) bool FatalLog(...interface{}) Log(...interface{}) - Shell(...string) (*exec.Cmd, error) + Shell(cmd string, v ...string) (*exec.Cmd, error) FileInfo(file string) (string, error) } +// NewOSHelper is the Constructor for the OSHelper func NewOSHelper() OSHelper { // TODO check os and return the Helper return UnixHelper{} diff --git a/internal/cluster/oshelper/unixhelper.go b/internal/cluster/oshelper/unixhelper.go index fa77351..659eec6 100644 --- a/internal/cluster/oshelper/unixhelper.go +++ b/internal/cluster/oshelper/unixhelper.go @@ -5,29 +5,32 @@ import ( "log" "os" "os/exec" - "strings" ) // UnixHelper provied some methods for unix type UnixHelper struct { } +// FatalLog for logging Fatal errors func (h UnixHelper) FatalLog(v ...interface{}) { log.Fatal(v) } +// Log for logging output func (h UnixHelper) Log(v ...interface{}) { log.Print(v) } +// FileInfo to get information of a file func (h UnixHelper) FileInfo(file string) (string, error) { fileInfo, err := os.Stat(file) - fileInfoJson, _ := json.Marshal(fileInfo) - return string(fileInfoJson), err + fileInfoJSON, _ := json.Marshal(fileInfo) + return string(fileInfoJSON), err } -func (h UnixHelper) Shell(v ...string) (*exec.Cmd, error) { - rr := exec.Command(strings.Join(v, " ")) +// Shell to execute operstion on the os shell +func (h UnixHelper) Shell(cmd string, v ...string) (*exec.Cmd, error) { + rr := exec.Command(cmd, v...) logString, err := rr.Output() if err != nil { h.FatalLog(err) @@ -37,10 +40,7 @@ func (h UnixHelper) Shell(v ...string) (*exec.Cmd, error) { return rr, err } -func (h UnixHelper) GetOs() string { - return "unix" -} - +// CheckDependency checked if the dependency is installed func (h UnixHelper) CheckDependency(dependecy string) bool { _, err := exec.LookPath(dependecy) if err != nil { From 1141646dc2651df91cf274b96d3d1b1963828f6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20M=C3=BCller?= Date: Sat, 11 Aug 2018 12:34:57 +0200 Subject: [PATCH 6/9] add tests for CreateFileFromTemplate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Manuel Müller --- configs/templates/config.yaml | 23 +++ .../templates/kubespray-aws-create-infra.tf | 12 +- .../kubespray-aws-credentials.tfvars | 10 +- .../templates/kubespray-aws-terraform.tfvars | 36 ++-- configs/templates/kubespray-aws-variables.tf | 8 +- internal/cluster/aws.go | 45 +++-- internal/cluster/aws_test.go | 139 +++++++++++++ .../cluster/testcase/create-infrastructer.tf | 191 ++++++++++++++++++ internal/cluster/testcase/credentials.tfvars | 4 + internal/cluster/testcase/terraform.tfvars | 21 ++ internal/cluster/testcase/variables.tf | 105 ++++++++++ 11 files changed, 543 insertions(+), 51 deletions(-) create mode 100644 configs/templates/config.yaml create mode 100644 internal/cluster/aws_test.go create mode 100644 internal/cluster/testcase/create-infrastructer.tf create mode 100644 internal/cluster/testcase/credentials.tfvars create mode 100644 internal/cluster/testcase/terraform.tfvars create mode 100644 internal/cluster/testcase/variables.tf diff --git a/configs/templates/config.yaml b/configs/templates/config.yaml new file mode 100644 index 0000000..cf4a5eb --- /dev/null +++ b/configs/templates/config.yaml @@ -0,0 +1,23 @@ +aws: + clustername: kubernauts + os: coreos + master: 1 + worker: 1 + etcd: 1 + aws_access_key_id: + aws_secret_access_key: + aws_ssh_keypair: + aws_default_region: + aws_vpc_cidr_block : "10.250.192.0/18" + aws_cidr_subnets_private : '["10.250.192.0/20","10.250.208.0/20"]' + aws_cidr_subnets_public : '["10.250.224.0/20","10.250.240.0/20"]' + aws_bastion_size : "t2.medium" + aws_kube_master_num : 1 + aws_kube_master_size : "t2.medium" + aws_etcd_num : 1 + aws_etcd_size : "t2.medium" + aws_kube_worker_num : 2 + aws_kube_worker_size : "t2.medium" + aws_elb_api_port : 6443 + k8s_secure_api_port : 6443 + kube_insecure_apiserver_address : "0.0.0.0" diff --git a/configs/templates/kubespray-aws-create-infra.tf b/configs/templates/kubespray-aws-create-infra.tf index 50fe3a3..d0486ac 100644 --- a/configs/templates/kubespray-aws-create-infra.tf +++ b/configs/templates/kubespray-aws-create-infra.tf @@ -1,4 +1,3 @@ -{{define "DistOS"}} terraform { required_version = ">= 0.8.7" } @@ -54,7 +53,7 @@ module "aws-iam" { */ resource "aws_instance" "bastion-server" { - ami = {{.OS}} + ami = "{{.OS}}" instance_type = "${var.aws_bastion_size}" count = "${length(var.aws_cidr_subnets_public)}" associate_public_ip_address = true @@ -80,7 +79,7 @@ resource "aws_instance" "bastion-server" { */ resource "aws_instance" "k8s-master" { - ami = {{.OS}} + ami = "{{.OS}}" instance_type = "${var.aws_kube_master_size}" count = "${var.aws_kube_master_num}" @@ -112,7 +111,7 @@ resource "aws_elb_attachment" "attach_master_nodes" { resource "aws_instance" "k8s-etcd" { - ami = {{.OS}} + ami = "{{.OS}}" instance_type = "${var.aws_etcd_size}" count = "${var.aws_etcd_num}" @@ -136,7 +135,7 @@ resource "aws_instance" "k8s-etcd" { resource "aws_instance" "k8s-worker" { - ami = {{.OS}} + ami = "{{.OS}}" instance_type = "${var.aws_kube_worker_size}" count = "${var.aws_kube_worker_num}" @@ -189,5 +188,4 @@ resource "null_resource" "inventories" { template = "${data.template_file.inventory.rendered}" } -} -{{end}} \ No newline at end of file +} \ No newline at end of file diff --git a/configs/templates/kubespray-aws-credentials.tfvars b/configs/templates/kubespray-aws-credentials.tfvars index effd659..7ebce7a 100644 --- a/configs/templates/kubespray-aws-credentials.tfvars +++ b/configs/templates/kubespray-aws-credentials.tfvars @@ -1,6 +1,4 @@ -{{define "AwsCredentials"}} -AWS_ACCESS_KEY_ID = {{.AwsAccessKeyID}} -AWS_SECRET_ACCESS_KEY = {{.AwsSecretKey}} -AWS_SSH_KEY_NAME = {{.AwsAccessSSHKey}} -AWS_DEFAULT_REGION = {{.AwsDefaultRegion}} -{{end}} \ No newline at end of file +AWS_ACCESS_KEY_ID = "{{.AwsAccessKeyID}}" +AWS_SECRET_ACCESS_KEY = "{{.AwsSecretKey}}" +AWS_SSH_KEY_NAME = "{{.AwsAccessSSHKey}}" +AWS_DEFAULT_REGION = "{{.AwsDefaultRegion}}" \ No newline at end of file diff --git a/configs/templates/kubespray-aws-terraform.tfvars b/configs/templates/kubespray-aws-terraform.tfvars index 0c16376..2f51335 100644 --- a/configs/templates/kubespray-aws-terraform.tfvars +++ b/configs/templates/kubespray-aws-terraform.tfvars @@ -1,23 +1,21 @@ -{{define "ClusterConfig"}} -aws_cluster_name = {{.AwsClusterName}} -aws_vpc_cidr_block = {{.AwsVpcCidrBlock}} -aws_cidr_subnets_private = {{.AwsCidrSubnetsPrivat}} -aws_cidr_subnets_public = {{.AwsCidrSubnetsPubli}} +aws_cluster_name = "{{.AwsClusterName}}" +aws_vpc_cidr_block = "{{.AwsVpcCidrBlock}}" +aws_cidr_subnets_private = "{{.AwsCidrSubnetsPrivate}}" +aws_cidr_subnets_public = "{{.AwsCidrSubnetsPublic}}" -aws_bastion_size = {{.AwsBastionSize}} -aws_kube_master_num = {{.AwsKubeMasterNu}} -aws_kube_master_size = {{.AwsKubeMasterSize}} -aws_etcd_num = {{.AwsEtcdNu}} +aws_bastion_size = "{{.AwsBastionSize}}" +aws_kube_master_num = "{{.AwsKubeMasterNum}}" +aws_kube_master_size = "{{.AwsKubeMasterSize}}" +aws_etcd_num = "{{.AwsEtcdNum}}" -aws_etcd_size = {{.AwsEtcdSize}} -aws_kube_worker_num = {{.AwsKubeWorkerNu}} -aws_kube_worker_size = {{.AwsKubeWorkerSize}} -aws_elb_api_port = {{.AwsElbAPIPor}} -k8s_secure_api_port = {{.K8sSecureAPIPor}} -kube_insecure_apiserver_address = {{.KubeInsecureApiserverAddress}} +aws_etcd_size = "{{.AwsEtcdSize}}" +aws_kube_worker_num = "{{.AwsKubeWorkerNum}}" +aws_kube_worker_size = "{{.AwsKubeWorkerSize}}" +aws_elb_api_port = "{{.AwsElbAPIPort}}" +k8s_secure_api_port = "{{.K8sSecureAPIPort}}" +kube_insecure_apiserver_address = "{{.KubeInsecureApiserverAddress}}" default_tags = { - Env = 'devtest', - Product = 'kubernetes' -} -{{end}} \ No newline at end of file + Env = "devtest" + Product = "kubernetes" +} \ No newline at end of file diff --git a/configs/templates/kubespray-aws-variables.tf b/configs/templates/kubespray-aws-variables.tf index 567a3f2..c939200 100644 --- a/configs/templates/kubespray-aws-variables.tf +++ b/configs/templates/kubespray-aws-variables.tf @@ -19,13 +19,13 @@ variable "AWS_DEFAULT_REGION" { variable "aws_cluster_name" { description = "Name of AWS Cluster" } -{{define "DistOS"}} + data "aws_ami" "distro" { most_recent = true filter { name = "name" - values = [{{.OS}}] + values = ["{{.OS}}"] } filter { @@ -33,9 +33,9 @@ data "aws_ami" "distro" { values = ["hvm"] } - owners = [{{.AmiOwner}}] #CoreOS + owners = ["{{.AmiOwner}}"] #CoreOS } -{{end}} + //AWS VPC Variables variable "aws_vpc_cidr_block" { diff --git a/internal/cluster/aws.go b/internal/cluster/aws.go index dcf3ef1..14150d8 100644 --- a/internal/cluster/aws.go +++ b/internal/cluster/aws.go @@ -15,6 +15,7 @@ package cluster import ( + "C" "bufio" "fmt" "html/template" @@ -27,6 +28,10 @@ import ( "github.com/kubernauts/tk8/internal/cluster/oshelper" "github.com/spf13/viper" ) +import ( + "path" + "path/filepath" +) // AWS is the main structer of the platform controller type AWS struct { @@ -43,18 +48,27 @@ type AwsCredentials struct { AwsDefaultRegion string } -// create config files from templates -func (aws *AWS) createFileFromTemplate(templateName string, targetFileName string, awsInstanceOS string, data interface{}) bool { - _ = os.Mkdir("./"+aws.Namespace+"/variables.tf", os.ModePerm) +func GetRootPath() string { + e, err := os.Executable() + if err != nil { + panic(err) + } + path := path.Dir(e) + fmt.Println(path) + return path +} + +// CreateFileFromTemplate create config files from templates +func (aws *AWS) CreateFileFromTemplate(templateName string, targetFileName string, awsInstanceOS string, data interface{}) bool { + absPath, _ := filepath.Abs("../../" + templateName) + _ = os.Mkdir(aws.Namespace, os.ModePerm) file, err := os.Create(targetFileName) if err != nil { aws.OSHelper.FatalLog("Cannot create file", err) return false } defer file.Close() - - template := template.New(awsInstanceOS) - template, err = template.Parse(templateName) + template := template.Must(template.ParseFiles(absPath)) if err != nil { aws.OSHelper.FatalLog(templateName, "for", awsInstanceOS, "could not parsed") return false @@ -65,15 +79,15 @@ func (aws *AWS) createFileFromTemplate(templateName string, targetFileName strin } template.Execute(file, data) return true - //TODO save StdOut as targetFileName } -// load configs from viper +// GetConfig configs from viper func (aws *AWS) GetConfig() (string, string, string) { //Read Configuration File viper.SetConfigName("config") - viper.AddConfigPath(".") + viper.AddConfigPath("/tk8") + viper.AddConfigPath("./../..") verr := viper.ReadInConfig() // Find and read the config file if verr != nil { // Handle errors reading the config file log.Fatal("config could not readed") @@ -111,10 +125,10 @@ func (aws *AWS) DistSelect() (string, string) { return "", "" } // prepare config - if !aws.createFileFromTemplate("/configs/templates/kubespray-aws-variables.tf", "./"+aws.Namespace+"/variables.tf", awsInstanceOS, nil) { + if !aws.CreateFileFromTemplate("/configs/templates/kubespray-aws-variables.tf", "./"+aws.Namespace+"/variables.tf", awsInstanceOS, nil) { return "", "" } - if !aws.createFileFromTemplate("/configs/templates/kubespray-aws-create-infra.tf", "./"+aws.Namespace+"/create-infrastructure.tf", awsInstanceOS, nil) { + if !aws.CreateFileFromTemplate("/configs/templates/kubespray-aws-create-infra.tf", "./"+aws.Namespace+"/create-infrastructure.tf", awsInstanceOS, nil) { return "", "" } @@ -124,9 +138,9 @@ func (aws *AWS) DistSelect() (string, string) { func (aws *AWS) GetCredentials() AwsCredentials { //Read Configuration File viper.SetConfigName("config") - viper.AddConfigPath(".") viper.AddConfigPath("/tk8") + viper.AddConfigPath("./../..") verr := viper.ReadInConfig() // Find and read the config file if verr != nil { // Handle errors reading the config file panic(fmt.Errorf("fatal error config file: %s", verr)) @@ -142,8 +156,9 @@ func (aws *AWS) GetCredentials() AwsCredentials { func (aws *AWS) GetClusterConfig() ClusterConfig { //Read Configuration File viper.SetConfigName("config") - viper.AddConfigPath(".") + viper.AddConfigPath("/tk8") + viper.AddConfigPath("./../..") verr := viper.ReadInConfig() // Find and read the config file if verr != nil { // Handle errors reading the config file panic(fmt.Errorf("fatal error config file: %s", verr)) @@ -176,11 +191,11 @@ func (aws *AWS) Create() { return // cancel process } if _, err := aws.OSHelper.FileInfo("/configs/templates/credentials.tfvars"); err != nil { - if !aws.createFileFromTemplate("/configs/templates/kubespray-aws-credentials.tfvars", "./"+aws.Namespace+"/credentials.tfvars", aws.Namespace, aws.GetCredentials()) { + if !aws.CreateFileFromTemplate("/configs/templates/kubespray-aws-credentials.tfvars", "./"+aws.Namespace+"/credentials.tfvars", aws.Namespace, aws.GetCredentials()) { return // cancel process } } - if !aws.createFileFromTemplate("/configs/templates/kubespray-aws-terraform.tfvars", "./"+aws.Namespace+"/terraform.tfvars", aws.Namespace, aws.GetClusterConfig()) { + if !aws.CreateFileFromTemplate("/configs/templates/kubespray-aws-terraform.tfvars", "./"+aws.Namespace+"/terraform.tfvars", aws.Namespace, aws.GetClusterConfig()) { return // cancel process } diff --git a/internal/cluster/aws_test.go b/internal/cluster/aws_test.go new file mode 100644 index 0000000..8d9d5f7 --- /dev/null +++ b/internal/cluster/aws_test.go @@ -0,0 +1,139 @@ +// Copyright © 2018 NAME HERE +// +// 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 cluster + +import ( + "testing" + + "github.com/kubernauts/tk8/internal/cluster/oshelper" +) + +func TestAWS_CreateFileFromTemplate(t *testing.T) { + type fields struct { + Dists map[string]DistOS + Ec2IP string + Namespace string + OSHelper oshelper.OSHelper + } + type args struct { + templateName string + targetFileName string + awsInstanceOS string + data interface{} + } + tests := []struct { + name string + fields fields + args args + want bool + }{ + { + "test_variables", + fields{ + map[string]DistOS{ + "centos": DistOS{ + User: "centos", + AmiOwner: "688023202711", + OS: "dcos-centos7-*", + }, + }, + "", + "testcase", + oshelper.NewOSHelper(), + }, + args{ + "configs/templates/kubespray-aws-variables.tf", "testcase/variables.tf", "centos", nil, + }, + true, + }, + { + "test_infra", + fields{ + map[string]DistOS{ + "centos": DistOS{ + User: "centos", + AmiOwner: "688023202711", + OS: "dcos-centos7-*", + }, + }, + "", + "testcase", + oshelper.NewOSHelper(), + }, + args{ + "configs/templates/kubespray-aws-create-infra.tf", "testcase/create-infrastructer.tf", "centos", nil, + }, + true, + }, + { + "test_terraform", + fields{ + map[string]DistOS{ + "centos": DistOS{ + User: "centos", + AmiOwner: "688023202711", + OS: "dcos-centos7-*", + }, + }, + "", + "testcase", + oshelper.NewOSHelper(), + }, + args{ + "configs/templates/kubespray-aws-terraform.tfvars", "testcase/terraform.tfvars", "centos", nil, + }, + true, + }, + { + "test_credentials", + fields{ + map[string]DistOS{ + "centos": DistOS{ + User: "centos", + AmiOwner: "688023202711", + OS: "dcos-centos7-*", + }, + }, + "", + "testcase", + oshelper.NewOSHelper(), + }, + args{ + "configs/templates/kubespray-aws-credentials.tfvars", "testcase/credentials.tfvars", "centos", nil, + }, + true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + aws := &AWS{ + Dists: tt.fields.Dists, + Ec2IP: tt.fields.Ec2IP, + Namespace: tt.fields.Namespace, + OSHelper: tt.fields.OSHelper, + } + switch tt.name { + case "test_terraform": + tt.args.data = aws.GetClusterConfig() + case "test_credentials": + tt.args.data = aws.GetCredentials() + } + + if got := aws.CreateFileFromTemplate(tt.args.templateName, tt.args.targetFileName, tt.args.awsInstanceOS, tt.args.data); got != tt.want { + t.Errorf("AWS.CreateFileFromTemplate() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/internal/cluster/testcase/create-infrastructer.tf b/internal/cluster/testcase/create-infrastructer.tf new file mode 100644 index 0000000..3e638a9 --- /dev/null +++ b/internal/cluster/testcase/create-infrastructer.tf @@ -0,0 +1,191 @@ +terraform { + required_version = ">= 0.8.7" +} + +provider "aws" { + access_key = "${var.AWS_ACCESS_KEY_ID}" + secret_key = "${var.AWS_SECRET_ACCESS_KEY}" + region = "${var.AWS_DEFAULT_REGION}" +} + +data "aws_availability_zones" "available" {} + +/* +* Calling modules who create the initial AWS VPC / AWS ELB +* and AWS IAM Roles for Kubernetes Deployment +*/ + +module "aws-vpc" { + source = "modules/vpc" + + aws_cluster_name = "${var.aws_cluster_name}" + aws_vpc_cidr_block = "${var.aws_vpc_cidr_block}" + aws_avail_zones="${slice(data.aws_availability_zones.available.names,0,2)}" + aws_cidr_subnets_private="${var.aws_cidr_subnets_private}" + aws_cidr_subnets_public="${var.aws_cidr_subnets_public}" + default_tags="${var.default_tags}" + +} + + +module "aws-elb" { + source = "modules/elb" + + aws_cluster_name="${var.aws_cluster_name}" + aws_vpc_id="${module.aws-vpc.aws_vpc_id}" + aws_avail_zones="${slice(data.aws_availability_zones.available.names,0,2)}" + aws_subnet_ids_public="${module.aws-vpc.aws_subnet_ids_public}" + aws_elb_api_port = "${var.aws_elb_api_port}" + k8s_secure_api_port = "${var.k8s_secure_api_port}" + default_tags="${var.default_tags}" + +} + +module "aws-iam" { + source = "modules/iam" + + aws_cluster_name="${var.aws_cluster_name}" +} + +/* +* Create Bastion Instances in AWS +* +*/ + +resource "aws_instance" "bastion-server" { + ami = "dcos-centos7-*" + instance_type = "${var.aws_bastion_size}" + count = "${length(var.aws_cidr_subnets_public)}" + associate_public_ip_address = true + availability_zone = "${element(slice(data.aws_availability_zones.available.names,0,2),count.index)}" + subnet_id = "${element(module.aws-vpc.aws_subnet_ids_public,count.index)}" + + + vpc_security_group_ids = [ "${module.aws-vpc.aws_security_group}" ] + + key_name = "${var.AWS_SSH_KEY_NAME}" + + tags = "${merge(var.default_tags, map( + "Name", "kubernetes-${var.aws_cluster_name}-bastion-${count.index}", + "Cluster", "${var.aws_cluster_name}", + "Role", "bastion-${var.aws_cluster_name}-${count.index}" + ))}" +} + + +/* +* Create K8s Master and worker nodes and etcd instances +* +*/ + +resource "aws_instance" "k8s-master" { + ami = "dcos-centos7-*" + instance_type = "${var.aws_kube_master_size}" + + count = "${var.aws_kube_master_num}" + + + availability_zone = "${element(slice(data.aws_availability_zones.available.names,0,2),count.index)}" + subnet_id = "${element(module.aws-vpc.aws_subnet_ids_private,count.index)}" + + + vpc_security_group_ids = [ "${module.aws-vpc.aws_security_group}" ] + + + iam_instance_profile = "${module.aws-iam.kube-master-profile}" + key_name = "${var.AWS_SSH_KEY_NAME}" + + + tags = "${merge(var.default_tags, map( + "Name", "kubernetes-${var.aws_cluster_name}-master${count.index}", + "kubernetes.io/cluster/${var.aws_cluster_name}", "member", + "Role", "master" + ))}" +} + +resource "aws_elb_attachment" "attach_master_nodes" { + count = "${var.aws_kube_master_num}" + elb = "${module.aws-elb.aws_elb_api_id}" + instance = "${element(aws_instance.k8s-master.*.id,count.index)}" +} + + +resource "aws_instance" "k8s-etcd" { + ami = "dcos-centos7-*" + instance_type = "${var.aws_etcd_size}" + + count = "${var.aws_etcd_num}" + + + availability_zone = "${element(slice(data.aws_availability_zones.available.names,0,2),count.index)}" + subnet_id = "${element(module.aws-vpc.aws_subnet_ids_private,count.index)}" + + + vpc_security_group_ids = [ "${module.aws-vpc.aws_security_group}" ] + + key_name = "${var.AWS_SSH_KEY_NAME}" + + tags = "${merge(var.default_tags, map( + "Name", "kubernetes-${var.aws_cluster_name}-etcd${count.index}", + "kubernetes.io/cluster/${var.aws_cluster_name}", "member", + "Role", "etcd" + ))}" + +} + + +resource "aws_instance" "k8s-worker" { + ami = "dcos-centos7-*" + instance_type = "${var.aws_kube_worker_size}" + + count = "${var.aws_kube_worker_num}" + + availability_zone = "${element(slice(data.aws_availability_zones.available.names,0,2),count.index)}" + subnet_id = "${element(module.aws-vpc.aws_subnet_ids_private,count.index)}" + + vpc_security_group_ids = [ "${module.aws-vpc.aws_security_group}" ] + + iam_instance_profile = "${module.aws-iam.kube-worker-profile}" + key_name = "${var.AWS_SSH_KEY_NAME}" + + + tags = "${merge(var.default_tags, map( + "Name", "kubernetes-${var.aws_cluster_name}-worker${count.index}", + "kubernetes.io/cluster/${var.aws_cluster_name}", "member", + "Role", "worker" + ))}" + +} + + + +/* +* Create Kubespray Inventory File +* +*/ +data "template_file" "inventory" { + template = "${file("${path.module}/templates/inventory.tpl")}" + + vars { + public_ip_address_bastion = "${join("\n",formatlist("bastion ansible_host=%s" , aws_instance.bastion-server.*.public_ip))}" + connection_strings_master = "${join("\n",formatlist("%s ansible_host=%s",aws_instance.k8s-master.*.tags.Name, aws_instance.k8s-master.*.private_ip))}" + connection_strings_node = "${join("\n", formatlist("%s ansible_host=%s", aws_instance.k8s-worker.*.tags.Name, aws_instance.k8s-worker.*.private_ip))}" + connection_strings_etcd = "${join("\n",formatlist("%s ansible_host=%s", aws_instance.k8s-etcd.*.tags.Name, aws_instance.k8s-etcd.*.private_ip))}" + list_master = "${join("\n",aws_instance.k8s-master.*.tags.Name)}" + list_node = "${join("\n",aws_instance.k8s-worker.*.tags.Name)}" + list_etcd = "${join("\n",aws_instance.k8s-etcd.*.tags.Name)}" + elb_api_fqdn = "apiserver_loadbalancer_domain_name=\"${module.aws-elb.aws_elb_api_fqdn}\"" + } + +} + +resource "null_resource" "inventories" { + provisioner "local-exec" { + command = "echo '${data.template_file.inventory.rendered}' > ../../../inventory/hosts" + } + + triggers { + template = "${data.template_file.inventory.rendered}" + } + +} \ No newline at end of file diff --git a/internal/cluster/testcase/credentials.tfvars b/internal/cluster/testcase/credentials.tfvars new file mode 100644 index 0000000..89e1e29 --- /dev/null +++ b/internal/cluster/testcase/credentials.tfvars @@ -0,0 +1,4 @@ +AWS_ACCESS_KEY_ID = "" +AWS_SECRET_ACCESS_KEY = "" +AWS_SSH_KEY_NAME = "" +AWS_DEFAULT_REGION = "" \ No newline at end of file diff --git a/internal/cluster/testcase/terraform.tfvars b/internal/cluster/testcase/terraform.tfvars new file mode 100644 index 0000000..a135c86 --- /dev/null +++ b/internal/cluster/testcase/terraform.tfvars @@ -0,0 +1,21 @@ +aws_cluster_name = "kubernauts" +aws_vpc_cidr_block = "10.250.192.0/18" +aws_cidr_subnets_private = "["10.250.192.0/20","10.250.208.0/20"]" +aws_cidr_subnets_public = "["10.250.224.0/20","10.250.240.0/20"]" + +aws_bastion_size = "t2.medium" +aws_kube_master_num = "1" +aws_kube_master_size = "t2.medium" +aws_etcd_num = "1" + +aws_etcd_size = "t2.medium" +aws_kube_worker_num = "2" +aws_kube_worker_size = "t2.medium" +aws_elb_api_port = "6443" +k8s_secure_api_port = "6443" +kube_insecure_apiserver_address = "" + +default_tags = { + Env = "devtest" + Product = "kubernetes" +} \ No newline at end of file diff --git a/internal/cluster/testcase/variables.tf b/internal/cluster/testcase/variables.tf new file mode 100644 index 0000000..90570f0 --- /dev/null +++ b/internal/cluster/testcase/variables.tf @@ -0,0 +1,105 @@ +variable "AWS_ACCESS_KEY_ID" { + description = "AWS Access Key" +} + +variable "AWS_SECRET_ACCESS_KEY" { + description = "AWS Secret Key" +} + +variable "AWS_SSH_KEY_NAME" { + description = "Name of the SSH keypair to use in AWS." +} + +variable "AWS_DEFAULT_REGION" { + description = "AWS Region" +} + +//General Cluster Settings + +variable "aws_cluster_name" { + description = "Name of AWS Cluster" +} + +data "aws_ami" "distro" { + most_recent = true + + filter { + name = "name" + values = ["dcos-centos7-*"] + } + + filter { + name = "virtualization-type" + values = ["hvm"] + } + + owners = ["688023202711"] #CoreOS +} + +//AWS VPC Variables + +variable "aws_vpc_cidr_block" { + description = "CIDR Block for VPC" +} + +variable "aws_cidr_subnets_private" { + description = "CIDR Blocks for private subnets in Availability Zones" + type = "list" +} + +variable "aws_cidr_subnets_public" { + description = "CIDR Blocks for public subnets in Availability Zones" + type = "list" +} + +//AWS EC2 Settings + +variable "aws_bastion_size" { + description = "EC2 Instance Size of Bastion Host" +} + +/* +* AWS EC2 Settings +* The number should be divisable by the number of used +* AWS Availability Zones without an remainder. +*/ +variable "aws_kube_master_num" { + description = "Number of Kubernetes Master Nodes" +} + +variable "aws_kube_master_size" { + description = "Instance size of Kube Master Nodes" +} + +variable "aws_etcd_num" { + description = "Number of etcd Nodes" +} + +variable "aws_etcd_size" { + description = "Instance size of etcd Nodes" +} + +variable "aws_kube_worker_num" { + description = "Number of Kubernetes Worker Nodes" +} + +variable "aws_kube_worker_size" { + description = "Instance size of Kubernetes Worker Nodes" +} + +/* +* AWS ELB Settings +* +*/ +variable "aws_elb_api_port" { + description = "Port for AWS ELB" +} + +variable "k8s_secure_api_port" { + description = "Secure Port of K8S API Server" +} + +variable "default_tags" { + description = "Default tags for all resources" + type = "map" +} From bc055fe5ab79e0d37e6ab384b893c8fad83f5d7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20M=C3=BCller?= Date: Sat, 11 Aug 2018 13:25:39 +0200 Subject: [PATCH 7/9] prepare test for the other functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Manuel Müller --- internal/cluster/aws.go | 74 ++++-------- internal/cluster/aws_test.go | 225 ++++++++++++++++++++++++++++++++--- 2 files changed, 234 insertions(+), 65 deletions(-) diff --git a/internal/cluster/aws.go b/internal/cluster/aws.go index 14150d8..dd6e852 100644 --- a/internal/cluster/aws.go +++ b/internal/cluster/aws.go @@ -1,21 +1,6 @@ -// Copyright © 2018 NAME HERE -// -// 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 cluster import ( - "C" "bufio" "fmt" "html/template" @@ -25,13 +10,11 @@ import ( "os/exec" "strings" + "path/filepath" + "github.com/kubernauts/tk8/internal/cluster/oshelper" "github.com/spf13/viper" ) -import ( - "path" - "path/filepath" -) // AWS is the main structer of the platform controller type AWS struct { @@ -48,19 +31,15 @@ type AwsCredentials struct { AwsDefaultRegion string } -func GetRootPath() string { - e, err := os.Executable() - if err != nil { - panic(err) - } - path := path.Dir(e) - fmt.Println(path) - return path +// GetAbsPath return the absoltue path of a file somewhere in the folder structure +func (aws *AWS) GetAbsPath(filePath string) string { + absPath, _ := filepath.Abs("../../" + filePath) + return absPath } // CreateFileFromTemplate create config files from templates func (aws *AWS) CreateFileFromTemplate(templateName string, targetFileName string, awsInstanceOS string, data interface{}) bool { - absPath, _ := filepath.Abs("../../" + templateName) + _ = os.Mkdir(aws.Namespace, os.ModePerm) file, err := os.Create(targetFileName) if err != nil { @@ -68,7 +47,7 @@ func (aws *AWS) CreateFileFromTemplate(templateName string, targetFileName strin return false } defer file.Close() - template := template.Must(template.ParseFiles(absPath)) + template := template.Must(template.ParseFiles(aws.GetAbsPath(templateName))) if err != nil { aws.OSHelper.FatalLog(templateName, "for", awsInstanceOS, "could not parsed") return false @@ -83,16 +62,7 @@ func (aws *AWS) CreateFileFromTemplate(templateName string, targetFileName strin // GetConfig configs from viper func (aws *AWS) GetConfig() (string, string, string) { - //Read Configuration File - viper.SetConfigName("config") - viper.AddConfigPath(".") - viper.AddConfigPath("/tk8") - viper.AddConfigPath("./../..") - verr := viper.ReadInConfig() // Find and read the config file - if verr != nil { // Handle errors reading the config file - log.Fatal("config could not readed") - return "", "", "" - } + aws.readViperConfigFile("config") awsAmiID := viper.GetString("aws.ami_id") awsInstanceOS := viper.GetString("aws.os") sshUser := viper.GetString("aws.ssh_user") @@ -124,6 +94,8 @@ func (aws *AWS) DistSelect() (string, string) { log.Fatal("SSH Username is required when using custom AMI") return "", "" } + + // TODO change to parallel creation // prepare config if !aws.CreateFileFromTemplate("/configs/templates/kubespray-aws-variables.tf", "./"+aws.Namespace+"/variables.tf", awsInstanceOS, nil) { return "", "" @@ -134,10 +106,9 @@ func (aws *AWS) DistSelect() (string, string) { return sshUser, awsInstanceOS } - -func (aws *AWS) GetCredentials() AwsCredentials { +func (aws *AWS) readViperConfigFile(configName string) { //Read Configuration File - viper.SetConfigName("config") + viper.SetConfigName(configName) viper.AddConfigPath(".") viper.AddConfigPath("/tk8") viper.AddConfigPath("./../..") @@ -145,6 +116,11 @@ func (aws *AWS) GetCredentials() AwsCredentials { if verr != nil { // Handle errors reading the config file panic(fmt.Errorf("fatal error config file: %s", verr)) } +} + +// GetCredentials get the aws credentials from config file +func (aws *AWS) GetCredentials() AwsCredentials { + aws.readViperConfigFile("config") return AwsCredentials{ AwsAccessKeyID: viper.GetString("aws.aws_access_key_id"), AwsSecretKey: viper.GetString("aws.aws_secret_access_key"), @@ -153,16 +129,9 @@ func (aws *AWS) GetCredentials() AwsCredentials { } } +// GetClusterConfig get the configuration from config file func (aws *AWS) GetClusterConfig() ClusterConfig { - //Read Configuration File - viper.SetConfigName("config") - viper.AddConfigPath(".") - viper.AddConfigPath("/tk8") - viper.AddConfigPath("./../..") - verr := viper.ReadInConfig() // Find and read the config file - if verr != nil { // Handle errors reading the config file - panic(fmt.Errorf("fatal error config file: %s", verr)) - } + aws.readViperConfigFile("config") return ClusterConfig{ AwsClusterName: viper.GetString("aws.clustername"), AwsVpcCidrBlock: viper.GetString("aws.aws_vpc_cidr_block"), @@ -181,6 +150,7 @@ func (aws *AWS) GetClusterConfig() ClusterConfig { } } +// Create a aws kubernetes cluster with terraform func (aws *AWS) Create() { if !aws.OSHelper.CheckDependency("terraform") { return @@ -264,6 +234,8 @@ func AWSInstall() { fmt.Println("Configuration folder already exists") } else { //os.MkdirAll("./kubespray/inventory/awscluster/group_vars", 0755) + + //TODO: os.Rename to move files exec.Command("cp", "-rfp", "./kubespray/inventory/sample/", "./kubespray/inventory/awscluster/").Run() exec.Command("cp", "./kubespray/inventory/hosts", "./kubespray/inventory/awscluster/hosts").Run() diff --git a/internal/cluster/aws_test.go b/internal/cluster/aws_test.go index 8d9d5f7..f574f29 100644 --- a/internal/cluster/aws_test.go +++ b/internal/cluster/aws_test.go @@ -1,20 +1,7 @@ -// Copyright © 2018 NAME HERE -// -// 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 cluster import ( + "reflect" "testing" "github.com/kubernauts/tk8/internal/cluster/oshelper" @@ -137,3 +124,213 @@ func TestAWS_CreateFileFromTemplate(t *testing.T) { }) } } + +func TestAWS_GetAbsPath(t *testing.T) { + type fields struct { + Dists map[string]DistOS + Ec2IP string + Namespace string + OSHelper oshelper.OSHelper + } + type args struct { + filePath string + } + tests := []struct { + name string + fields fields + args args + want string + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + aws := &AWS{ + Dists: tt.fields.Dists, + Ec2IP: tt.fields.Ec2IP, + Namespace: tt.fields.Namespace, + OSHelper: tt.fields.OSHelper, + } + if got := aws.GetAbsPath(tt.args.filePath); got != tt.want { + t.Errorf("AWS.GetAbsPath() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestAWS_GetConfig(t *testing.T) { + type fields struct { + Dists map[string]DistOS + Ec2IP string + Namespace string + OSHelper oshelper.OSHelper + } + tests := []struct { + name string + fields fields + want string + want1 string + want2 string + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + aws := &AWS{ + Dists: tt.fields.Dists, + Ec2IP: tt.fields.Ec2IP, + Namespace: tt.fields.Namespace, + OSHelper: tt.fields.OSHelper, + } + got, got1, got2 := aws.GetConfig() + if got != tt.want { + t.Errorf("AWS.GetConfig() got = %v, want %v", got, tt.want) + } + if got1 != tt.want1 { + t.Errorf("AWS.GetConfig() got1 = %v, want %v", got1, tt.want1) + } + if got2 != tt.want2 { + t.Errorf("AWS.GetConfig() got2 = %v, want %v", got2, tt.want2) + } + }) + } +} + +func TestAWS_DistSelect(t *testing.T) { + type fields struct { + Dists map[string]DistOS + Ec2IP string + Namespace string + OSHelper oshelper.OSHelper + } + tests := []struct { + name string + fields fields + want string + want1 string + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + aws := &AWS{ + Dists: tt.fields.Dists, + Ec2IP: tt.fields.Ec2IP, + Namespace: tt.fields.Namespace, + OSHelper: tt.fields.OSHelper, + } + got, got1 := aws.DistSelect() + if got != tt.want { + t.Errorf("AWS.DistSelect() got = %v, want %v", got, tt.want) + } + if got1 != tt.want1 { + t.Errorf("AWS.DistSelect() got1 = %v, want %v", got1, tt.want1) + } + }) + } +} + +func Test_distSelect(t *testing.T) { + tests := []struct { + name string + want string + want1 string + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, got1 := distSelect() + if got != tt.want { + t.Errorf("distSelect() got = %v, want %v", got, tt.want) + } + if got1 != tt.want1 { + t.Errorf("distSelect() got1 = %v, want %v", got1, tt.want1) + } + }) + } +} + +func TestAWS_GetCredentials(t *testing.T) { + type fields struct { + Dists map[string]DistOS + Ec2IP string + Namespace string + OSHelper oshelper.OSHelper + } + tests := []struct { + name string + fields fields + want AwsCredentials + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + aws := &AWS{ + Dists: tt.fields.Dists, + Ec2IP: tt.fields.Ec2IP, + Namespace: tt.fields.Namespace, + OSHelper: tt.fields.OSHelper, + } + if got := aws.GetCredentials(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("AWS.GetCredentials() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestAWS_GetClusterConfig(t *testing.T) { + type fields struct { + Dists map[string]DistOS + Ec2IP string + Namespace string + OSHelper oshelper.OSHelper + } + tests := []struct { + name string + fields fields + want ClusterConfig + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + aws := &AWS{ + Dists: tt.fields.Dists, + Ec2IP: tt.fields.Ec2IP, + Namespace: tt.fields.Namespace, + OSHelper: tt.fields.OSHelper, + } + if got := aws.GetClusterConfig(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("AWS.GetClusterConfig() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestAWS_Create(t *testing.T) { + type fields struct { + Dists map[string]DistOS + Ec2IP string + Namespace string + OSHelper oshelper.OSHelper + } + tests := []struct { + name string + fields fields + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + aws := &AWS{ + Dists: tt.fields.Dists, + Ec2IP: tt.fields.Ec2IP, + Namespace: tt.fields.Namespace, + OSHelper: tt.fields.OSHelper, + } + aws.Create() + }) + } +} From 03b17904a38454e550329ffba94d806ef677a950 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20M=C3=BCller?= Date: Sat, 11 Aug 2018 13:34:13 +0200 Subject: [PATCH 8/9] remove testcase folder from internal and add to gitignore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Manuel Müller --- .gitignore | 3 + internal/cluster/aws.go | 5 +- internal/cluster/aws_test.go | 8 +- .../cluster/testcase/create-infrastructer.tf | 191 ------------------ internal/cluster/testcase/credentials.tfvars | 4 - internal/cluster/testcase/terraform.tfvars | 21 -- internal/cluster/testcase/variables.tf | 105 ---------- 7 files changed, 10 insertions(+), 327 deletions(-) delete mode 100644 internal/cluster/testcase/create-infrastructer.tf delete mode 100644 internal/cluster/testcase/credentials.tfvars delete mode 100644 internal/cluster/testcase/terraform.tfvars delete mode 100644 internal/cluster/testcase/variables.tf diff --git a/.gitignore b/.gitignore index 84749f1..6a411c9 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,6 @@ _book tk8 dist bin + +kubespray +testcase \ No newline at end of file diff --git a/internal/cluster/aws.go b/internal/cluster/aws.go index dd6e852..69ebdc1 100644 --- a/internal/cluster/aws.go +++ b/internal/cluster/aws.go @@ -40,8 +40,8 @@ func (aws *AWS) GetAbsPath(filePath string) string { // CreateFileFromTemplate create config files from templates func (aws *AWS) CreateFileFromTemplate(templateName string, targetFileName string, awsInstanceOS string, data interface{}) bool { - _ = os.Mkdir(aws.Namespace, os.ModePerm) - file, err := os.Create(targetFileName) + _ = os.Mkdir(aws.GetAbsPath(".")+"/"+aws.Namespace, os.ModePerm) + file, err := os.Create(aws.GetAbsPath(".") + "/" + aws.Namespace + "/" + targetFileName) if err != nil { aws.OSHelper.FatalLog("Cannot create file", err) return false @@ -206,6 +206,7 @@ func NewAWS(namespace string, distOS map[string]DistOS, oshelper oshelper.OSHelp aws := AWS{Namespace: namespace, Dists: distOS, OSHelper: oshelper} return aws } + func AWSInstall() { // check if ansible is installed terr, err := exec.LookPath("ansible") diff --git a/internal/cluster/aws_test.go b/internal/cluster/aws_test.go index f574f29..edf0199 100644 --- a/internal/cluster/aws_test.go +++ b/internal/cluster/aws_test.go @@ -41,7 +41,7 @@ func TestAWS_CreateFileFromTemplate(t *testing.T) { oshelper.NewOSHelper(), }, args{ - "configs/templates/kubespray-aws-variables.tf", "testcase/variables.tf", "centos", nil, + "configs/templates/kubespray-aws-variables.tf", "variables.tf", "centos", nil, }, true, }, @@ -60,7 +60,7 @@ func TestAWS_CreateFileFromTemplate(t *testing.T) { oshelper.NewOSHelper(), }, args{ - "configs/templates/kubespray-aws-create-infra.tf", "testcase/create-infrastructer.tf", "centos", nil, + "configs/templates/kubespray-aws-create-infra.tf", "create-infrastructer.tf", "centos", nil, }, true, }, @@ -79,7 +79,7 @@ func TestAWS_CreateFileFromTemplate(t *testing.T) { oshelper.NewOSHelper(), }, args{ - "configs/templates/kubespray-aws-terraform.tfvars", "testcase/terraform.tfvars", "centos", nil, + "configs/templates/kubespray-aws-terraform.tfvars", "terraform.tfvars", "centos", nil, }, true, }, @@ -98,7 +98,7 @@ func TestAWS_CreateFileFromTemplate(t *testing.T) { oshelper.NewOSHelper(), }, args{ - "configs/templates/kubespray-aws-credentials.tfvars", "testcase/credentials.tfvars", "centos", nil, + "configs/templates/kubespray-aws-credentials.tfvars", "credentials.tfvars", "centos", nil, }, true, }, diff --git a/internal/cluster/testcase/create-infrastructer.tf b/internal/cluster/testcase/create-infrastructer.tf deleted file mode 100644 index 3e638a9..0000000 --- a/internal/cluster/testcase/create-infrastructer.tf +++ /dev/null @@ -1,191 +0,0 @@ -terraform { - required_version = ">= 0.8.7" -} - -provider "aws" { - access_key = "${var.AWS_ACCESS_KEY_ID}" - secret_key = "${var.AWS_SECRET_ACCESS_KEY}" - region = "${var.AWS_DEFAULT_REGION}" -} - -data "aws_availability_zones" "available" {} - -/* -* Calling modules who create the initial AWS VPC / AWS ELB -* and AWS IAM Roles for Kubernetes Deployment -*/ - -module "aws-vpc" { - source = "modules/vpc" - - aws_cluster_name = "${var.aws_cluster_name}" - aws_vpc_cidr_block = "${var.aws_vpc_cidr_block}" - aws_avail_zones="${slice(data.aws_availability_zones.available.names,0,2)}" - aws_cidr_subnets_private="${var.aws_cidr_subnets_private}" - aws_cidr_subnets_public="${var.aws_cidr_subnets_public}" - default_tags="${var.default_tags}" - -} - - -module "aws-elb" { - source = "modules/elb" - - aws_cluster_name="${var.aws_cluster_name}" - aws_vpc_id="${module.aws-vpc.aws_vpc_id}" - aws_avail_zones="${slice(data.aws_availability_zones.available.names,0,2)}" - aws_subnet_ids_public="${module.aws-vpc.aws_subnet_ids_public}" - aws_elb_api_port = "${var.aws_elb_api_port}" - k8s_secure_api_port = "${var.k8s_secure_api_port}" - default_tags="${var.default_tags}" - -} - -module "aws-iam" { - source = "modules/iam" - - aws_cluster_name="${var.aws_cluster_name}" -} - -/* -* Create Bastion Instances in AWS -* -*/ - -resource "aws_instance" "bastion-server" { - ami = "dcos-centos7-*" - instance_type = "${var.aws_bastion_size}" - count = "${length(var.aws_cidr_subnets_public)}" - associate_public_ip_address = true - availability_zone = "${element(slice(data.aws_availability_zones.available.names,0,2),count.index)}" - subnet_id = "${element(module.aws-vpc.aws_subnet_ids_public,count.index)}" - - - vpc_security_group_ids = [ "${module.aws-vpc.aws_security_group}" ] - - key_name = "${var.AWS_SSH_KEY_NAME}" - - tags = "${merge(var.default_tags, map( - "Name", "kubernetes-${var.aws_cluster_name}-bastion-${count.index}", - "Cluster", "${var.aws_cluster_name}", - "Role", "bastion-${var.aws_cluster_name}-${count.index}" - ))}" -} - - -/* -* Create K8s Master and worker nodes and etcd instances -* -*/ - -resource "aws_instance" "k8s-master" { - ami = "dcos-centos7-*" - instance_type = "${var.aws_kube_master_size}" - - count = "${var.aws_kube_master_num}" - - - availability_zone = "${element(slice(data.aws_availability_zones.available.names,0,2),count.index)}" - subnet_id = "${element(module.aws-vpc.aws_subnet_ids_private,count.index)}" - - - vpc_security_group_ids = [ "${module.aws-vpc.aws_security_group}" ] - - - iam_instance_profile = "${module.aws-iam.kube-master-profile}" - key_name = "${var.AWS_SSH_KEY_NAME}" - - - tags = "${merge(var.default_tags, map( - "Name", "kubernetes-${var.aws_cluster_name}-master${count.index}", - "kubernetes.io/cluster/${var.aws_cluster_name}", "member", - "Role", "master" - ))}" -} - -resource "aws_elb_attachment" "attach_master_nodes" { - count = "${var.aws_kube_master_num}" - elb = "${module.aws-elb.aws_elb_api_id}" - instance = "${element(aws_instance.k8s-master.*.id,count.index)}" -} - - -resource "aws_instance" "k8s-etcd" { - ami = "dcos-centos7-*" - instance_type = "${var.aws_etcd_size}" - - count = "${var.aws_etcd_num}" - - - availability_zone = "${element(slice(data.aws_availability_zones.available.names,0,2),count.index)}" - subnet_id = "${element(module.aws-vpc.aws_subnet_ids_private,count.index)}" - - - vpc_security_group_ids = [ "${module.aws-vpc.aws_security_group}" ] - - key_name = "${var.AWS_SSH_KEY_NAME}" - - tags = "${merge(var.default_tags, map( - "Name", "kubernetes-${var.aws_cluster_name}-etcd${count.index}", - "kubernetes.io/cluster/${var.aws_cluster_name}", "member", - "Role", "etcd" - ))}" - -} - - -resource "aws_instance" "k8s-worker" { - ami = "dcos-centos7-*" - instance_type = "${var.aws_kube_worker_size}" - - count = "${var.aws_kube_worker_num}" - - availability_zone = "${element(slice(data.aws_availability_zones.available.names,0,2),count.index)}" - subnet_id = "${element(module.aws-vpc.aws_subnet_ids_private,count.index)}" - - vpc_security_group_ids = [ "${module.aws-vpc.aws_security_group}" ] - - iam_instance_profile = "${module.aws-iam.kube-worker-profile}" - key_name = "${var.AWS_SSH_KEY_NAME}" - - - tags = "${merge(var.default_tags, map( - "Name", "kubernetes-${var.aws_cluster_name}-worker${count.index}", - "kubernetes.io/cluster/${var.aws_cluster_name}", "member", - "Role", "worker" - ))}" - -} - - - -/* -* Create Kubespray Inventory File -* -*/ -data "template_file" "inventory" { - template = "${file("${path.module}/templates/inventory.tpl")}" - - vars { - public_ip_address_bastion = "${join("\n",formatlist("bastion ansible_host=%s" , aws_instance.bastion-server.*.public_ip))}" - connection_strings_master = "${join("\n",formatlist("%s ansible_host=%s",aws_instance.k8s-master.*.tags.Name, aws_instance.k8s-master.*.private_ip))}" - connection_strings_node = "${join("\n", formatlist("%s ansible_host=%s", aws_instance.k8s-worker.*.tags.Name, aws_instance.k8s-worker.*.private_ip))}" - connection_strings_etcd = "${join("\n",formatlist("%s ansible_host=%s", aws_instance.k8s-etcd.*.tags.Name, aws_instance.k8s-etcd.*.private_ip))}" - list_master = "${join("\n",aws_instance.k8s-master.*.tags.Name)}" - list_node = "${join("\n",aws_instance.k8s-worker.*.tags.Name)}" - list_etcd = "${join("\n",aws_instance.k8s-etcd.*.tags.Name)}" - elb_api_fqdn = "apiserver_loadbalancer_domain_name=\"${module.aws-elb.aws_elb_api_fqdn}\"" - } - -} - -resource "null_resource" "inventories" { - provisioner "local-exec" { - command = "echo '${data.template_file.inventory.rendered}' > ../../../inventory/hosts" - } - - triggers { - template = "${data.template_file.inventory.rendered}" - } - -} \ No newline at end of file diff --git a/internal/cluster/testcase/credentials.tfvars b/internal/cluster/testcase/credentials.tfvars deleted file mode 100644 index 89e1e29..0000000 --- a/internal/cluster/testcase/credentials.tfvars +++ /dev/null @@ -1,4 +0,0 @@ -AWS_ACCESS_KEY_ID = "" -AWS_SECRET_ACCESS_KEY = "" -AWS_SSH_KEY_NAME = "" -AWS_DEFAULT_REGION = "" \ No newline at end of file diff --git a/internal/cluster/testcase/terraform.tfvars b/internal/cluster/testcase/terraform.tfvars deleted file mode 100644 index a135c86..0000000 --- a/internal/cluster/testcase/terraform.tfvars +++ /dev/null @@ -1,21 +0,0 @@ -aws_cluster_name = "kubernauts" -aws_vpc_cidr_block = "10.250.192.0/18" -aws_cidr_subnets_private = "["10.250.192.0/20","10.250.208.0/20"]" -aws_cidr_subnets_public = "["10.250.224.0/20","10.250.240.0/20"]" - -aws_bastion_size = "t2.medium" -aws_kube_master_num = "1" -aws_kube_master_size = "t2.medium" -aws_etcd_num = "1" - -aws_etcd_size = "t2.medium" -aws_kube_worker_num = "2" -aws_kube_worker_size = "t2.medium" -aws_elb_api_port = "6443" -k8s_secure_api_port = "6443" -kube_insecure_apiserver_address = "" - -default_tags = { - Env = "devtest" - Product = "kubernetes" -} \ No newline at end of file diff --git a/internal/cluster/testcase/variables.tf b/internal/cluster/testcase/variables.tf deleted file mode 100644 index 90570f0..0000000 --- a/internal/cluster/testcase/variables.tf +++ /dev/null @@ -1,105 +0,0 @@ -variable "AWS_ACCESS_KEY_ID" { - description = "AWS Access Key" -} - -variable "AWS_SECRET_ACCESS_KEY" { - description = "AWS Secret Key" -} - -variable "AWS_SSH_KEY_NAME" { - description = "Name of the SSH keypair to use in AWS." -} - -variable "AWS_DEFAULT_REGION" { - description = "AWS Region" -} - -//General Cluster Settings - -variable "aws_cluster_name" { - description = "Name of AWS Cluster" -} - -data "aws_ami" "distro" { - most_recent = true - - filter { - name = "name" - values = ["dcos-centos7-*"] - } - - filter { - name = "virtualization-type" - values = ["hvm"] - } - - owners = ["688023202711"] #CoreOS -} - -//AWS VPC Variables - -variable "aws_vpc_cidr_block" { - description = "CIDR Block for VPC" -} - -variable "aws_cidr_subnets_private" { - description = "CIDR Blocks for private subnets in Availability Zones" - type = "list" -} - -variable "aws_cidr_subnets_public" { - description = "CIDR Blocks for public subnets in Availability Zones" - type = "list" -} - -//AWS EC2 Settings - -variable "aws_bastion_size" { - description = "EC2 Instance Size of Bastion Host" -} - -/* -* AWS EC2 Settings -* The number should be divisable by the number of used -* AWS Availability Zones without an remainder. -*/ -variable "aws_kube_master_num" { - description = "Number of Kubernetes Master Nodes" -} - -variable "aws_kube_master_size" { - description = "Instance size of Kube Master Nodes" -} - -variable "aws_etcd_num" { - description = "Number of etcd Nodes" -} - -variable "aws_etcd_size" { - description = "Instance size of etcd Nodes" -} - -variable "aws_kube_worker_num" { - description = "Number of Kubernetes Worker Nodes" -} - -variable "aws_kube_worker_size" { - description = "Instance size of Kubernetes Worker Nodes" -} - -/* -* AWS ELB Settings -* -*/ -variable "aws_elb_api_port" { - description = "Port for AWS ELB" -} - -variable "k8s_secure_api_port" { - description = "Secure Port of K8S API Server" -} - -variable "default_tags" { - description = "Default tags for all resources" - type = "map" -} From f8dde6a00dd0d4ff0aa0a794f60d534c4aab2930 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20M=C3=BCller?= Date: Sat, 11 Aug 2018 13:47:17 +0200 Subject: [PATCH 9/9] add file prepare MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Manuel Müller --- internal/cluster/aws.go | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/internal/cluster/aws.go b/internal/cluster/aws.go index 69ebdc1..3a056c9 100644 --- a/internal/cluster/aws.go +++ b/internal/cluster/aws.go @@ -4,6 +4,8 @@ import ( "bufio" "fmt" "html/template" + "io" + "io/ioutil" "log" "net" "os" @@ -97,10 +99,10 @@ func (aws *AWS) DistSelect() (string, string) { // TODO change to parallel creation // prepare config - if !aws.CreateFileFromTemplate("/configs/templates/kubespray-aws-variables.tf", "./"+aws.Namespace+"/variables.tf", awsInstanceOS, nil) { + if !aws.CreateFileFromTemplate("/configs/templates/kubespray-aws-variables.tf", "variables.tf", awsInstanceOS, nil) { return "", "" } - if !aws.CreateFileFromTemplate("/configs/templates/kubespray-aws-create-infra.tf", "./"+aws.Namespace+"/create-infrastructure.tf", awsInstanceOS, nil) { + if !aws.CreateFileFromTemplate("/configs/templates/kubespray-aws-create-infra.tf", "create-infrastructure.tf", awsInstanceOS, nil) { return "", "" } @@ -150,6 +152,24 @@ func (aws *AWS) GetClusterConfig() ClusterConfig { } } +func (aws *AWS) prepareBuilderFiles() { + + _ = os.Mkdir(aws.GetAbsPath(".")+"/"+aws.Namespace, os.ModePerm) + + files, err := ioutil.ReadDir("./kubespray/contrib/terraform/aws/") + if err != nil { + log.Fatal(err) + } + + for _, f := range files { + inFileReader, _ := os.Open("./kubespray/contrib/terraform/aws/" + f.Name()) + defer inFileReader.Close() + outWriter, _ := os.Open(aws.GetAbsPath(".") + "/" + aws.Namespace + "/" + f.Name()) + defer outWriter.Close() + io.Copy(outWriter, inFileReader) + } +} + // Create a aws kubernetes cluster with terraform func (aws *AWS) Create() { if !aws.OSHelper.CheckDependency("terraform") { @@ -160,12 +180,15 @@ func (aws *AWS) Create() { if err != nil { return // cancel process } + + aws.prepareBuilderFiles() + if _, err := aws.OSHelper.FileInfo("/configs/templates/credentials.tfvars"); err != nil { - if !aws.CreateFileFromTemplate("/configs/templates/kubespray-aws-credentials.tfvars", "./"+aws.Namespace+"/credentials.tfvars", aws.Namespace, aws.GetCredentials()) { + if !aws.CreateFileFromTemplate("/configs/templates/kubespray-aws-credentials.tfvars", "credentials.tfvars", aws.Namespace, aws.GetCredentials()) { return // cancel process } } - if !aws.CreateFileFromTemplate("/configs/templates/kubespray-aws-terraform.tfvars", "./"+aws.Namespace+"/terraform.tfvars", aws.Namespace, aws.GetClusterConfig()) { + if !aws.CreateFileFromTemplate("/configs/templates/kubespray-aws-terraform.tfvars", "terraform.tfvars", aws.Namespace, aws.GetClusterConfig()) { return // cancel process }