diff --git a/pkg/cfn/builder/api_test.go b/pkg/cfn/builder/api_test.go index 4f7835ef568..a22a2ed1021 100644 --- a/pkg/cfn/builder/api_test.go +++ b/pkg/cfn/builder/api_test.go @@ -25,11 +25,12 @@ import ( ) const ( - totalNodeResources = 10 - clusterName = "ferocious-mushroom-1532594698" - endpoint = "https://DE37D8AFB23F7275D2361AD6B2599143.yl4.us-west-2.eks.amazonaws.com" - caCert = "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5RENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRFNE1EWXdOekExTlRBMU5Wb1hEVEk0TURZd05EQTFOVEExTlZvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTWJoCnpvZElYR0drckNSZE1jUmVEN0YvMnB1NFZweTdvd3FEVDgrdk9zeGs2bXFMNWxQd3ZicFhmYkE3R0xzMDVHa0wKaDdqL0ZjcU91cnMwUFZSK3N5REtuQXltdDFORWxGNllGQktSV1dUQ1hNd2lwN1pweW9XMXdoYTlJYUlPUGxCTQpPTEVlckRabFVrVDFVV0dWeVdsMmxPeFgxa2JhV2gvakptWWdkeW5jMXhZZ3kxa2JybmVMSkkwLzVUVTRCajJxClB1emtrYW5Xd3lKbGdXQzhBSXlpWW82WFh2UVZmRzYrM3RISE5XM1F1b3ZoRng2MTFOYnl6RUI3QTdtZGNiNmgKR0ZpWjdOeThHZnFzdjJJSmI2Nk9FVzBSdW9oY1k3UDZPdnZmYnlKREhaU2hqTStRWFkxQXN5b3g4Ri9UelhHSgpQUWpoWUZWWEVhZU1wQmJqNmNFQ0F3RUFBYU1qTUNFd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFCa2hKRVd4MHk1LzlMSklWdXJ1c1hZbjN6Z2EKRkZ6V0JsQU44WTlqUHB3S2t0Vy9JNFYyUGg3bWY2Z3ZwZ3Jhc2t1Slk1aHZPcDdBQmcxSTFhaHUxNUFpMUI0ZApuMllRaDlOaHdXM2pKMmhuRXk0VElpb0gza2JFdHRnUVB2bWhUQzNEYUJreEpkbmZJSEJCV1RFTTU1czRwRmxUClpzQVJ3aDc1Q3hYbjdScVU0akpKcWNPaTRjeU5qeFVpRDBqR1FaTmNiZWEyMkRCeTJXaEEzUWZnbGNScGtDVGUKRDVPS3NOWlF4MW9MZFAwci9TSmtPT1NPeUdnbVJURTIrODQxN21PRW02Z3RPMCszdWJkbXQ0aENsWEtFTTZYdwpuQWNlK0JxVUNYblVIN2ZNS3p2TDE5UExvMm5KbFU1TnlCbU1nL1pNVHVlUy80eFZmKy94WnpsQ0Q1WT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=" - arn = "arn:aws:eks:us-west-2:122333:cluster/" + clusterName + typicalNodeResources = 10 + + clusterName = "ferocious-mushroom-1532594698" + endpoint = "https://DE37D8AFB23F7275D2361AD6B2599143.yl4.us-west-2.eks.amazonaws.com" + caCert = "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5RENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRFNE1EWXdOekExTlRBMU5Wb1hEVEk0TURZd05EQTFOVEExTlZvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTWJoCnpvZElYR0drckNSZE1jUmVEN0YvMnB1NFZweTdvd3FEVDgrdk9zeGs2bXFMNWxQd3ZicFhmYkE3R0xzMDVHa0wKaDdqL0ZjcU91cnMwUFZSK3N5REtuQXltdDFORWxGNllGQktSV1dUQ1hNd2lwN1pweW9XMXdoYTlJYUlPUGxCTQpPTEVlckRabFVrVDFVV0dWeVdsMmxPeFgxa2JhV2gvakptWWdkeW5jMXhZZ3kxa2JybmVMSkkwLzVUVTRCajJxClB1emtrYW5Xd3lKbGdXQzhBSXlpWW82WFh2UVZmRzYrM3RISE5XM1F1b3ZoRng2MTFOYnl6RUI3QTdtZGNiNmgKR0ZpWjdOeThHZnFzdjJJSmI2Nk9FVzBSdW9oY1k3UDZPdnZmYnlKREhaU2hqTStRWFkxQXN5b3g4Ri9UelhHSgpQUWpoWUZWWEVhZU1wQmJqNmNFQ0F3RUFBYU1qTUNFd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFCa2hKRVd4MHk1LzlMSklWdXJ1c1hZbjN6Z2EKRkZ6V0JsQU44WTlqUHB3S2t0Vy9JNFYyUGg3bWY2Z3ZwZ3Jhc2t1Slk1aHZPcDdBQmcxSTFhaHUxNUFpMUI0ZApuMllRaDlOaHdXM2pKMmhuRXk0VElpb0gza2JFdHRnUVB2bWhUQzNEYUJreEpkbmZJSEJCV1RFTTU1czRwRmxUClpzQVJ3aDc1Q3hYbjdScVU0akpKcWNPaTRjeU5qeFVpRDBqR1FaTmNiZWEyMkRCeTJXaEEzUWZnbGNScGtDVGUKRDVPS3NOWlF4MW9MZFAwci9TSmtPT1NPeUdnbVJURTIrODQxN21PRW02Z3RPMCszdWJkbXQ0aENsWEtFTTZYdwpuQWNlK0JxVUNYblVIN2ZNS3p2TDE5UExvMm5KbFU1TnlCbU1nL1pNVHVlUy80eFZmKy94WnpsQ0Q1WT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=" + arn = "arn:aws:eks:us-west-2:122333:cluster/" + clusterName vpcID = "vpc-0e265ad953062b94b" subnetsPublic = "subnet-0f98135715dfcf55f,subnet-0ade11bad78dced9e,subnet-0e2e63ff1712bf6ef" @@ -194,17 +195,24 @@ func newStackWithOutputs(outputs map[string]string) cfn.Stack { } var _ = Describe("CloudFormation template builder API", func() { - var caCertData []byte + var ( + cc *cloudconfig.CloudConfig + crs *ClusterResourceSet + ngrs *NodeGroupResourceSet + obj *Template + err error + + caCertData []byte + ) Describe("should decode CA data", func() { - var err error caCertData, err = base64.StdEncoding.DecodeString(caCert) It("should not error", func() { Expect(err).ShouldNot(HaveOccurred()) }) }) testAZs := []string{"us-west-2b", "us-west-2a", "us-west-2c"} - newClusterConfigAndNodegroup := func() (*api.ClusterConfig, *api.NodeGroup) { + newClusterConfigAndNodegroup := func(withFullVPC bool) (*api.ClusterConfig, *api.NodeGroup) { cfg := api.NewClusterConfig() ng := cfg.NewNodeGroup() @@ -223,13 +231,17 @@ var _ = Describe("CloudFormation template builder API", func() { ng.VolumeSize = 2 ng.VolumeType = api.NodeVolumeTypeIO1 - *cfg.VPC.CIDR = api.DefaultCIDR() + if withFullVPC { + cfg.VPC = testVPC() + } else { + *cfg.VPC.CIDR = api.DefaultCIDR() + } return cfg, ng } - newClusterConfig := func() *api.ClusterConfig { - cfg, _ := newClusterConfigAndNodegroup() + newSimpleClusterConfig := func() *api.ClusterConfig { + cfg, _ := newClusterConfigAndNodegroup(false) return cfg } @@ -334,7 +346,7 @@ var _ = Describe("CloudFormation template builder API", func() { }, } - cfg := newClusterConfig() + cfg := newSimpleClusterConfig() It("should not error when calling SetSubnets", func() { err := vpc.SetSubnets(cfg) @@ -342,14 +354,8 @@ var _ = Describe("CloudFormation template builder API", func() { }) It("should have public and private subnets", func() { - Expect(len(cfg.VPC.Subnets.Private)).To(Equal(3)) - Expect(len(cfg.VPC.Subnets.Public)).To(Equal(3)) - }) - - rs := NewClusterResourceSet(p, cfg) - It("should add all resources without error", func() { - err := rs.AddAllResources() - Expect(err).ShouldNot(HaveOccurred()) + Expect(cfg.VPC.Subnets.Private).To(HaveLen(3)) + Expect(cfg.VPC.Subnets.Public).To(HaveLen(3)) }) sampleOutputs := map[string]string{ @@ -365,14 +371,16 @@ var _ = Describe("CloudFormation template builder API", func() { "ServiceRoleARN": arn, } - sampleStack := newStackWithOutputs(sampleOutputs) - - It("should not error", func() { - err := rs.GetAllOutputs(sampleStack) + It("should add all resources and collect outputs without errors", func() { + crs = NewClusterResourceSet(p, cfg) + err := crs.AddAllResources() + Expect(err).ShouldNot(HaveOccurred()) + sampleStack := newStackWithOutputs(sampleOutputs) + err = crs.GetAllOutputs(sampleStack) Expect(err).ShouldNot(HaveOccurred()) }) - It("should be equal", func() { + It("resulting config should match what is expected", func() { cfgData, err := json.Marshal(cfg) Expect(err).ShouldNot(HaveOccurred()) expectedData, err := json.Marshal(expected) @@ -381,37 +389,47 @@ var _ = Describe("CloudFormation template builder API", func() { }) }) - Describe("AutoNameTag", func() { - cfg, ng := newClusterConfigAndNodegroup() - - rs := NewNodeGroupResourceSet(p, cfg, "eksctl-test-123-cluster", ng) - - err := rs.AddAllResources() + build := func(cfg *api.ClusterConfig, name string, ng *api.NodeGroup) { It("should add all resources without errors", func() { + crs = NewClusterResourceSet(p, cfg) + err = crs.AddAllResources() + Expect(err).ShouldNot(HaveOccurred()) + + ngrs = NewNodeGroupResourceSet(p, cfg, name, ng) + err = ngrs.AddAllResources() Expect(err).ShouldNot(HaveOccurred()) - t := rs.Template() - Expect(t.Resources).ToNot(BeEmpty()) - Expect(len(t.Resources)).To(Equal(totalNodeResources)) + + t := ngrs.Template() + Expect(len(t.Resources) >= typicalNodeResources).To(BeTrue()) + Expect(t.Resources).Should(HaveKey("NodeGroup")) + templateBody, err := t.JSON() Expect(err).ShouldNot(HaveOccurred()) Expect(templateBody).ShouldNot(BeEmpty()) }) + } - templateBody, err := rs.RenderJSON() - It("should serialise JSON without errors", func() { + roundtript := func() { + It("should serialise JSON without errors, and parse the teamplate", func() { + obj = &Template{} + templateBody, err := ngrs.RenderJSON() Expect(err).ShouldNot(HaveOccurred()) - Expect(templateBody).ShouldNot(BeEmpty()) - }) - obj := Template{} - It("should parse JSON without errors", func() { - err := json.Unmarshal(templateBody, &obj) + err = json.Unmarshal(templateBody, obj) Expect(err).ShouldNot(HaveOccurred()) }) + } + + Context("AutoNameTag", func() { + cfg, ng := newClusterConfigAndNodegroup(true) + + build(cfg, "eksctl-test-123-cluster", ng) + + roundtript() It("SG should have correct tags", func() { Expect(obj.Resources).ToNot(BeNil()) - Expect(len(obj.Resources)).To(Equal(totalNodeResources)) - Expect(len(obj.Resources["SG"].Properties.Tags)).To(Equal(2)) + Expect(obj.Resources).To(HaveLen(typicalNodeResources)) + Expect(obj.Resources["SG"].Properties.Tags).To(HaveLen(2)) Expect(obj.Resources["SG"].Properties.Tags[0].Key).To(Equal("kubernetes.io/cluster/" + clusterName)) Expect(obj.Resources["SG"].Properties.Tags[0].Value).To(Equal("owned")) Expect(obj.Resources["SG"].Properties.Tags[1].Key).To(Equal("Name")) @@ -421,31 +439,19 @@ var _ = Describe("CloudFormation template builder API", func() { }) }) - Describe("NodeGroupTags", func() { - cfg, ng := newClusterConfigAndNodegroup() + Context("NodeGroupTags", func() { + cfg, ng := newClusterConfigAndNodegroup(true) ng.InstanceType = "t2.medium" ng.Name = "ng-abcd1234" - rs := NewNodeGroupResourceSet(p, cfg, "eksctl-test-123-cluster", ng) - err := rs.AddAllResources() - It("should add all resources without errors", func() { - Expect(err).ShouldNot(HaveOccurred()) - }) + build(cfg, "eksctl-test-123-cluster", ng) - template, err := rs.RenderJSON() - It("should serialise JSON without errors", func() { - Expect(err).ShouldNot(HaveOccurred()) - }) - obj := Template{} - It("should parse JSON without errors", func() { - err := json.Unmarshal(template, &obj) - Expect(err).ShouldNot(HaveOccurred()) - }) + roundtript() It("should have correct tags", func() { - Expect(len(obj.Resources)).ToNot(Equal(0)) - Expect(len(obj.Resources["NodeGroup"].Properties.Tags)).To(Equal(2)) + Expect(obj.Resources).ToNot(BeEmpty()) + Expect(obj.Resources["NodeGroup"].Properties.Tags).To(HaveLen(2)) Expect(obj.Resources["NodeGroup"].Properties.Tags[0].Key).To(Equal("Name")) Expect(obj.Resources["NodeGroup"].Properties.Tags[0].Value).To(Equal(clusterName + "-ng-abcd1234-Node")) Expect(obj.Resources["NodeGroup"].Properties.Tags[0].PropagateAtLaunch).To(Equal("true")) @@ -455,31 +461,19 @@ var _ = Describe("CloudFormation template builder API", func() { }) }) - Describe("NodeGroupAutoScaling", func() { - cfg, ng := newClusterConfigAndNodegroup() + Context("NodeGroupAutoScaling", func() { + cfg, ng := newClusterConfigAndNodegroup(true) ng.IAM.WithAddonPolicies.AutoScaler = api.NewBoolTrue() - rs := NewNodeGroupResourceSet(p, cfg, "eksctl-test-123-cluster", ng) - err := rs.AddAllResources() - It("should add all resources without errors", func() { - Expect(err).ShouldNot(HaveOccurred()) - }) + build(cfg, "eksctl-test-123-cluster", ng) - template, err := rs.RenderJSON() - It("should serialise JSON without errors", func() { - Expect(err).ShouldNot(HaveOccurred()) - }) - obj := Template{} - It("should parse JSON without errors", func() { - err := json.Unmarshal(template, &obj) - Expect(err).ShouldNot(HaveOccurred()) - }) + roundtript() It("should have correct policies", func() { - Expect(len(obj.Resources)).ToNot(Equal(0)) + Expect(obj.Resources).ToNot(BeEmpty()) Expect(obj.Resources["PolicyAutoScaling"]).ToNot(BeNil()) - Expect(len(obj.Resources["PolicyAutoScaling"].Properties.PolicyDocument.Statement)).To(Equal(1)) + Expect(obj.Resources["PolicyAutoScaling"].Properties.PolicyDocument.Statement).To(HaveLen(1)) Expect(obj.Resources["PolicyAutoScaling"].Properties.PolicyDocument.Statement[0].Effect).To(Equal("Allow")) Expect(obj.Resources["PolicyAutoScaling"].Properties.PolicyDocument.Statement[0].Resource).To(Equal("*")) Expect(obj.Resources["PolicyAutoScaling"].Properties.PolicyDocument.Statement[0].Action).To(Equal([]string{ @@ -525,29 +519,17 @@ var _ = Describe("CloudFormation template builder API", func() { }) }) - Describe("NodeGroup{PrivateNetworking=true AllowSSH=true}", func() { - cfg, ng := newClusterConfigAndNodegroup() + Context("NodeGroup{PrivateNetworking=true AllowSSH=true}", func() { + cfg, ng := newClusterConfigAndNodegroup(true) ng.AllowSSH = true ng.InstanceType = "t2.medium" ng.PrivateNetworking = true ng.AMIFamily = "AmazonLinux2" - rs := NewNodeGroupResourceSet(p, cfg, "eksctl-test-private-ng", ng) - err := rs.AddAllResources() - It("should add all resources without errors", func() { - Expect(err).ShouldNot(HaveOccurred()) - }) + build(cfg, "eksctl-test-private-ng", ng) - template, err := rs.RenderJSON() - It("should serialise JSON without errors", func() { - Expect(err).ShouldNot(HaveOccurred()) - }) - obj := Template{} - It("should parse JSON without errors", func() { - err := json.Unmarshal(template, &obj) - Expect(err).ShouldNot(HaveOccurred()) - }) + roundtript() It("should have correct description", func() { Expect(obj.Description).To(ContainSubstring("AMI family: AmazonLinux2")) @@ -556,12 +538,12 @@ var _ = Describe("CloudFormation template builder API", func() { }) It("should have correct resources and attributes", func() { - Expect(len(obj.Resources)).ToNot(Equal(0)) + Expect(obj.Resources).ToNot(BeEmpty()) - Expect(obj.Resources["NodeGroup"].Properties.VPCZoneIdentifier).To(Not(BeNil())) + Expect(obj.Resources["NodeGroup"].Properties.VPCZoneIdentifier).ToNot(BeNil()) x, ok := obj.Resources["NodeGroup"].Properties.VPCZoneIdentifier.(map[string]interface{}) Expect(ok).To(BeTrue()) - Expect(len(x)).To(Equal(1)) + Expect(x).To(HaveLen(1)) refSubnets := map[string]interface{}{ "Fn::Split": []interface{}{ ",", @@ -578,34 +560,21 @@ var _ = Describe("CloudFormation template builder API", func() { Expect(obj.Resources["SSHIPv4"].Properties.FromPort).To(Equal(22)) Expect(obj.Resources["SSHIPv4"].Properties.ToPort).To(Equal(22)) - Expect(obj.Resources).To(Not(HaveKey("SSHIPv6"))) + Expect(obj.Resources).ToNot(HaveKey("SSHIPv6")) }) }) - Describe("NodeGroup{PrivateNetworking=false AllowSSH=true}", func() { - cfg, ng := newClusterConfigAndNodegroup() + Context("NodeGroup{PrivateNetworking=false AllowSSH=true}", func() { + cfg, ng := newClusterConfigAndNodegroup(true) ng.AllowSSH = true ng.InstanceType = "t2.medium" ng.PrivateNetworking = false ng.AMIFamily = "AmazonLinux2" - rs := NewNodeGroupResourceSet(p, cfg, "eksctl-test-public-ng", ng) - err := rs.AddAllResources() - It("should add all resources without errors", func() { - Expect(err).ShouldNot(HaveOccurred()) - }) - - template, err := rs.RenderJSON() - It("should serialise JSON without errors", func() { - Expect(err).ShouldNot(HaveOccurred()) - }) + build(cfg, "eksctl-test-public-ng", ng) - obj := Template{} - It("should parse JSON without errors", func() { - err := json.Unmarshal(template, &obj) - Expect(err).ShouldNot(HaveOccurred()) - }) + roundtript() It("should have correct description", func() { Expect(obj.Description).To(ContainSubstring("AMI family: AmazonLinux2")) @@ -614,12 +583,12 @@ var _ = Describe("CloudFormation template builder API", func() { }) It("should have correct resources and attributes", func() { - Expect(len(obj.Resources)).ToNot(Equal(0)) + Expect(obj.Resources).ToNot(BeEmpty()) - Expect(obj.Resources["NodeGroup"].Properties.VPCZoneIdentifier).To(Not(BeNil())) + Expect(obj.Resources["NodeGroup"].Properties.VPCZoneIdentifier).ToNot(BeNil()) x, ok := obj.Resources["NodeGroup"].Properties.VPCZoneIdentifier.(map[string]interface{}) Expect(ok).To(BeTrue()) - Expect(len(x)).To(Equal(1)) + Expect(x).To(HaveLen(1)) refSubnets := map[string]interface{}{ "Fn::Split": []interface{}{ ",", @@ -642,8 +611,8 @@ var _ = Describe("CloudFormation template builder API", func() { }) }) - Describe("NodeGroup{PrivateNetworking=false AllowSSH=false}", func() { - cfg, ng := newClusterConfigAndNodegroup() + Context("NodeGroup{PrivateNetworking=false AllowSSH=false}", func() { + cfg, ng := newClusterConfigAndNodegroup(true) cfg.VPC = &api.ClusterVPC{ Network: api.Network{ @@ -686,21 +655,9 @@ var _ = Describe("CloudFormation template builder API", func() { Expect(ng.AvailabilityZones).To(Equal([]string{"us-west-2a"})) }) - rs := NewNodeGroupResourceSet(p, cfg, "eksctl-test-public-ng", ng) - err := rs.AddAllResources() - It("should add all resources without errors", func() { - Expect(err).ShouldNot(HaveOccurred()) - }) + build(cfg, "eksctl-test-public-ng", ng) - template, err := rs.RenderJSON() - It("should serialise JSON without errors", func() { - Expect(err).ShouldNot(HaveOccurred()) - }) - obj := Template{} - It("should parse JSON without errors", func() { - err := json.Unmarshal(template, &obj) - Expect(err).ShouldNot(HaveOccurred()) - }) + roundtript() It("should have correct description", func() { Expect(obj.Description).To(ContainSubstring("AMI family: AmazonLinux2")) @@ -709,9 +666,9 @@ var _ = Describe("CloudFormation template builder API", func() { }) It("should have correct resources and attributes", func() { - Expect(len(obj.Resources)).ToNot(Equal(0)) + Expect(obj.Resources).ToNot(BeEmpty()) - Expect(obj.Resources["NodeGroup"].Properties.VPCZoneIdentifier).To(Not(BeNil())) + Expect(obj.Resources["NodeGroup"].Properties.VPCZoneIdentifier).ToNot(BeNil()) x, ok := obj.Resources["NodeGroup"].Properties.VPCZoneIdentifier.([]interface{}) Expect(ok).To(BeTrue()) refSubnets := []interface{}{ @@ -721,9 +678,9 @@ var _ = Describe("CloudFormation template builder API", func() { Expect(obj.Resources["NodeLaunchConfig"].Properties.AssociatePublicIpAddress).To(BeTrue()) - Expect(obj.Resources).To(Not(HaveKey("SSHIPv4"))) + Expect(obj.Resources).ToNot(HaveKey("SSHIPv4")) - Expect(obj.Resources).To(Not(HaveKey("SSHIPv6"))) + Expect(obj.Resources).ToNot(HaveKey("SSHIPv6")) }) }) @@ -760,334 +717,289 @@ var _ = Describe("CloudFormation template builder API", func() { } } - Describe("UserData - AmazonLinux2", func() { - cfg, ng := newClusterConfigAndNodegroup() + Context("UserData - AmazonLinux2", func() { + cfg, ng := newClusterConfigAndNodegroup(true) - var c *cloudconfig.CloudConfig + ng.InstanceType = "m5.large" - cfg.NodeGroups[0].InstanceType = "m5.large" + build(cfg, "eksctl-test-123-cluster", ng) - rs := NewNodeGroupResourceSet(p, cfg, "eksctl-test-123-cluster", ng) - err := rs.AddAllResources() - It("should add all resources without errors", func() { - Expect(err).ShouldNot(HaveOccurred()) - }) + roundtript() - template, err := rs.RenderJSON() - It("should serialise JSON without errors", func() { - Expect(err).ShouldNot(HaveOccurred()) - }) - obj := Template{} - It("should parse JSON without errors and extract valid cloud-config using our implementation", func() { - err = json.Unmarshal(template, &obj) - Expect(err).ShouldNot(HaveOccurred()) - Expect(len(obj.Resources)).ToNot(Equal(0)) + It("should extract valid cloud-config using our implementation", func() { + Expect(obj.Resources).ToNot(BeEmpty()) userData := obj.Resources["NodeLaunchConfig"].Properties.UserData Expect(userData).ToNot(BeEmpty()) - c, err = cloudconfig.DecodeCloudConfig(userData) + cc, err = cloudconfig.DecodeCloudConfig(userData) Expect(err).ShouldNot(HaveOccurred()) }) It("should have packages, scripts and commands in cloud-config", func() { - Expect(c).ToNot(BeNil()) + Expect(cc).ToNot(BeNil()) - Expect(c.Packages).Should(BeEmpty()) + Expect(cc.Packages).Should(BeEmpty()) - kubeletEnv := getFile(c, "/etc/eksctl/kubelet.env") + kubeletEnv := getFile(cc, "/etc/eksctl/kubelet.env") Expect(kubeletEnv).ToNot(BeNil()) Expect(kubeletEnv.Permissions).To(Equal("0644")) Expect(strings.Split(kubeletEnv.Content, "\n")).To(Equal([]string{ - "MAX_PODS=29", - "CLUSTER_DNS=10.100.0.10", "NODE_LABELS=", })) - kubeletDropInUnit := getFile(c, "/etc/systemd/system/kubelet.service.d/10-eksclt.al2.conf") + kubeletDropInUnit := getFile(cc, "/etc/systemd/system/kubelet.service.d/10-eksclt.al2.conf") Expect(kubeletDropInUnit).ToNot(BeNil()) Expect(kubeletDropInUnit.Permissions).To(Equal("0644")) checkAsset("10-eksclt.al2.conf", kubeletDropInUnit.Content) - kubeconfig := getFile(c, "/etc/eksctl/kubeconfig.yaml") + kubeconfig := getFile(cc, "/etc/eksctl/kubeconfig.yaml") Expect(kubeconfig).ToNot(BeNil()) Expect(kubeconfig.Permissions).To(Equal("0644")) - Expect(kubeconfig.Content).To(Equal(kubeconfigBody("aws-iam-authenticator"))) + Expect(kubeconfig.Content).To(MatchYAML(kubeconfigBody("aws-iam-authenticator"))) + + kubeletConfigAssetContent, err := nodebootstrap.Asset("kubelet.yaml") + Expect(err).ToNot(HaveOccurred()) + + kubeletConfigAssetContentString := string(kubeletConfigAssetContent) + + "\n" + + "maxPods: 29\n" + + "clusterDNS: [10.100.0.10]\n" + + kubeletConfig := getFile(cc, "/etc/eksctl/kubelet.yaml") + Expect(kubeletConfig).ToNot(BeNil()) + Expect(kubeletConfig.Permissions).To(Equal("0644")) - ca := getFile(c, "/etc/eksctl/ca.crt") + Expect(kubeletConfig.Content).To(MatchYAML(kubeletConfigAssetContentString)) + + ca := getFile(cc, "/etc/eksctl/ca.crt") Expect(ca).ToNot(BeNil()) Expect(ca.Permissions).To(Equal("0644")) Expect(ca.Content).To(Equal(string(caCertData))) - checkScript(c, "/var/lib/cloud/scripts/per-instance/bootstrap.al2.sh", true) + checkScript(cc, "/var/lib/cloud/scripts/per-instance/bootstrap.al2.sh", true) }) }) - Describe("UserData - AmazonLinux2 (custom pre-bootstrap)", func() { - cfg, ng := newClusterConfigAndNodegroup() - - var c *cloudconfig.CloudConfig + Context("UserData - AmazonLinux2 (custom pre-bootstrap)", func() { + cfg, ng := newClusterConfigAndNodegroup(true) - cfg.NodeGroups[0].InstanceType = "m5.large" + ng.InstanceType = "m5.large" - cfg.NodeGroups[0].PreBootstrapCommands = []string{ + ng.PreBootstrapCommands = []string{ "touch /tmp/test", "rm /tmp/test", } - rs := NewNodeGroupResourceSet(p, cfg, "eksctl-test-123-cluster", ng) - err := rs.AddAllResources() - It("should add all resources without errors", func() { - Expect(err).ShouldNot(HaveOccurred()) - }) + build(cfg, "eksctl-test-123-cluster", ng) - template, err := rs.RenderJSON() - It("should serialise JSON without errors", func() { - Expect(err).ShouldNot(HaveOccurred()) - }) - obj := Template{} - It("should parse JSON without errors and extract valid cloud-config using our implementation", func() { - err = json.Unmarshal(template, &obj) - Expect(err).ShouldNot(HaveOccurred()) - Expect(len(obj.Resources)).ToNot(Equal(0)) + roundtript() + + It("should extract valid cloud-config using our implementation", func() { + Expect(obj.Resources).ToNot(BeEmpty()) userData := obj.Resources["NodeLaunchConfig"].Properties.UserData Expect(userData).ToNot(BeEmpty()) - c, err = cloudconfig.DecodeCloudConfig(userData) + cc, err = cloudconfig.DecodeCloudConfig(userData) Expect(err).ShouldNot(HaveOccurred()) }) It("should have packages, scripts and commands in cloud-config", func() { - Expect(c).ToNot(BeNil()) + Expect(cc).ToNot(BeNil()) - Expect(c.Packages).Should(BeEmpty()) + Expect(cc.Packages).Should(BeEmpty()) - kubeletEnv := getFile(c, "/etc/eksctl/kubelet.env") + kubeletEnv := getFile(cc, "/etc/eksctl/kubelet.env") Expect(kubeletEnv).ToNot(BeNil()) Expect(kubeletEnv.Permissions).To(Equal("0644")) Expect(strings.Split(kubeletEnv.Content, "\n")).To(Equal([]string{ - "MAX_PODS=29", - "CLUSTER_DNS=10.100.0.10", "NODE_LABELS=", })) - kubeletDropInUnit := getFile(c, "/etc/systemd/system/kubelet.service.d/10-eksclt.al2.conf") + kubeletDropInUnit := getFile(cc, "/etc/systemd/system/kubelet.service.d/10-eksclt.al2.conf") Expect(kubeletDropInUnit).ToNot(BeNil()) Expect(kubeletDropInUnit.Permissions).To(Equal("0644")) checkAsset("10-eksclt.al2.conf", kubeletDropInUnit.Content) - kubeconfig := getFile(c, "/etc/eksctl/kubeconfig.yaml") + kubeconfig := getFile(cc, "/etc/eksctl/kubeconfig.yaml") Expect(kubeconfig).ToNot(BeNil()) Expect(kubeconfig.Permissions).To(Equal("0644")) - Expect(kubeconfig.Content).To(Equal(kubeconfigBody("aws-iam-authenticator"))) + Expect(kubeconfig.Content).To(MatchYAML(kubeconfigBody("aws-iam-authenticator"))) - ca := getFile(c, "/etc/eksctl/ca.crt") + ca := getFile(cc, "/etc/eksctl/ca.crt") Expect(ca).ToNot(BeNil()) Expect(ca.Permissions).To(Equal("0644")) Expect(ca.Content).To(Equal(string(caCertData))) - checkScript(c, "/var/lib/cloud/scripts/per-instance/bootstrap.al2.sh", true) + checkScript(cc, "/var/lib/cloud/scripts/per-instance/bootstrap.al2.sh", true) - for i, cmd := range cfg.NodeGroups[0].PreBootstrapCommands { - Expect(c.Commands[i].([]interface{})[0]).To(Equal("/bin/bash")) - Expect(c.Commands[i].([]interface{})[1]).To(Equal("-c")) - Expect(c.Commands[i].([]interface{})[2]).To(Equal(cmd)) + Expect(cc.Commands).To(HaveLen(len(ng.PreBootstrapCommands) + 1)) + for i, cmd := range ng.PreBootstrapCommands { + c := cc.Commands[i].([]interface{}) + Expect(c[0]).To(Equal("/bin/bash")) + Expect(c[1]).To(Equal("-c")) + Expect(c[2]).To(Equal(cmd)) } }) }) - Describe("UserData - AmazonLinux2 (custom bootstrap)", func() { - cfg, ng := newClusterConfigAndNodegroup() + Context("UserData - AmazonLinux2 (custom bootstrap)", func() { + cfg, ng := newClusterConfigAndNodegroup(true) - var c *cloudconfig.CloudConfig - - cfg.NodeGroups[0].InstanceType = "m5.large" - cfg.NodeGroups[0].Labels = map[string]string{ + ng.InstanceType = "m5.large" + ng.Labels = map[string]string{ "os": "al2", } - cfg.NodeGroups[0].OverrideBootstrapCommand = &overrideBootstrapCommand + ng.OverrideBootstrapCommand = &overrideBootstrapCommand - cfg.NodeGroups[0].ClusterDNS = "169.254.20.10" + ng.ClusterDNS = "169.254.20.10" - rs := NewNodeGroupResourceSet(p, cfg, "eksctl-test-123-cluster", ng) - err := rs.AddAllResources() - It("should add all resources without errors", func() { - Expect(err).ShouldNot(HaveOccurred()) - }) + build(cfg, "eksctl-test-123-cluster", ng) - template, err := rs.RenderJSON() - It("should serialise JSON without errors", func() { - Expect(err).ShouldNot(HaveOccurred()) - }) - obj := Template{} - It("should parse JSON without errors and extract valid cloud-config using our implementation", func() { - err = json.Unmarshal(template, &obj) - Expect(err).ShouldNot(HaveOccurred()) - Expect(len(obj.Resources)).ToNot(Equal(0)) + roundtript() + + It("should extract valid cloud-config using our implementation", func() { + Expect(obj.Resources).ToNot(BeEmpty()) userData := obj.Resources["NodeLaunchConfig"].Properties.UserData Expect(userData).ToNot(BeEmpty()) - c, err = cloudconfig.DecodeCloudConfig(userData) + cc, err = cloudconfig.DecodeCloudConfig(userData) Expect(err).ShouldNot(HaveOccurred()) }) It("should have packages, scripts and commands in cloud-config", func() { - Expect(c).ToNot(BeNil()) + Expect(cc).ToNot(BeNil()) - Expect(c.Packages).Should(BeEmpty()) + Expect(cc.Packages).Should(BeEmpty()) - kubeletEnv := getFile(c, "/etc/eksctl/kubelet.env") + kubeletEnv := getFile(cc, "/etc/eksctl/kubelet.env") Expect(kubeletEnv).ToNot(BeNil()) Expect(kubeletEnv.Permissions).To(Equal("0644")) Expect(strings.Split(kubeletEnv.Content, "\n")).To(Equal([]string{ - "MAX_PODS=29", - "CLUSTER_DNS=169.254.20.10", "NODE_LABELS=os=al2", })) - kubeletDropInUnit := getFile(c, "/etc/systemd/system/kubelet.service.d/10-eksclt.al2.conf") + kubeletDropInUnit := getFile(cc, "/etc/systemd/system/kubelet.service.d/10-eksclt.al2.conf") Expect(kubeletDropInUnit).ToNot(BeNil()) Expect(kubeletDropInUnit.Permissions).To(Equal("0644")) checkAsset("10-eksclt.al2.conf", kubeletDropInUnit.Content) - kubeconfig := getFile(c, "/etc/eksctl/kubeconfig.yaml") + kubeconfig := getFile(cc, "/etc/eksctl/kubeconfig.yaml") Expect(kubeconfig).ToNot(BeNil()) Expect(kubeconfig.Permissions).To(Equal("0644")) - Expect(kubeconfig.Content).To(Equal(kubeconfigBody("aws-iam-authenticator"))) + Expect(kubeconfig.Content).To(MatchYAML(kubeconfigBody("aws-iam-authenticator"))) - ca := getFile(c, "/etc/eksctl/ca.crt") + ca := getFile(cc, "/etc/eksctl/ca.crt") Expect(ca).ToNot(BeNil()) Expect(ca.Permissions).To(Equal("0644")) Expect(ca.Content).To(Equal(string(caCertData))) - script := getFile(c, "/var/lib/cloud/scripts/per-instance/bootstrap.al2.sh") + script := getFile(cc, "/var/lib/cloud/scripts/per-instance/bootstrap.al2.sh") Expect(script).To(BeNil()) - Expect(c.Commands).To(HaveLen(1)) - Expect(c.Commands[0]).To(HaveLen(3)) - Expect(c.Commands[0].([]interface{})[0]).To(Equal("/bin/bash")) - Expect(c.Commands[0].([]interface{})[1]).To(Equal("-c")) - Expect(c.Commands[0].([]interface{})[2]).To(Equal(overrideBootstrapCommand)) + Expect(cc.Commands).To(HaveLen(1)) + Expect(cc.Commands[0]).To(HaveLen(3)) + c := cc.Commands[0].([]interface{}) + Expect(c[0]).To(Equal("/bin/bash")) + Expect(c[1]).To(Equal("-c")) + Expect(c[2]).To(Equal(overrideBootstrapCommand)) }) }) - Describe("UserData - AmazonLinux2 (custom bootstrap and pre-bootstrap)", func() { - cfg, ng := newClusterConfigAndNodegroup() + Context("UserData - AmazonLinux2 (custom bootstrap and pre-bootstrap)", func() { + cfg, ng := newClusterConfigAndNodegroup(true) - var c *cloudconfig.CloudConfig - - cfg.NodeGroups[0].InstanceType = "m5.large" - cfg.NodeGroups[0].Labels = map[string]string{ + ng.InstanceType = "m5.large" + ng.Labels = map[string]string{ "os": "al2", } - cfg.NodeGroups[0].PreBootstrapCommands = []string{"echo 1 > /tmp/1", "echo 2 > /tmp/2", "echo 3 > /tmp/3"} - cfg.NodeGroups[0].OverrideBootstrapCommand = &overrideBootstrapCommand + ng.PreBootstrapCommands = []string{"echo 1 > /tmp/1", "echo 2 > /tmp/2", "echo 3 > /tmp/3"} + ng.OverrideBootstrapCommand = &overrideBootstrapCommand - cfg.NodeGroups[0].ClusterDNS = "169.254.20.10" + ng.ClusterDNS = "169.254.20.10" - rs := NewNodeGroupResourceSet(p, cfg, "eksctl-test-123-cluster", ng) - err := rs.AddAllResources() - It("should add all resources without errors", func() { - Expect(err).ShouldNot(HaveOccurred()) - }) + build(cfg, "eksctl-test-123-cluster", ng) + + roundtript() - template, err := rs.RenderJSON() - It("should serialise JSON without errors", func() { - Expect(err).ShouldNot(HaveOccurred()) - }) - obj := Template{} It("should parse JSON without errors and extract valid cloud-config using our implementation", func() { - err = json.Unmarshal(template, &obj) - Expect(err).ShouldNot(HaveOccurred()) - Expect(len(obj.Resources)).ToNot(Equal(0)) + Expect(obj.Resources).ToNot(BeEmpty()) userData := obj.Resources["NodeLaunchConfig"].Properties.UserData Expect(userData).ToNot(BeEmpty()) - c, err = cloudconfig.DecodeCloudConfig(userData) + cc, err = cloudconfig.DecodeCloudConfig(userData) Expect(err).ShouldNot(HaveOccurred()) }) It("should have packages, scripts and commands in cloud-config", func() { - Expect(c).ToNot(BeNil()) + Expect(cc).ToNot(BeNil()) - Expect(c.Packages).Should(BeEmpty()) + Expect(cc.Packages).Should(BeEmpty()) - kubeletEnv := getFile(c, "/etc/eksctl/kubelet.env") + kubeletEnv := getFile(cc, "/etc/eksctl/kubelet.env") Expect(kubeletEnv).ToNot(BeNil()) Expect(kubeletEnv.Permissions).To(Equal("0644")) Expect(strings.Split(kubeletEnv.Content, "\n")).To(Equal([]string{ - "MAX_PODS=29", - "CLUSTER_DNS=169.254.20.10", "NODE_LABELS=os=al2", })) - kubeletDropInUnit := getFile(c, "/etc/systemd/system/kubelet.service.d/10-eksclt.al2.conf") + kubeletDropInUnit := getFile(cc, "/etc/systemd/system/kubelet.service.d/10-eksclt.al2.conf") Expect(kubeletDropInUnit).ToNot(BeNil()) Expect(kubeletDropInUnit.Permissions).To(Equal("0644")) checkAsset("10-eksclt.al2.conf", kubeletDropInUnit.Content) - kubeconfig := getFile(c, "/etc/eksctl/kubeconfig.yaml") + kubeconfig := getFile(cc, "/etc/eksctl/kubeconfig.yaml") Expect(kubeconfig).ToNot(BeNil()) Expect(kubeconfig.Permissions).To(Equal("0644")) - Expect(kubeconfig.Content).To(Equal(kubeconfigBody("aws-iam-authenticator"))) + Expect(kubeconfig.Content).To(MatchYAML(kubeconfigBody("aws-iam-authenticator"))) - ca := getFile(c, "/etc/eksctl/ca.crt") + ca := getFile(cc, "/etc/eksctl/ca.crt") Expect(ca).ToNot(BeNil()) Expect(ca.Permissions).To(Equal("0644")) Expect(ca.Content).To(Equal(string(caCertData))) - script := getFile(c, "/var/lib/cloud/scripts/per-instance/bootstrap.al2.sh") + script := getFile(cc, "/var/lib/cloud/scripts/per-instance/bootstrap.al2.sh") Expect(script).To(BeNil()) - Expect(c.Commands).To(HaveLen(4)) - Expect(c.Commands[0]).To(HaveLen(3)) + Expect(cc.Commands).To(HaveLen(4)) + Expect(cc.Commands[0]).To(HaveLen(3)) - for i, cmd := range cfg.NodeGroups[0].PreBootstrapCommands { - Expect(c.Commands[i].([]interface{})[0]).To(Equal("/bin/bash")) - Expect(c.Commands[i].([]interface{})[1]).To(Equal("-c")) - Expect(c.Commands[i].([]interface{})[2]).To(Equal(cmd)) + for i, cmd := range ng.PreBootstrapCommands { + c := cc.Commands[i].([]interface{}) + Expect(c[0]).To(Equal("/bin/bash")) + Expect(c[1]).To(Equal("-c")) + Expect(c[2]).To(Equal(cmd)) } - Expect(c.Commands[3].([]interface{})[0]).To(Equal("/bin/bash")) - Expect(c.Commands[3].([]interface{})[1]).To(Equal("-c")) - Expect(c.Commands[3].([]interface{})[2]).To(Equal(overrideBootstrapCommand)) + Expect(cc.Commands[3].([]interface{})[0]).To(Equal("/bin/bash")) + Expect(cc.Commands[3].([]interface{})[1]).To(Equal("-c")) + Expect(cc.Commands[3].([]interface{})[2]).To(Equal(overrideBootstrapCommand)) }) }) - Describe("UserData - Ubuntu1804", func() { - cfg, ng := newClusterConfigAndNodegroup() - - var c *cloudconfig.CloudConfig + Context("UserData - Ubuntu1804", func() { + cfg, ng := newClusterConfigAndNodegroup(true) cfg.VPC.CIDR, _ = ipnet.ParseCIDR("10.1.0.0/16") - cfg.NodeGroups[0].AMIFamily = "Ubuntu1804" - cfg.NodeGroups[0].InstanceType = "m5.large" + ng.AMIFamily = "Ubuntu1804" + ng.InstanceType = "m5.large" - rs := NewNodeGroupResourceSet(p, cfg, "eksctl-test-123-cluster", ng) - err := rs.AddAllResources() - It("should add all resources without errors", func() { - Expect(err).ShouldNot(HaveOccurred()) - }) + build(cfg, "eksctl-test-123-cluster", ng) - template, err := rs.RenderJSON() - It("should serialise JSON without errors", func() { - Expect(err).ShouldNot(HaveOccurred()) - }) - obj := Template{} - It("should parse JSON without errors and extract valid cloud-config using our implementation", func() { - err = json.Unmarshal(template, &obj) - Expect(err).ShouldNot(HaveOccurred()) - Expect(len(obj.Resources)).ToNot(Equal(0)) + roundtript() + + It("should extract valid cloud-config using our implementation", func() { + Expect(obj.Resources).ToNot(BeEmpty()) userData := obj.Resources["NodeLaunchConfig"].Properties.UserData Expect(userData).ToNot(BeEmpty()) - c, err = cloudconfig.DecodeCloudConfig(userData) + cc, err = cloudconfig.DecodeCloudConfig(userData) Expect(err).ShouldNot(HaveOccurred()) }) @@ -1098,66 +1010,55 @@ var _ = Describe("CloudFormation template builder API", func() { }) It("should have packages, scripts and commands in cloud-config", func() { - Expect(c).ToNot(BeNil()) + Expect(cc).ToNot(BeNil()) - Expect(c.Packages).Should(BeEmpty()) + Expect(cc.Packages).Should(BeEmpty()) - kubeletEnv := getFile(c, "/etc/eksctl/kubelet.env") + kubeletEnv := getFile(cc, "/etc/eksctl/kubelet.env") Expect(kubeletEnv).ToNot(BeNil()) Expect(kubeletEnv.Permissions).To(Equal("0644")) Expect(strings.Split(kubeletEnv.Content, "\n")).To(Equal([]string{ + "NODE_LABELS=", "MAX_PODS=29", "CLUSTER_DNS=172.20.0.10", - "NODE_LABELS=", })) - kubeconfig := getFile(c, "/etc/eksctl/kubeconfig.yaml") + kubeconfig := getFile(cc, "/etc/eksctl/kubeconfig.yaml") Expect(kubeconfig).ToNot(BeNil()) Expect(kubeconfig.Permissions).To(Equal("0644")) - Expect(kubeconfig.Content).To(Equal(kubeconfigBody("heptio-authenticator-aws"))) + Expect(kubeconfig.Content).To(MatchYAML(kubeconfigBody("heptio-authenticator-aws"))) - ca := getFile(c, "/etc/eksctl/ca.crt") + ca := getFile(cc, "/etc/eksctl/ca.crt") Expect(ca).ToNot(BeNil()) Expect(ca.Permissions).To(Equal("0644")) Expect(ca.Content).To(Equal(string(caCertData))) - checkScript(c, "/var/lib/cloud/scripts/per-instance/bootstrap.ubuntu.sh", true) + checkScript(cc, "/var/lib/cloud/scripts/per-instance/bootstrap.ubuntu.sh", true) }) }) - Describe("UserData - Ubuntu1804 (custom pre-bootstrap)", func() { - cfg, ng := newClusterConfigAndNodegroup() - - var c *cloudconfig.CloudConfig + Context("UserData - Ubuntu1804 (custom pre-bootstrap)", func() { + cfg, ng := newClusterConfigAndNodegroup(true) cfg.VPC.CIDR, _ = ipnet.ParseCIDR("10.1.0.0/16") - cfg.NodeGroups[0].AMIFamily = "Ubuntu1804" - cfg.NodeGroups[0].InstanceType = "m5.large" + ng.AMIFamily = "Ubuntu1804" + ng.InstanceType = "m5.large" - cfg.NodeGroups[0].PreBootstrapCommands = []string{ + ng.PreBootstrapCommands = []string{ "while true ; do echo foo > /dev/null ; done", } - rs := NewNodeGroupResourceSet(p, cfg, "eksctl-test-123-cluster", ng) - err := rs.AddAllResources() - It("should add all resources without errors", func() { - Expect(err).ShouldNot(HaveOccurred()) - }) + build(cfg, "eksctl-test-123-cluster", ng) - template, err := rs.RenderJSON() - It("should serialise JSON without errors", func() { - Expect(err).ShouldNot(HaveOccurred()) - }) - obj := Template{} - It("should parse JSON without errors and extract valid cloud-config using our implementation", func() { - err = json.Unmarshal(template, &obj) - Expect(err).ShouldNot(HaveOccurred()) - Expect(len(obj.Resources)).ToNot(Equal(0)) + roundtript() + + It("should extract valid cloud-config using our implementation", func() { + Expect(obj.Resources).ToNot(BeEmpty()) userData := obj.Resources["NodeLaunchConfig"].Properties.UserData Expect(userData).ToNot(BeEmpty()) - c, err = cloudconfig.DecodeCloudConfig(userData) + cc, err = cloudconfig.DecodeCloudConfig(userData) Expect(err).ShouldNot(HaveOccurred()) }) @@ -1168,76 +1069,66 @@ var _ = Describe("CloudFormation template builder API", func() { }) It("should have packages, scripts and commands in cloud-config", func() { - Expect(c).ToNot(BeNil()) + Expect(cc).ToNot(BeNil()) - Expect(c.Packages).Should(BeEmpty()) + Expect(cc.Packages).Should(BeEmpty()) - kubeletEnv := getFile(c, "/etc/eksctl/kubelet.env") + kubeletEnv := getFile(cc, "/etc/eksctl/kubelet.env") Expect(kubeletEnv).ToNot(BeNil()) Expect(kubeletEnv.Permissions).To(Equal("0644")) Expect(strings.Split(kubeletEnv.Content, "\n")).To(Equal([]string{ + "NODE_LABELS=", "MAX_PODS=29", "CLUSTER_DNS=172.20.0.10", - "NODE_LABELS=", })) - kubeconfig := getFile(c, "/etc/eksctl/kubeconfig.yaml") + kubeconfig := getFile(cc, "/etc/eksctl/kubeconfig.yaml") Expect(kubeconfig).ToNot(BeNil()) Expect(kubeconfig.Permissions).To(Equal("0644")) - Expect(kubeconfig.Content).To(Equal(kubeconfigBody("heptio-authenticator-aws"))) + Expect(kubeconfig.Content).To(MatchYAML(kubeconfigBody("heptio-authenticator-aws"))) - ca := getFile(c, "/etc/eksctl/ca.crt") + ca := getFile(cc, "/etc/eksctl/ca.crt") Expect(ca).ToNot(BeNil()) Expect(ca.Permissions).To(Equal("0644")) Expect(ca.Content).To(Equal(string(caCertData))) - checkScript(c, "/var/lib/cloud/scripts/per-instance/bootstrap.ubuntu.sh", true) + checkScript(cc, "/var/lib/cloud/scripts/per-instance/bootstrap.ubuntu.sh", true) - for i, cmd := range cfg.NodeGroups[0].PreBootstrapCommands { - Expect(c.Commands[i].([]interface{})[0]).To(Equal("/bin/bash")) - Expect(c.Commands[i].([]interface{})[1]).To(Equal("-c")) - Expect(c.Commands[i].([]interface{})[2]).To(Equal(cmd)) + for i, cmd := range ng.PreBootstrapCommands { + c := cc.Commands[i].([]interface{}) + Expect(c[0]).To(Equal("/bin/bash")) + Expect(c[1]).To(Equal("-c")) + Expect(c[2]).To(Equal(cmd)) } }) }) - Describe("UserData - Ubuntu1804 (custom bootstrap)", func() { - cfg, ng := newClusterConfigAndNodegroup() - - var c *cloudconfig.CloudConfig + Context("UserData - Ubuntu1804 (custom bootstrap)", func() { + cfg, ng := newClusterConfigAndNodegroup(true) cfg.VPC.CIDR, _ = ipnet.ParseCIDR("10.1.0.0/16") - cfg.NodeGroups[0].AMIFamily = "Ubuntu1804" - cfg.NodeGroups[0].InstanceType = "m5.large" + ng.AMIFamily = "Ubuntu1804" + ng.InstanceType = "m5.large" - cfg.NodeGroups[0].Labels = map[string]string{ + ng.Labels = map[string]string{ "os": "ubuntu", } - cfg.NodeGroups[0].ClusterDNS = "169.254.20.10" + ng.ClusterDNS = "169.254.20.10" - cfg.NodeGroups[0].OverrideBootstrapCommand = &overrideBootstrapCommand + ng.OverrideBootstrapCommand = &overrideBootstrapCommand - rs := NewNodeGroupResourceSet(p, cfg, "eksctl-test-123-cluster", ng) - err := rs.AddAllResources() - It("should add all resources without errors", func() { - Expect(err).ShouldNot(HaveOccurred()) - }) + build(cfg, "eksctl-test-123-cluster", ng) - template, err := rs.RenderJSON() - It("should serialise JSON without errors", func() { - Expect(err).ShouldNot(HaveOccurred()) - }) - obj := Template{} - It("should parse JSON without errors and extract valid cloud-config using our implementation", func() { - err = json.Unmarshal(template, &obj) - Expect(err).ShouldNot(HaveOccurred()) - Expect(len(obj.Resources)).ToNot(Equal(0)) + roundtript() + + It("should extract valid cloud-config using our implementation", func() { + Expect(obj.Resources).ToNot(BeEmpty()) userData := obj.Resources["NodeLaunchConfig"].Properties.UserData Expect(userData).ToNot(BeEmpty()) - c, err = cloudconfig.DecodeCloudConfig(userData) + cc, err = cloudconfig.DecodeCloudConfig(userData) Expect(err).ShouldNot(HaveOccurred()) }) @@ -1248,78 +1139,67 @@ var _ = Describe("CloudFormation template builder API", func() { }) It("should have packages, scripts and commands in cloud-config", func() { - Expect(c).ToNot(BeNil()) + Expect(cc).ToNot(BeNil()) - Expect(c.Packages).Should(BeEmpty()) + Expect(cc.Packages).Should(BeEmpty()) - kubeletEnv := getFile(c, "/etc/eksctl/kubelet.env") + kubeletEnv := getFile(cc, "/etc/eksctl/kubelet.env") Expect(kubeletEnv).ToNot(BeNil()) Expect(kubeletEnv.Permissions).To(Equal("0644")) Expect(strings.Split(kubeletEnv.Content, "\n")).To(Equal([]string{ + "NODE_LABELS=os=ubuntu", "MAX_PODS=29", "CLUSTER_DNS=169.254.20.10", - "NODE_LABELS=os=ubuntu", })) - kubeconfig := getFile(c, "/etc/eksctl/kubeconfig.yaml") + kubeconfig := getFile(cc, "/etc/eksctl/kubeconfig.yaml") Expect(kubeconfig).ToNot(BeNil()) Expect(kubeconfig.Permissions).To(Equal("0644")) - Expect(kubeconfig.Content).To(Equal(kubeconfigBody("heptio-authenticator-aws"))) + Expect(kubeconfig.Content).To(MatchYAML(kubeconfigBody("heptio-authenticator-aws"))) - ca := getFile(c, "/etc/eksctl/ca.crt") + ca := getFile(cc, "/etc/eksctl/ca.crt") Expect(ca).ToNot(BeNil()) Expect(ca.Permissions).To(Equal("0644")) Expect(ca.Content).To(Equal(string(caCertData))) - script := getFile(c, "/var/lib/cloud/scripts/per-instance/bootstrap.ubuntu.sh") + script := getFile(cc, "/var/lib/cloud/scripts/per-instance/bootstrap.ubuntu.sh") Expect(script).To(BeNil()) - Expect(c.Commands).To(HaveLen(1)) - Expect(c.Commands[0]).To(HaveLen(3)) - Expect(c.Commands[0].([]interface{})[0]).To(Equal("/bin/bash")) - Expect(c.Commands[0].([]interface{})[1]).To(Equal("-c")) - Expect(c.Commands[0].([]interface{})[2]).To(Equal(overrideBootstrapCommand)) + Expect(cc.Commands).To(HaveLen(1)) + Expect(cc.Commands[0]).To(HaveLen(3)) + Expect(cc.Commands[0].([]interface{})[0]).To(Equal("/bin/bash")) + Expect(cc.Commands[0].([]interface{})[1]).To(Equal("-c")) + Expect(cc.Commands[0].([]interface{})[2]).To(Equal(overrideBootstrapCommand)) }) }) - Describe("UserData - Ubuntu1804 (custom bootstrap and pre-bootstrap)", func() { - cfg, ng := newClusterConfigAndNodegroup() - - var c *cloudconfig.CloudConfig + Context("UserData - Ubuntu1804 (custom bootstrap and pre-bootstrap)", func() { + cfg, ng := newClusterConfigAndNodegroup(true) cfg.VPC.CIDR, _ = ipnet.ParseCIDR("10.1.0.0/16") - cfg.NodeGroups[0].AMIFamily = "Ubuntu1804" - cfg.NodeGroups[0].InstanceType = "m5.large" + ng.AMIFamily = "Ubuntu1804" + ng.InstanceType = "m5.large" - cfg.NodeGroups[0].Labels = map[string]string{ + ng.Labels = map[string]string{ "os": "ubuntu", } - cfg.NodeGroups[0].ClusterDNS = "169.254.20.10" + ng.ClusterDNS = "169.254.20.10" - cfg.NodeGroups[0].PreBootstrapCommands = []string{"echo 1 > /tmp/1", "echo 2 > /tmp/2", "echo 3 > /tmp/3"} - cfg.NodeGroups[0].OverrideBootstrapCommand = &overrideBootstrapCommand + ng.PreBootstrapCommands = []string{"echo 1 > /tmp/1", "echo 2 > /tmp/2", "echo 3 > /tmp/3"} + ng.OverrideBootstrapCommand = &overrideBootstrapCommand - rs := NewNodeGroupResourceSet(p, cfg, "eksctl-test-123-cluster", ng) - err := rs.AddAllResources() - It("should add all resources without errors", func() { - Expect(err).ShouldNot(HaveOccurred()) - }) + build(cfg, "eksctl-test-123-cluster", ng) - template, err := rs.RenderJSON() - It("should serialise JSON without errors", func() { - Expect(err).ShouldNot(HaveOccurred()) - }) - obj := Template{} - It("should parse JSON without errors and extract valid cloud-config using our implementation", func() { - err = json.Unmarshal(template, &obj) - Expect(err).ShouldNot(HaveOccurred()) - Expect(len(obj.Resources)).ToNot(Equal(0)) + roundtript() + + It("should extract valid cloud-config using our implementation", func() { + Expect(obj.Resources).ToNot(BeEmpty()) userData := obj.Resources["NodeLaunchConfig"].Properties.UserData Expect(userData).ToNot(BeEmpty()) - c, err = cloudconfig.DecodeCloudConfig(userData) + cc, err = cloudconfig.DecodeCloudConfig(userData) Expect(err).ShouldNot(HaveOccurred()) }) @@ -1330,44 +1210,46 @@ var _ = Describe("CloudFormation template builder API", func() { }) It("should have packages, scripts and commands in cloud-config", func() { - Expect(c).ToNot(BeNil()) + Expect(cc).ToNot(BeNil()) - Expect(c.Packages).Should(BeEmpty()) + Expect(cc.Packages).Should(BeEmpty()) - kubeletEnv := getFile(c, "/etc/eksctl/kubelet.env") + kubeletEnv := getFile(cc, "/etc/eksctl/kubelet.env") Expect(kubeletEnv).ToNot(BeNil()) Expect(kubeletEnv.Permissions).To(Equal("0644")) Expect(strings.Split(kubeletEnv.Content, "\n")).To(Equal([]string{ + "NODE_LABELS=os=ubuntu", "MAX_PODS=29", "CLUSTER_DNS=169.254.20.10", - "NODE_LABELS=os=ubuntu", })) - kubeconfig := getFile(c, "/etc/eksctl/kubeconfig.yaml") + kubeconfig := getFile(cc, "/etc/eksctl/kubeconfig.yaml") Expect(kubeconfig).ToNot(BeNil()) Expect(kubeconfig.Permissions).To(Equal("0644")) - Expect(kubeconfig.Content).To(Equal(kubeconfigBody("heptio-authenticator-aws"))) + Expect(kubeconfig.Content).To(MatchYAML(kubeconfigBody("heptio-authenticator-aws"))) - ca := getFile(c, "/etc/eksctl/ca.crt") + ca := getFile(cc, "/etc/eksctl/ca.crt") Expect(ca).ToNot(BeNil()) Expect(ca.Permissions).To(Equal("0644")) Expect(ca.Content).To(Equal(string(caCertData))) - script := getFile(c, "/var/lib/cloud/scripts/per-instance/bootstrap.ubuntu.sh") + script := getFile(cc, "/var/lib/cloud/scripts/per-instance/bootstrap.ubuntu.sh") Expect(script).To(BeNil()) - Expect(c.Commands).To(HaveLen(4)) - Expect(c.Commands[0]).To(HaveLen(3)) + Expect(cc.Commands).To(HaveLen(4)) + Expect(cc.Commands[0]).To(HaveLen(3)) - for i, cmd := range cfg.NodeGroups[0].PreBootstrapCommands { - Expect(c.Commands[i].([]interface{})[0]).To(Equal("/bin/bash")) - Expect(c.Commands[i].([]interface{})[1]).To(Equal("-c")) - Expect(c.Commands[i].([]interface{})[2]).To(Equal(cmd)) + for i, cmd := range ng.PreBootstrapCommands { + c := cc.Commands[i].([]interface{}) + Expect(c[0]).To(Equal("/bin/bash")) + Expect(c[1]).To(Equal("-c")) + Expect(c[2]).To(Equal(cmd)) } - Expect(c.Commands[3].([]interface{})[0]).To(Equal("/bin/bash")) - Expect(c.Commands[3].([]interface{})[1]).To(Equal("-c")) - Expect(c.Commands[3].([]interface{})[2]).To(Equal(overrideBootstrapCommand)) + c3 := cc.Commands[3].([]interface{}) + Expect(c3[0]).To(Equal("/bin/bash")) + Expect(c3[1]).To(Equal("-c")) + Expect(c3[2]).To(Equal(overrideBootstrapCommand)) }) }) }) diff --git a/pkg/nodebootstrap/assets.go b/pkg/nodebootstrap/assets.go index 3205a70ca8e..bec8657424c 100644 --- a/pkg/nodebootstrap/assets.go +++ b/pkg/nodebootstrap/assets.go @@ -3,7 +3,7 @@ // assets/10-eksclt.al2.conf // assets/bootstrap.al2.sh // assets/bootstrap.ubuntu.sh -// assets/kubelet-config.json +// assets/kubelet.yaml // DO NOT EDIT! package nodebootstrap @@ -71,7 +71,7 @@ func (fi bindataFileInfo) Sys() interface{} { return nil } -var __10EkscltAl2Conf = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x8c\x92\x41\x6f\xda\x40\x10\x85\xef\xfe\x15\x2b\x85\x43\x2b\xb1\x76\x42\x68\x0e\x91\x7c\xa0\xc1\x89\x90\x28\x89\xe2\x44\xad\xd4\x56\x68\xd8\x1d\xe8\x94\xf5\xac\xb5\xbb\x86\xa4\x88\xff\x5e\x19\xdb\x29\x55\xa2\xaa\x37\xd8\x6f\xfc\xde\xcc\x9b\x39\x11\xb8\xf6\x2a\x18\xe9\x4b\x54\xb4\x24\x25\xfc\xb3\x0f\x58\x68\xa1\x9d\x2d\x25\xb1\xa8\x98\x82\x58\x5a\x27\xd6\xd5\x02\x0d\x86\xfe\xe1\xcf\xa8\x80\x5f\x96\xc5\x94\xb8\x7a\x12\x03\xf1\x6e\x34\x1d\xbc\x8f\xa2\xaf\x39\xba\x0d\x29\xfc\x1e\x9d\x88\xa9\x55\x60\x44\x81\x01\x34\x04\x10\x25\x38\x28\x30\xa0\xf3\x97\xe2\x3e\xbb\x99\xdc\xce\xfa\x62\xf4\x39\x9f\x8f\xb3\xeb\xd1\xe3\xf4\x61\xde\xbc\x45\x19\x6f\xc8\x59\x2e\x90\xc3\x35\x19\x4c\x13\x0c\x2a\x69\x5a\x4c\x3a\xad\x18\x79\x13\x9d\x88\x1b\x63\x17\x60\x04\xb0\x16\x3e\x40\x20\xf5\x97\xc7\xa7\xd1\x97\xf9\xdd\xed\x38\xef\x8b\xab\xe9\x63\xfe\x90\xdd\xcf\xc7\xb3\xbc\x2f\x66\xb7\xe3\x6c\x3e\x1d\x7d\xcc\xa6\xf9\x3f\xbd\xda\x61\x5b\xab\x66\x16\xb6\x2c\xdf\x70\x3a\x48\x4e\xee\xfa\x62\x32\xcb\x1f\x46\xb3\xab\x6c\x3e\x19\xff\x97\xb6\xa9\x55\x0f\x0e\x51\xf6\x84\x2a\x0f\xe0\x42\x7a\xf4\x33\xa9\xbc\x4b\x16\xc4\xdd\x07\xe2\x5b\x24\x84\x94\x6c\x35\x4a\x2a\xd3\xde\xae\x75\xde\xb7\x40\x99\xca\x07\x74\x52\xb3\x4f\x7b\xbb\xa3\xb1\xbb\x82\x02\x9e\x64\x69\x75\x4d\xbb\x78\xf6\xc7\xa2\x06\x16\x68\x7c\x27\xdc\xa4\xb4\xef\x83\x29\x7f\x40\xdc\xf4\x1e\x93\x4d\x88\x7d\x00\x56\x28\x49\xa7\xbd\xdd\xd1\xd0\x9d\x16\x18\x63\xb7\xb2\x74\xb4\x21\x83\x2b\xd4\x69\x70\x15\xb6\xac\xb4\x5a\x12\x2f\x1d\x48\x65\x39\x00\x31\x3a\x49\x05\xac\x30\xbd\x38\x1d\x0c\x4f\xcf\xce\x86\xe7\xc3\x0f\x83\x58\xaf\x5d\x8c\xca\xc5\xbd\xdd\xeb\x1b\xd9\xc7\x70\x38\x3e\xd8\xfa\x58\xd9\xa2\x4e\x35\x29\xa1\xf2\x28\xa1\xd0\x17\xc3\xcb\xf3\xf8\xec\x25\x10\x5b\x69\x59\x3a\xbb\x21\x8d\x2e\x85\xad\xef\x00\x93\x5c\x10\x4b\x4d\x2e\x4d\x6c\x19\x12\xc5\x54\x27\x7d\x84\x95\xe5\x65\xc3\xeb\xcd\xd5\x9c\x31\xc4\xba\xab\x78\x69\xde\x55\x1c\xa8\xc0\x54\x5b\xb5\x46\xd7\xa5\x89\x61\x6b\xdd\x5a\x96\xa6\x5a\x11\xa7\x8a\xa9\x05\x0e\x57\x74\xd8\x51\x9d\xf7\x71\x2e\xf5\x8a\x6b\x4b\x5a\xbd\x3a\x95\xe6\x39\x7e\x86\xc2\xfc\x71\x7f\xab\xd0\x60\x68\x51\xfc\xd3\x5b\x8e\x7e\x07\x00\x00\xff\xff\x63\xce\x0d\x56\xdc\x03\x00\x00") +var __10EkscltAl2Conf = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x8c\x92\x41\x6b\xdb\x4e\x10\xc5\xef\xfa\x14\x0b\xc9\xe1\xff\x07\xaf\x94\x38\x6e\x0e\x01\x1d\xd4\x58\x09\x06\xd5\x09\x51\x42\x0b\x6d\x31\xe3\xdd\xb1\x3b\x78\x35\x2b\x76\x57\x76\xd2\xe0\xef\x5e\x64\x49\xd4\x25\xa1\xf4\x26\xed\x9b\x7d\xbf\x37\x3b\x73\x22\x70\xe3\x55\x30\xd2\xd7\xa8\x68\x45\x4a\xf8\x17\x1f\xb0\xd2\x42\x3b\x5b\x4b\x62\xd1\x30\x05\xb1\xb2\x4e\x6c\x9a\x25\x1a\x0c\xa3\xc3\x4f\x56\xc1\x4f\xcb\xa2\x20\x6e\x9e\xc5\x58\xfc\x97\x15\xe3\xff\xa3\xe8\x6b\x89\x6e\x4b\x0a\xbf\x47\x27\xa2\xb0\x0a\x8c\xa8\x30\x80\x86\x00\xa2\x06\x07\x15\x06\x74\xfe\x4a\x3c\xe4\xb7\xb3\xbb\xf9\x48\x64\x9f\xcb\xc5\x34\xbf\xc9\x9e\x8a\xc7\x45\x77\x16\xe5\xbc\x25\x67\xb9\x42\x0e\x37\x64\x30\x4d\x30\xa8\xa4\x8b\x98\x0c\x5e\x31\xf2\x36\x3a\x11\xb7\xc6\x2e\xc1\x08\x60\x2d\x7c\x80\x40\xea\x0f\xc6\xa7\xec\xcb\xe2\xfe\x6e\x5a\x8e\xc4\x75\xf1\x54\x3e\xe6\x0f\x8b\xe9\xbc\x1c\x89\xf9\xdd\x34\x5f\x14\xd9\xc7\xbc\x28\xff\xca\xea\x9b\xed\x51\x5d\x2f\x6c\x59\xbe\x43\x3a\x58\xce\xee\x47\x62\x36\x2f\x1f\xb3\xf9\x75\xbe\x98\x4d\xff\xc9\xdb\xb4\xae\x07\x42\x94\x3f\xa3\x2a\x03\xb8\x90\x1e\x7d\x26\x8d\x77\xc9\x92\x78\xb8\x20\xbe\x45\x42\x48\xc9\x56\xa3\xa4\x3a\x3d\x7d\xed\xc9\xfb\x63\xc1\xc0\x12\x8d\x1f\xc4\xae\xd3\xfd\x08\x4c\xfd\x03\xe2\x8e\x1f\x93\x4d\x88\x7d\x00\x56\x28\x49\xa7\xa7\xaf\x47\xc1\x07\x2f\x30\xc6\xee\x64\xed\x68\x4b\x06\xd7\xa8\xd3\xe0\x1a\xec\x35\x65\x6c\xa3\x65\xed\xec\x96\x34\xba\x14\x76\x7e\x10\x2c\x07\x20\x46\x27\x5d\xc3\x81\x2a\x4c\xb5\x55\x1b\x74\x43\x3e\x0c\x3b\xeb\x36\xb2\x36\xcd\x9a\x38\x55\x4c\xc3\x3d\x26\xb9\x24\x96\x9a\x5c\x9a\xd8\x3a\x24\x8a\xa9\x6d\xfc\x48\x56\x96\x57\x9d\xde\x3e\x64\xab\x33\x86\x58\xf7\x15\xb5\xd5\x92\x78\xe5\xe0\x28\x02\x55\xb0\xc6\xf4\xf2\x6c\x3c\x39\x3b\x3f\x9f\x5c\x4c\x3e\x8c\x63\xbd\x71\x31\x2a\x17\x9f\xbe\xbe\xdd\xbc\x7d\x0c\x87\x95\x86\x9d\x8f\x95\xad\xda\x59\x25\x35\x34\x1e\x25\x54\xfa\x72\x72\x75\x11\x9f\xf7\xb0\x76\x1a\x6d\x1c\x5a\xbf\x99\x6a\x77\x1c\xbf\x40\x65\x7e\x3f\xc9\x7b\x85\xed\xf8\xdb\xaa\xe8\x57\x00\x00\x00\xff\xff\x2a\xa6\x3e\x1f\x80\x03\x00\x00") func _10EkscltAl2ConfBytes() ([]byte, error) { return bindataRead( @@ -86,7 +86,7 @@ func _10EkscltAl2Conf() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "10-eksclt.al2.conf", size: 988, mode: os.FileMode(420), modTime: time.Unix(1, 0)} + info := bindataFileInfo{name: "10-eksclt.al2.conf", size: 896, mode: os.FileMode(420), modTime: time.Unix(1, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -131,22 +131,22 @@ func bootstrapUbuntuSh() (*asset, error) { return a, nil } -var _kubeletConfigJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x84\x92\x4d\x6f\xf2\x30\x10\x84\xef\xfc\x8a\xc8\x67\x94\x84\xf7\x15\x52\xcb\x8d\x82\xda\x43\x39\x15\xda\x9e\x1d\x67\x03\x56\x1c\x2f\x5a\xaf\xe9\x97\xf8\xef\x95\x3f\x5a\x0a\x3d\x54\x39\x79\xf4\xec\x78\x36\xe3\x8f\x51\x51\x88\x5e\xdb\x56\xcc\x0a\x71\xef\x1b\x30\xc0\x0b\xb4\x9d\xde\x7a\x92\xac\xd1\x8a\x71\x20\xe4\x5e\x3f\x01\xb9\x70\x9e\x15\xa2\x4f\x5c\xa9\x22\x58\xf6\x57\xae\xd4\x58\x1d\x26\x0d\xb0\x9c\xe4\x81\xb6\x25\x70\x2e\xd0\x75\x19\xbf\xac\x7b\xde\x81\x65\xad\x92\xf9\xac\x08\x01\x82\x6e\xd1\xbe\x0d\xe8\xdd\xb7\x54\x14\x02\xac\x6c\x0c\x84\x68\x9d\x34\x0e\xa2\x7c\x1c\xa7\x81\x17\x68\x76\x88\xfd\x4f\x5c\x49\xb5\x83\xcd\x66\x15\x2e\xfd\x37\xd4\x4e\x8c\x7f\x1b\x31\xf9\x73\x9f\xd7\x69\x7d\x7d\x66\x62\x34\x58\x5e\xcc\x6f\xb5\x81\x60\x54\x01\xab\x0a\x7a\xa7\xd8\x54\x4a\x96\x8a\x58\xa4\xf9\x51\xf6\x88\x2b\x21\xe9\xf7\x8b\x8d\x06\x6c\xa3\xc1\x73\x0e\xfa\x47\xee\x79\x76\x81\x36\x6f\x30\x3d\xdb\x20\x32\x8f\x56\x5e\x52\xff\x6b\x77\x99\x47\x19\xef\x18\x68\x89\x83\xd4\xb1\xae\x2c\x94\x06\x95\x34\xa9\x06\xb5\x25\xf4\xfb\x25\xe9\x03\x50\x44\xe2\xb9\x4b\x17\x8a\x0e\x24\x7b\x82\x3b\xc9\x70\xea\x43\x3c\x20\x4b\x86\xfc\x46\xd6\x40\x07\xa0\x05\x10\xeb\x2e\x94\x09\xa7\x7f\x9b\x52\xb8\x08\x6c\x56\xeb\x1b\x44\x76\x4c\x72\xff\x45\x1c\x3f\x03\x00\x00\xff\xff\xbb\x62\xda\x19\x74\x02\x00\x00") +var _kubeletYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x6c\x91\x4f\x4f\xc3\x30\x0c\xc5\xef\xf9\x14\xfe\x04\x6d\x07\x9a\x04\xb9\x8d\x4d\x70\x60\x27\x36\xe0\xec\xa6\xee\x16\x35\x8d\x27\xc7\x19\x7f\x3e\x3d\x5a\x5a\x90\x26\xa1\x9c\x9e\xde\xb3\xdf\x4f\xce\xe0\x63\x67\xe1\x39\xb7\x14\x48\xd7\x1c\x7b\x7f\xc8\x82\xea\x39\x1a\x3c\xf9\x37\x92\xe4\x39\x5a\x18\xa6\x40\xe5\x4a\xa2\x1a\xee\x52\xe5\xb9\x3e\x2f\x5a\x52\x5c\x18\x83\x5d\x27\x94\x92\x85\xa6\x2a\xcf\xb8\x90\x93\x92\x6c\x78\x44\x1f\x2d\xcc\xb2\x0a\xec\x30\x18\x83\x59\x8f\x14\xd5\xbb\x52\x64\x0d\x00\x46\x8e\x5f\x23\xe7\x74\x11\x00\x14\xb1\x0d\xd4\x59\xe8\x31\x24\x32\x00\x1f\xd4\x1e\x99\x87\xc9\x75\xe8\x8e\xb4\xdf\x6f\x2d\xdc\x8c\x4d\xba\x1e\x50\xc9\x97\xfc\xe7\xb2\xb9\x9f\xc3\xc1\x53\xd4\xf5\xea\xd1\x07\xb2\x50\x93\xba\x9a\x86\xe4\x34\xd4\x0e\x2b\x27\x3a\xd1\xb0\xf8\xef\x3f\x98\x91\x3b\xb2\xf0\x3e\x55\xfe\x5b\xbe\x9a\x47\xa8\x2b\x18\xcb\x5f\x8c\x62\xbe\x46\xbc\xb6\x6f\x9b\x64\x4c\x22\x39\x93\xec\xb7\xbb\x07\x66\x4d\x2a\x78\x9a\x61\x8d\x3b\x08\xe7\xd3\x46\xfc\x99\xc4\xc2\xa4\xfa\x64\x4c\x4f\xa8\x59\xe8\x09\x95\xca\x59\x5e\x58\x51\x69\xfe\xaa\x5d\x59\xb7\x26\x51\xdf\x5f\xee\x48\xf3\xb6\x9f\x00\x00\x00\xff\xff\x1f\x2f\xa9\x0f\xd0\x01\x00\x00") -func kubeletConfigJsonBytes() ([]byte, error) { +func kubeletYamlBytes() ([]byte, error) { return bindataRead( - _kubeletConfigJson, - "kubelet-config.json", + _kubeletYaml, + "kubelet.yaml", ) } -func kubeletConfigJson() (*asset, error) { - bytes, err := kubeletConfigJsonBytes() +func kubeletYaml() (*asset, error) { + bytes, err := kubeletYamlBytes() if err != nil { return nil, err } - info := bindataFileInfo{name: "kubelet-config.json", size: 628, mode: os.FileMode(420), modTime: time.Unix(1, 0)} + info := bindataFileInfo{name: "kubelet.yaml", size: 464, mode: os.FileMode(420), modTime: time.Unix(1, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -206,7 +206,7 @@ var _bindata = map[string]func() (*asset, error){ "10-eksclt.al2.conf": _10EkscltAl2Conf, "bootstrap.al2.sh": bootstrapAl2Sh, "bootstrap.ubuntu.sh": bootstrapUbuntuSh, - "kubelet-config.json": kubeletConfigJson, + "kubelet.yaml": kubeletYaml, } // AssetDir returns the file names below a certain @@ -252,7 +252,7 @@ var _bintree = &bintree{nil, map[string]*bintree{ "10-eksclt.al2.conf": &bintree{_10EkscltAl2Conf, map[string]*bintree{}}, "bootstrap.al2.sh": &bintree{bootstrapAl2Sh, map[string]*bintree{}}, "bootstrap.ubuntu.sh": &bintree{bootstrapUbuntuSh, map[string]*bintree{}}, - "kubelet-config.json": &bintree{kubeletConfigJson, map[string]*bintree{}}, + "kubelet.yaml": &bintree{kubeletYaml, map[string]*bintree{}}, }} // RestoreAsset restores an asset under the given directory diff --git a/pkg/nodebootstrap/assets/10-eksclt.al2.conf b/pkg/nodebootstrap/assets/10-eksclt.al2.conf index 992f380064f..e44b141abe2 100644 --- a/pkg/nodebootstrap/assets/10-eksclt.al2.conf +++ b/pkg/nodebootstrap/assets/10-eksclt.al2.conf @@ -11,16 +11,13 @@ EnvironmentFile=/etc/eksctl/kubelet.local.env ExecStart= ExecStart=/usr/bin/kubelet \ --node-ip=${NODE_IP} \ - --cluster-dns=${CLUSTER_DNS} \ - --max-pods=${MAX_PODS} \ --node-labels=${NODE_LABELS},alpha.eksctl.io/instance-id=${INSTANCE_ID} \ --allow-privileged=true \ - --pod-infra-container-image=602401143452.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/eks/pause-amd64:3.1 \ --cloud-provider=aws \ - --cni-bin-dir=/opt/cni/bin \ - --cni-conf-dir=/etc/cni/net.d \ --container-runtime=docker \ --network-plugin=cni \ - --register-node=true \ + --cni-bin-dir=/opt/cni/bin \ + --cni-conf-dir=/etc/cni/net.d \ + --pod-infra-container-image=602401143452.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/eks/pause-amd64:3.1 \ --kubeconfig=/etc/eksctl/kubeconfig.yaml \ - --config=/etc/eksctl/kubelet-config.json + --config=/etc/eksctl/kubelet.yaml diff --git a/pkg/nodebootstrap/assets/kubelet-config.json b/pkg/nodebootstrap/assets/kubelet-config.json deleted file mode 100644 index d8f7b626022..00000000000 --- a/pkg/nodebootstrap/assets/kubelet-config.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "kind": "KubeletConfiguration", - "apiVersion": "kubelet.config.k8s.io/v1beta1", - "address": "0.0.0.0", - "authentication": { - "anonymous": { - "enabled": false - }, - "webhook": { - "cacheTTL": "2m0s", - "enabled": true - }, - "x509": { - "clientCAFile": "/etc/eksctl/ca.crt" - } - }, - "authorization": { - "mode": "Webhook", - "webhook": { - "cacheAuthorizedTTL": "5m0s", - "cacheUnauthorizedTTL": "30s" - } - }, - "clusterDomain": "cluster.local", - "cgroupDriver": "cgroupfs", - "featureGates": { - "RotateKubeletServerCertificate": true - }, - "serverTLSBootstrap": true -} \ No newline at end of file diff --git a/pkg/nodebootstrap/assets/kubelet.yaml b/pkg/nodebootstrap/assets/kubelet.yaml new file mode 100644 index 00000000000..f062a5aba77 --- /dev/null +++ b/pkg/nodebootstrap/assets/kubelet.yaml @@ -0,0 +1,27 @@ +kind: KubeletConfiguration +apiVersion: kubelet.config.k8s.io/v1beta1 + +address: 0.0.0.0 +clusterDomain: cluster.local + +authentication: + anonymous: + enabled: false + webhook: + cacheTTL: 2m0s + enabled: true + x509: + clientCAFile: /etc/eksctl/ca.crt + +authorization: + mode: Webhook + webhook: + cacheAuthorizedTTL: 5m0s + cacheUnauthorizedTTL: 30s + +serverTLSBootstrap: true + +cgroupDriver: cgroupfs + +featureGates: + RotateKubeletServerCertificate: true diff --git a/pkg/nodebootstrap/userdata.go b/pkg/nodebootstrap/userdata.go index 21648fd28c4..29e2453dd03 100644 --- a/pkg/nodebootstrap/userdata.go +++ b/pkg/nodebootstrap/userdata.go @@ -6,7 +6,11 @@ import ( "strings" "github.com/pkg/errors" + "k8s.io/client-go/tools/clientcmd" + kubeletapi "k8s.io/kubelet/config/v1beta1" + + "sigs.k8s.io/yaml" "github.com/weaveworks/eksctl/pkg/ami" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha4" @@ -96,20 +100,48 @@ func clusterDNS(spec *api.ClusterConfig, ng *api.NodeGroup) string { return "10.100.0.10" } -func makeKubeletParamsCommon(spec *api.ClusterConfig, ng *api.NodeGroup) []string { +func makeKubeletConfigYAML(spec *api.ClusterConfig, ng *api.NodeGroup) ([]byte, error) { + data, err := Asset("kubelet.yaml") + if err != nil { + return nil, err + } + + // use a map here, as using struct will require us to add defaulting etc, + // and we only need to add a few top-level fields + obj := map[string]interface{}{} + if err := yaml.Unmarshal(data, &obj); err != nil { + return nil, err + } + if ng.MaxPodsPerNode == 0 { ng.MaxPodsPerNode = maxPodsPerNodeType[ng.InstanceType] } + obj["maxPods"] = int32(ng.MaxPodsPerNode) + + obj["clusterDNS"] = []string{ + clusterDNS(spec, ng), + } + + data, err = yaml.Marshal(obj) + if err != nil { + return nil, err + } + + // validate if data can be decoded as KubeletConfiguration + if err := yaml.Unmarshal(data, &kubeletapi.KubeletConfiguration{}); err != nil { + return nil, errors.Wrap(err, "validating generated KubeletConfiguration object") + } + + return data, nil +} +func makeCommonKubeletEnvParams(spec *api.ClusterConfig, ng *api.NodeGroup) []string { labels := []string{} for k, v := range ng.Labels { labels = append(labels, fmt.Sprintf("%s=%s", k, v)) } - // TODO: use componentconfig or kubelet config file – https://github.com/weaveworks/eksctl/issues/156 return []string{ - fmt.Sprintf("MAX_PODS=%d", ng.MaxPodsPerNode), - fmt.Sprintf("CLUSTER_DNS=%s", clusterDNS(spec, ng)), fmt.Sprintf("NODE_LABELS=%s", strings.Join(labels, ",")), } } diff --git a/pkg/nodebootstrap/userdata_al2.go b/pkg/nodebootstrap/userdata_al2.go index c5348a0da4d..6d3a96873dd 100644 --- a/pkg/nodebootstrap/userdata_al2.go +++ b/pkg/nodebootstrap/userdata_al2.go @@ -19,17 +19,22 @@ func makeAmazonLinux2Config(spec *api.ClusterConfig, ng *api.NodeGroup) (configF return nil, errors.New("invalid cluster config: missing CertificateAuthorityData") } + kubeletConfigData, err := makeKubeletConfigYAML(spec, ng) + if err != nil { + return nil, err + } + files := configFiles{ kubeletDropInUnitDir: { "10-eksclt.al2.conf": {isAsset: true}, }, configDir: { "metadata.env": {content: strings.Join(makeMetadata(spec), "\n")}, - "kubelet.env": {content: strings.Join(makeKubeletParamsCommon(spec, ng), "\n")}, + "kubelet.env": {content: strings.Join(makeCommonKubeletEnvParams(spec, ng), "\n")}, + "kubelet.yaml": {content: string(kubeletConfigData)}, // TODO: https://github.com/weaveworks/eksctl/issues/161 - "kubelet-config.json": {isAsset: true}, - "ca.crt": {content: string(spec.Status.CertificateAuthorityData)}, - "kubeconfig.yaml": {content: string(clientConfigData)}, + "ca.crt": {content: string(spec.Status.CertificateAuthorityData)}, + "kubeconfig.yaml": {content: string(clientConfigData)}, }, } diff --git a/pkg/nodebootstrap/userdata_ubuntu.go b/pkg/nodebootstrap/userdata_ubuntu.go index 861b7d86dd1..bce567bc1fb 100644 --- a/pkg/nodebootstrap/userdata_ubuntu.go +++ b/pkg/nodebootstrap/userdata_ubuntu.go @@ -1,6 +1,7 @@ package nodebootstrap import ( + "fmt" "strings" "github.com/kris-nova/logger" @@ -19,10 +20,19 @@ func makeUbuntu1804Config(spec *api.ClusterConfig, ng *api.NodeGroup) (configFil return nil, errors.New("invalid cluster config: missing CertificateAuthorityData") } + if ng.MaxPodsPerNode == 0 { + ng.MaxPodsPerNode = maxPodsPerNodeType[ng.InstanceType] + } + + kubeletEnvParams := append(makeCommonKubeletEnvParams(spec, ng), + fmt.Sprintf("MAX_PODS=%d", ng.MaxPodsPerNode), + fmt.Sprintf("CLUSTER_DNS=%s", clusterDNS(spec, ng)), + ) + files := configFiles{ configDir: { "metadata.env": {content: strings.Join(makeMetadata(spec), "\n")}, - "kubelet.env": {content: strings.Join(makeKubeletParamsCommon(spec, ng), "\n")}, + "kubelet.env": {content: strings.Join(kubeletEnvParams, "\n")}, // TODO: https://github.com/weaveworks/eksctl/issues/161 "ca.crt": {content: string(spec.Status.CertificateAuthorityData)}, "kubeconfig.yaml": {content: string(clientConfigData)},