From a70598a7efa2272931b1a07b69349b5821d38e0b Mon Sep 17 00:00:00 2001 From: Christopher Hein Date: Thu, 21 Mar 2019 08:59:33 +0000 Subject: [PATCH 1/4] adding policies to automatically allow the EBS CSI driver to be deployed Signed-off-by: Christopher Hein --- pkg/apis/eksctl.io/v1alpha4/types.go | 2 ++ pkg/cfn/builder/iam.go | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/pkg/apis/eksctl.io/v1alpha4/types.go b/pkg/apis/eksctl.io/v1alpha4/types.go index 790253930b..8598dd697e 100644 --- a/pkg/apis/eksctl.io/v1alpha4/types.go +++ b/pkg/apis/eksctl.io/v1alpha4/types.go @@ -420,5 +420,7 @@ type ( ExternalDNS *bool `json:"externalDNS"` // +optional AppMesh *bool `json:"appMesh"` + // +optional + EBSCSI *bool `json:"ebsCSI"` } ) diff --git a/pkg/cfn/builder/iam.go b/pkg/cfn/builder/iam.go index 01aa2d013a..cf20ab4ae1 100644 --- a/pkg/cfn/builder/iam.go +++ b/pkg/cfn/builder/iam.go @@ -217,6 +217,25 @@ func (n *NodeGroupResourceSet) addResourcesForIAM() { ) } + if v := n.spec.IAM.WithAddonPolicies.EBSCSI; v != nil && *v { + n.rs.attachAllowPolicy("PolicyEBSCSI", refIR, "*", + []string{ + "ec2:AttachVolume", + "ec2:CreateSnapshot", + "ec2:CreateTags", + "ec2:CreateVolume", + "ec2:DeleteSnapshot", + "ec2:DeleteTags", + "ec2:DeleteVolume", + "ec2:DescribeInstances", + "ec2:DescribeSnapshots", + "ec2:DescribeTags", + "ec2:DescribeVolumes", + "ec2:DetachVolume", + }, + ) + } + n.rs.defineOutputFromAtt(outputs.NodeGroupInstanceProfileARN, "NodeInstanceProfile.Arn", true, func(v string) error { n.spec.IAM.InstanceProfileARN = v return nil From 3420bfe53c440ae2ac646ef381adf5f521c6a7fb Mon Sep 17 00:00:00 2001 From: Christopher Hein Date: Fri, 22 Mar 2019 00:26:45 +0000 Subject: [PATCH 2/4] Adding unit tests for EBS CSI Signed-off-by: Christopher Hein --- pkg/cfn/builder/api_test.go | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/pkg/cfn/builder/api_test.go b/pkg/cfn/builder/api_test.go index 071f19f882..3c699067a3 100644 --- a/pkg/cfn/builder/api_test.go +++ b/pkg/cfn/builder/api_test.go @@ -520,11 +520,12 @@ var _ = Describe("CloudFormation template builder API", func() { }) }) - Context("NodeGroupAppMeshExternalDNS", func() { + Context("NodeGroupAppMeshExternalDNSEBSCSI", func() { cfg, ng := newClusterConfigAndNodegroup(true) ng.IAM.WithAddonPolicies.AppMesh = api.NewBoolTrue() ng.IAM.WithAddonPolicies.ExternalDNS = api.NewBoolTrue() + ng.IAM.WithAddonPolicies.EBSCSI = api.NewBoolTrue() build(cfg, "eksctl-test-megaapps-cluster", ng) @@ -557,6 +558,25 @@ var _ = Describe("CloudFormation template builder API", func() { Expect(obj.Resources["PolicyAppMesh"].Properties.PolicyDocument.Statement[0].Action).To(Equal([]string{ "appmesh:*", })) + + Expect(obj.Resources["PolicyEBSCSI"]).ToNot(BeNil()) + Expect(obj.Resources["PolicyEBSCSI"].Properties.PolicyDocument.Statement).To(HaveLen(1)) + Expect(obj.Resources["PolicyEBSCSI"].Properties.PolicyDocument.Statement[0].Effect).To(Equal("Allow")) + Expect(obj.Resources["PolicyEBSCSI"].Properties.PolicyDocument.Statement[0].Resource).To(Equal("*")) + Expect(obj.Resources["PolicyEBSCSI"].Properties.PolicyDocument.Statement[0].Action).To(Equal([]string{ + "ec2:AttachVolume", + "ec2:CreateSnapshot", + "ec2:CreateTags", + "ec2:CreateVolume", + "ec2:DeleteSnapshot", + "ec2:DeleteTags", + "ec2:DeleteVolume", + "ec2:DescribeInstances", + "ec2:DescribeSnapshots", + "ec2:DescribeTags", + "ec2:DescribeVolumes", + "ec2:DetachVolume", + })) }) }) From 74649b00fe83b710abebe63b3bde023b128afb48 Mon Sep 17 00:00:00 2001 From: Ilya Dmitrichenko Date: Fri, 22 Mar 2019 10:31:34 +0000 Subject: [PATCH 3/4] Additional test suite improvements --- pkg/cfn/builder/api_test.go | 52 ++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/pkg/cfn/builder/api_test.go b/pkg/cfn/builder/api_test.go index 3c699067a3..b533ac6d0c 100644 --- a/pkg/cfn/builder/api_test.go +++ b/pkg/cfn/builder/api_test.go @@ -59,6 +59,7 @@ type Template struct { Resource interface{} } } + BlockDeviceMappings []interface{} VPCZoneIdentifier interface{} AssociatePublicIpAddress bool CidrIp string @@ -473,7 +474,7 @@ var _ = Describe("CloudFormation template builder API", func() { It("should have correct policies", func() { Expect(obj.Resources).ToNot(BeEmpty()) - Expect(obj.Resources["PolicyAutoScaling"]).ToNot(BeNil()) + Expect(obj.Resources).To(HaveKey("PolicyAutoScaling")) 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("*")) @@ -520,12 +521,11 @@ var _ = Describe("CloudFormation template builder API", func() { }) }) - Context("NodeGroupAppMeshExternalDNSEBSCSI", func() { + Context("NodeGroupAppMeshExternalDNS", func() { cfg, ng := newClusterConfigAndNodegroup(true) ng.IAM.WithAddonPolicies.AppMesh = api.NewBoolTrue() ng.IAM.WithAddonPolicies.ExternalDNS = api.NewBoolTrue() - ng.IAM.WithAddonPolicies.EBSCSI = api.NewBoolTrue() build(cfg, "eksctl-test-megaapps-cluster", ng) @@ -534,7 +534,7 @@ var _ = Describe("CloudFormation template builder API", func() { It("should have correct policies", func() { Expect(obj.Resources).ToNot(BeEmpty()) - Expect(obj.Resources["PolicyExternalDNSChangeSet"]).ToNot(BeNil()) + Expect(obj.Resources).To(HaveKey("PolicyExternalDNSChangeSet")) Expect(obj.Resources["PolicyExternalDNSChangeSet"].Properties.PolicyDocument.Statement).To(HaveLen(1)) Expect(obj.Resources["PolicyExternalDNSChangeSet"].Properties.PolicyDocument.Statement[0].Effect).To(Equal("Allow")) Expect(obj.Resources["PolicyExternalDNSChangeSet"].Properties.PolicyDocument.Statement[0].Resource).To(Equal("arn:aws:route53:::hostedzone/*")) @@ -542,7 +542,7 @@ var _ = Describe("CloudFormation template builder API", func() { "route53:ChangeResourceRecordSets", })) - Expect(obj.Resources["PolicyExternalDNSHostedZones"]).ToNot(BeNil()) + Expect(obj.Resources).To(HaveKey("PolicyExternalDNSHostedZones")) Expect(obj.Resources["PolicyExternalDNSHostedZones"].Properties.PolicyDocument.Statement).To(HaveLen(1)) Expect(obj.Resources["PolicyExternalDNSHostedZones"].Properties.PolicyDocument.Statement[0].Effect).To(Equal("Allow")) Expect(obj.Resources["PolicyExternalDNSHostedZones"].Properties.PolicyDocument.Statement[0].Resource).To(Equal("*")) @@ -551,7 +551,7 @@ var _ = Describe("CloudFormation template builder API", func() { "route53:ListResourceRecordSets", })) - Expect(obj.Resources["PolicyAppMesh"]).ToNot(BeNil()) + Expect(obj.Resources).To(HaveKey("PolicyAppMesh")) Expect(obj.Resources["PolicyAppMesh"].Properties.PolicyDocument.Statement).To(HaveLen(1)) Expect(obj.Resources["PolicyAppMesh"].Properties.PolicyDocument.Statement[0].Effect).To(Equal("Allow")) Expect(obj.Resources["PolicyAppMesh"].Properties.PolicyDocument.Statement[0].Resource).To(Equal("*")) @@ -559,7 +559,29 @@ var _ = Describe("CloudFormation template builder API", func() { "appmesh:*", })) - Expect(obj.Resources["PolicyEBSCSI"]).ToNot(BeNil()) + Expect(obj.Resources).ToNot(HaveKey("PolicyEBSCSI")) + Expect(obj.Resources).ToNot(HaveKey("PolicyAutoScaling")) + }) + + }) + + Context("NodeGroupEBSCSI", func() { + cfg, ng := newClusterConfigAndNodegroup(true) + + ng.VolumeSize = 0 + ng.IAM.WithAddonPolicies.EBSCSI = api.NewBoolTrue() + + build(cfg, "eksctl-test-ebscsi-cluster", ng) + + roundtript() + + It("should have correct policies", func() { + Expect(obj.Resources).ToNot(BeEmpty()) + + Expect(obj.Resources).To(HaveKey("NodeLaunchConfig")) + Expect(obj.Resources["NodeLaunchConfig"].Properties.BlockDeviceMappings).To(HaveLen(0)) + + Expect(obj.Resources).To(HaveKey("PolicyEBSCSI")) Expect(obj.Resources["PolicyEBSCSI"].Properties.PolicyDocument.Statement).To(HaveLen(1)) Expect(obj.Resources["PolicyEBSCSI"].Properties.PolicyDocument.Statement[0].Effect).To(Equal("Allow")) Expect(obj.Resources["PolicyEBSCSI"].Properties.PolicyDocument.Statement[0].Resource).To(Equal("*")) @@ -577,6 +599,11 @@ var _ = Describe("CloudFormation template builder API", func() { "ec2:DescribeVolumes", "ec2:DetachVolume", })) + + Expect(obj.Resources).ToNot(HaveKey("PolicyAutoScaling")) + Expect(obj.Resources).ToNot(HaveKey("PolicyExternalDNSChangeSet")) + Expect(obj.Resources).ToNot(HaveKey("PolicyExternalDNSHostedZones")) + Expect(obj.Resources).ToNot(HaveKey("PolicyAppMesh")) }) }) @@ -615,6 +642,17 @@ var _ = Describe("CloudFormation template builder API", func() { } Expect(x).To(Equal(refSubnets)) + Expect(obj.Resources).To(HaveKey("NodeLaunchConfig")) + + Expect(obj.Resources["NodeLaunchConfig"].Properties.BlockDeviceMappings).To(HaveLen(1)) + + rootVolume := obj.Resources["NodeLaunchConfig"].Properties.BlockDeviceMappings[0].(map[string]interface{}) + + Expect(rootVolume).To(HaveKeyWithValue("DeviceName", "/dev/xvda")) + Expect(rootVolume).To(HaveKey("Ebs")) + Expect(rootVolume["Ebs"].(map[string]interface{})).To(HaveKeyWithValue("VolumeType", "io1")) + Expect(rootVolume["Ebs"].(map[string]interface{})).To(HaveKeyWithValue("VolumeSize", 2.0)) + Expect(obj.Resources["NodeLaunchConfig"].Properties.AssociatePublicIpAddress).To(BeFalse()) Expect(obj.Resources["SSHIPv4"].Properties.CidrIp).To(Equal("192.168.0.0/16")) From 42b63f48189e1b9ce2fc661ccb940877ae000ce7 Mon Sep 17 00:00:00 2001 From: Ilya Dmitrichenko Date: Fri, 22 Mar 2019 10:35:14 +0000 Subject: [PATCH 4/4] Add missing defaulting logic and generated code --- pkg/apis/eksctl.io/v1alpha4/types.go | 1 + pkg/apis/eksctl.io/v1alpha4/validation.go | 3 +++ pkg/apis/eksctl.io/v1alpha4/zz_generated.deepcopy.go | 5 +++++ pkg/cfn/builder/api_test.go | 1 + 4 files changed, 10 insertions(+) diff --git a/pkg/apis/eksctl.io/v1alpha4/types.go b/pkg/apis/eksctl.io/v1alpha4/types.go index 8598dd697e..bb7c6f69a1 100644 --- a/pkg/apis/eksctl.io/v1alpha4/types.go +++ b/pkg/apis/eksctl.io/v1alpha4/types.go @@ -312,6 +312,7 @@ func (c *ClusterConfig) NewNodeGroup() *NodeGroup { AutoScaler: NewBoolFalse(), ExternalDNS: NewBoolFalse(), AppMesh: NewBoolFalse(), + EBSCSI: NewBoolFalse(), }, }, } diff --git a/pkg/apis/eksctl.io/v1alpha4/validation.go b/pkg/apis/eksctl.io/v1alpha4/validation.go index 1ce7abb589..e5e45d4c8e 100644 --- a/pkg/apis/eksctl.io/v1alpha4/validation.go +++ b/pkg/apis/eksctl.io/v1alpha4/validation.go @@ -28,6 +28,9 @@ func validateNodeGroupIAM(i int, ng *NodeGroup, value, fieldName, path string) e if v := ng.IAM.WithAddonPolicies.AppMesh; v != nil && *v { return fmt.Errorf("%s.AppMesh cannot be set at the same time", p) } + if v := ng.IAM.WithAddonPolicies.EBSCSI; v != nil && *v { + return fmt.Errorf("%s.ebsCSI cannot be set at the same time", p) + } } return nil } diff --git a/pkg/apis/eksctl.io/v1alpha4/zz_generated.deepcopy.go b/pkg/apis/eksctl.io/v1alpha4/zz_generated.deepcopy.go index 7aa25f3ef4..c268319409 100644 --- a/pkg/apis/eksctl.io/v1alpha4/zz_generated.deepcopy.go +++ b/pkg/apis/eksctl.io/v1alpha4/zz_generated.deepcopy.go @@ -377,6 +377,11 @@ func (in *NodeGroupIAMAddonPolicies) DeepCopyInto(out *NodeGroupIAMAddonPolicies *out = new(bool) **out = **in } + if in.EBSCSI != nil { + in, out := &in.EBSCSI, &out.EBSCSI + *out = new(bool) + **out = **in + } return } diff --git a/pkg/cfn/builder/api_test.go b/pkg/cfn/builder/api_test.go index b533ac6d0c..2eafe31efb 100644 --- a/pkg/cfn/builder/api_test.go +++ b/pkg/cfn/builder/api_test.go @@ -342,6 +342,7 @@ var _ = Describe("CloudFormation template builder API", func() { AutoScaler: api.NewBoolFalse(), ExternalDNS: api.NewBoolFalse(), AppMesh: api.NewBoolFalse(), + EBSCSI: api.NewBoolFalse(), }, }, },