From f4890b91847933d2c1ac355777fe342f3321ece7 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Tue, 9 Apr 2024 21:38:22 +0530 Subject: [PATCH] Fix reusing instanceRoleARN for nodegroups authorized with access entry --- go.mod | 22 +-- go.sum | 44 +++--- pkg/actions/nodegroup/create.go | 8 +- pkg/actions/nodegroup/create_test.go | 127 +++++++-------- .../fakes/fake_nodegroup_task_creator.go | 127 --------------- .../fakes/fake_unmanaged_nodegroup_task.go | 117 ++++++++++++++ .../fake_unmanaged_nodegroup_task_creator.go | 116 ++++++++++++++ pkg/actions/nodegroup/get_test.go | 2 +- pkg/actions/nodegroup/nodegroup.go | 49 +++--- pkg/actions/nodegroup/scale_test.go | 2 +- pkg/actions/nodegroup/update_test.go | 6 +- pkg/actions/nodegroup/upgrade_test.go | 2 +- pkg/awsapi/cloudformation.go | 8 +- pkg/cfn/builder/iam.go | 1 + pkg/cfn/builder/nodegroup.go | 24 +-- pkg/cfn/manager/create_tasks.go | 35 ++--- pkg/cfn/manager/fakes/fake_stack_creator.go | 3 + pkg/cfn/manager/fakes/fake_stack_manager.go | 89 ----------- pkg/cfn/manager/interface.go | 1 - pkg/cfn/manager/nodegroup.go | 144 ++++++++++++++++-- pkg/cfn/manager/tasks.go | 16 -- pkg/cfn/manager/tasks_test.go | 74 ++++++--- pkg/ctl/create/nodegroup.go | 18 ++- pkg/ctl/get/nodegroup.go | 2 +- pkg/ctl/scale/nodegroup.go | 2 +- pkg/ctl/update/nodegroup.go | 2 +- pkg/ctl/upgrade/nodegroup.go | 2 +- 27 files changed, 596 insertions(+), 447 deletions(-) delete mode 100644 pkg/actions/nodegroup/fakes/fake_nodegroup_task_creator.go create mode 100644 pkg/actions/nodegroup/fakes/fake_unmanaged_nodegroup_task.go create mode 100644 pkg/actions/nodegroup/fakes/fake_unmanaged_nodegroup_task_creator.go diff --git a/go.mod b/go.mod index 81fe3d6c8c7..45948edd69f 100644 --- a/go.mod +++ b/go.mod @@ -14,19 +14,19 @@ require ( github.com/aws/aws-sdk-go-v2 v1.26.1 github.com/aws/aws-sdk-go-v2/config v1.27.11 github.com/aws/aws-sdk-go-v2/credentials v1.17.11 - github.com/aws/aws-sdk-go-v2/service/autoscaling v1.40.4 - github.com/aws/aws-sdk-go-v2/service/cloudformation v1.48.0 - github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.39.1 - github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.35.0 + github.com/aws/aws-sdk-go-v2/service/autoscaling v1.40.5 + github.com/aws/aws-sdk-go-v2/service/cloudformation v1.49.0 + github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.39.2 + github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.35.1 github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.36.3 github.com/aws/aws-sdk-go-v2/service/ec2 v1.156.0 - github.com/aws/aws-sdk-go-v2/service/eks v1.41.2 - github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.24.3 - github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.30.4 - github.com/aws/aws-sdk-go-v2/service/iam v1.31.3 + github.com/aws/aws-sdk-go-v2/service/eks v1.42.1 + github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.24.4 + github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.30.5 + github.com/aws/aws-sdk-go-v2/service/iam v1.31.4 github.com/aws/aws-sdk-go-v2/service/kms v1.27.5 - github.com/aws/aws-sdk-go-v2/service/outposts v1.37.3 - github.com/aws/aws-sdk-go-v2/service/ssm v1.49.4 + github.com/aws/aws-sdk-go-v2/service/outposts v1.37.4 + github.com/aws/aws-sdk-go-v2/service/ssm v1.49.5 github.com/aws/aws-sdk-go-v2/service/sts v1.28.6 github.com/aws/smithy-go v1.20.2 github.com/benjamintf1/unmarshalledmatchers v1.0.0 @@ -124,7 +124,7 @@ require ( github.com/ashanbrown/forbidigo v1.6.0 // indirect github.com/ashanbrown/makezero v1.1.1 // indirect github.com/atotto/clipboard v0.1.4 // indirect - github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 // indirect diff --git a/go.sum b/go.sum index f5e78384452..04477557f35 100644 --- a/go.sum +++ b/go.sum @@ -718,8 +718,8 @@ github.com/aws/aws-sdk-go v1.51.16/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3Tj github.com/aws/aws-sdk-go-v2 v1.16.15/go.mod h1:SwiyXi/1zTUZ6KIAmLK5V5ll8SiURNUYOqTerZPaF9k= github.com/aws/aws-sdk-go-v2 v1.26.1 h1:5554eUqIYVWpU0YmeeYZ0wU64H2VLBs8TlhRB2L+EkA= github.com/aws/aws-sdk-go-v2 v1.26.1/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1 h1:gTK2uhtAPtFcdRRJilZPx8uJLL2J85xK11nKtWL0wfU= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1/go.mod h1:sxpLb+nZk7tIfCWChfd+h4QwHNUR57d8hA1cleTkjJo= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2 h1:x6xsQXGSmW6frevwDA+vi/wqhp1ct18mVXYN08/93to= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2/go.mod h1:lPprDr1e6cJdyYeGXnRaJoP4Md+cDBvi2eOj00BlGmg= github.com/aws/aws-sdk-go-v2/config v1.27.11 h1:f47rANd2LQEYHda2ddSCKYId18/8BhSRM4BULGmfgNA= github.com/aws/aws-sdk-go-v2/config v1.27.11/go.mod h1:SMsV78RIOYdve1vf36z8LmnszlRWkwMQtomCAI0/mIE= github.com/aws/aws-sdk-go-v2/credentials v1.17.11 h1:YuIB1dJNf1Re822rriUOTxopaHHvIq0l/pX3fwO+Tzs= @@ -734,38 +734,38 @@ github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 h1:PG1F3OD1szkuQPzDw3C github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5/go.mod h1:jU1li6RFryMz+so64PpKtudI+QzbKoIEivqdf6LNpOc= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY= -github.com/aws/aws-sdk-go-v2/service/autoscaling v1.40.4 h1:f4pkN5PVSqlGxD2gZvboz6SRaeoykgknflMPBVuhcGs= -github.com/aws/aws-sdk-go-v2/service/autoscaling v1.40.4/go.mod h1:NZBgGUf6LD2KS6Ns5xTK+cR1LK5hZwNkeOt8nDKXzMA= -github.com/aws/aws-sdk-go-v2/service/cloudformation v1.48.0 h1:uMlYsoHdd2Gr9sDGq2ieUR5jVu7F5AqPYz6UBJmdRhY= -github.com/aws/aws-sdk-go-v2/service/cloudformation v1.48.0/go.mod h1:G2qcp9xrwch6TH9AlzWoYbV9QScyZhLCoMCQ1+BD404= -github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.39.1 h1:3gmWxPT3URe8Yswfm0uiyqURRat8P7Gxv9SFSN0KOxY= -github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.39.1/go.mod h1:d6xG6uOYwvPcLfgAqYVYJziH1kO2xwaNlReUk2jJeyQ= -github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.35.0 h1:Tpy3mOh9ladwf9bhlAr38OTnZk/Uh9UuN4UNg3MFB/U= -github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.35.0/go.mod h1:bIFyamdY1PRTmifPT7uHCq4+af0SooBn9hmK9UW/hmg= +github.com/aws/aws-sdk-go-v2/service/autoscaling v1.40.5 h1:vhdJymxlWS2qftzLiuCjSswjXBRLGfzo/BEE9LDveBA= +github.com/aws/aws-sdk-go-v2/service/autoscaling v1.40.5/go.mod h1:ZErgk/bPaaZIpj+lUWGlwI1A0UFhSIscgnCPzTLnb2s= +github.com/aws/aws-sdk-go-v2/service/cloudformation v1.49.0 h1:XSUAzNAV7kCSWhV8duijMz+FrOdMqbLiRXXWBs6BA9A= +github.com/aws/aws-sdk-go-v2/service/cloudformation v1.49.0/go.mod h1:/v2KYdCW4BaHKayenaWEXOOdxItIwEA3oU0XzuQY3F0= +github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.39.2 h1:svl3DNKWpcLOlz+bFzmOxGp8gcbvSZ6m2t44Zzaet9U= +github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.39.2/go.mod h1:gAJs+mKIoK4JTQD1KMZtHgyBRZ8S6Oy5+qjJzoDAvbE= +github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.35.1 h1:suWu59CRsDNhw2YXPpa6drYEetIUUIMUhkzHmucbCf8= +github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.35.1/go.mod h1:tZiRxrv5yBRgZ9Z4OOOxwscAZRFk5DgYhEcjX1QpvgI= github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.36.3 h1:JNWpkjImTP2e308bv7ihfwgOawf640BY/pyZWrBb9rw= github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.36.3/go.mod h1:TiLZ2/+WAEyG2PnuAYj/un46UJ7qBf5BWWTAKgaHP8I= github.com/aws/aws-sdk-go-v2/service/ec2 v1.156.0 h1:TFK9GeUINErClL2+A+GLYhjiChVdaXCgIUiCsS/UQrE= github.com/aws/aws-sdk-go-v2/service/ec2 v1.156.0/go.mod h1:xejKuuRDjz6z5OqyeLsz01MlOqqW7CqpAB4PabNvpu8= -github.com/aws/aws-sdk-go-v2/service/eks v1.41.2 h1:0X5g5H8YyW9QVtlp6j+ZGHl/h0ZS58jiLRXabyiB5uw= -github.com/aws/aws-sdk-go-v2/service/eks v1.41.2/go.mod h1:T2MBMUUCoSEvHuKPplubyQJbWNghbHhx3ToJpLoipDs= -github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.24.3 h1:pjgSJEvgJzv+e0frrqspeYdHz2JSW1KAGMXRe1FuQ1M= -github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.24.3/go.mod h1:dhRVzB/bmggoMEBhYXKZrTE+jqN34O4+webZSjGi12c= -github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.30.4 h1:Lq2q/AWzFv5jHVoGJ2Hz1PkxwHYNdGzAB3lbw2g7IEU= -github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.30.4/go.mod h1:SNhjWOsnsHSveL4fDQL0sDiAIMVnKrvJTp9Z/MNspx0= -github.com/aws/aws-sdk-go-v2/service/iam v1.31.3 h1:cJn9Snros9WmDA7/qCCN7jSkowcu1CqnwhFpv4ipHEE= -github.com/aws/aws-sdk-go-v2/service/iam v1.31.3/go.mod h1:+nAQlxsBxPFf6GrL93lvCuv5PxSTX3GO0RYrURyzl/Q= +github.com/aws/aws-sdk-go-v2/service/eks v1.42.1 h1:q7MWjPP0uCmUvuGDFCvkbqRkqfH+Bq6di9RTd64S0YM= +github.com/aws/aws-sdk-go-v2/service/eks v1.42.1/go.mod h1:UhKBrO0Ezz8iIg02a6u4irGKBKh0gTz3fF8LNdD2vDI= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.24.4 h1:V5YvSMQwZklktzYeOOhYdptx7rP650XP3RnxwNu1UEQ= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.24.4/go.mod h1:aYygRYqRxmLGrxRxAisgNarwo4x8bcJG14rh4r57VqE= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.30.5 h1:/x2u/TOx+n17U+gz98TOw1HKJom0EOqrhL4SjrHr0cQ= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.30.5/go.mod h1:e1McVqsud0JOERidvppLEHnuCdh/X6MRyL5L0LseAUk= +github.com/aws/aws-sdk-go-v2/service/iam v1.31.4 h1:eVm30ZIDv//r6Aogat9I88b5YX1xASSLcEDqHYRPVl0= +github.com/aws/aws-sdk-go-v2/service/iam v1.31.4/go.mod h1:aXWImQV0uTW35LM0A/T4wEg6R1/ReXUu4SM6/lUHYK0= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 h1:Ji0DY1xUsUr3I8cHps0G+XM3WWU16lP6yG8qu1GAZAs= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2/go.mod h1:5CsjAbs3NlGQyZNFACh+zztPDI7fU6eW9QsxjfnuBKg= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7 h1:ogRAwT1/gxJBcSWDMZlgyFUM962F51A5CRhDLbxLdmo= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7/go.mod h1:YCsIZhXfRPLFFCl5xxY+1T9RKzOKjCut+28JSX2DnAk= github.com/aws/aws-sdk-go-v2/service/kms v1.27.5 h1:7lKTr8zJ2nVaVgyII+7hUayTi7xWedMuANiNVXiD2S8= github.com/aws/aws-sdk-go-v2/service/kms v1.27.5/go.mod h1:D9FVDkZjkZnnFHymJ3fPVz0zOUlNSd0xcIIVmmrAac8= -github.com/aws/aws-sdk-go-v2/service/outposts v1.37.3 h1:FJVXeS+dVDBMr7g0vNl7Z5mekQu+JdwbWZmDX1O+C/s= -github.com/aws/aws-sdk-go-v2/service/outposts v1.37.3/go.mod h1:eL+8XoNJVASkW/kDpjNVpcJMSfxUVotaoouYLekSQzU= +github.com/aws/aws-sdk-go-v2/service/outposts v1.37.4 h1:nItBrTJbK72LWI3jWtpLC22yLjPrzVL998pp+yRAnQk= +github.com/aws/aws-sdk-go-v2/service/outposts v1.37.4/go.mod h1:6fqELmjNXUPBviJYhN4QzmMQRtuPAREMRKlhzfBD8j0= github.com/aws/aws-sdk-go-v2/service/pricing v1.17.0 h1:RQOMvPwte2H4ZqsiZmrla1crhBWDFnW8bZynkec5cGU= github.com/aws/aws-sdk-go-v2/service/pricing v1.17.0/go.mod h1:LJyh9figH3ZpSiVjR5umzbl6V3EpQdZR4Se1ayoUtfI= -github.com/aws/aws-sdk-go-v2/service/ssm v1.49.4 h1:2f1Gkbe9O15DntphmbdEInn6MGIZ3x2bbv8b0p/4awQ= -github.com/aws/aws-sdk-go-v2/service/ssm v1.49.4/go.mod h1:BlIdE/k0lwn8xyn8piK02oYjqKsxulo6yPV3BuIWuMI= +github.com/aws/aws-sdk-go-v2/service/ssm v1.49.5 h1:KBwyHzP2QG8J//hoGuPyHWZ5tgL1BzaoMURUkecpI4g= +github.com/aws/aws-sdk-go-v2/service/ssm v1.49.5/go.mod h1:Ebk/HZmGhxWKDVxM4+pwbxGjm3RQOQLMjAEosI3ss9Q= github.com/aws/aws-sdk-go-v2/service/sso v1.20.5 h1:vN8hEbpRnL7+Hopy9dzmRle1xmDc7o8tmY0klsr175w= github.com/aws/aws-sdk-go-v2/service/sso v1.20.5/go.mod h1:qGzynb/msuZIE8I75DVRCUXw3o3ZyBmUvMwQ2t/BrGM= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.4 h1:Jux+gDDyi1Lruk+KHF91tK2KCuY61kzoCpvtvJJBtOE= diff --git a/pkg/actions/nodegroup/create.go b/pkg/actions/nodegroup/create.go index 136c27f6281..e2170b87b15 100644 --- a/pkg/actions/nodegroup/create.go +++ b/pkg/actions/nodegroup/create.go @@ -254,7 +254,13 @@ func (m *Manager) nodeCreationTasks(ctx context.Context, isOwnedCluster, skipEgr Parallel: true, } disableAccessEntryCreation := !m.accessEntry.IsEnabled() || updateAuthConfigMap != nil - nodeGroupTasks := m.stackManager.NewUnmanagedNodeGroupTask(ctx, cfg.NodeGroups, !awsNodeUsesIRSA, skipEgressRules, disableAccessEntryCreation, vpcImporter) + unmanagedNodeGroupTaskCreator := m.unmanagedNodeGroupTask.NewCreator(m.cfg, m.ctl.AWSProvider, m.stackManager) + nodeGroupTasks := unmanagedNodeGroupTaskCreator.Create(ctx, manager.CreateNodeGroupOptions{ + ForceAddCNIPolicy: !awsNodeUsesIRSA, + SkipEgressRules: skipEgressRules, + DisableAccessEntryCreation: disableAccessEntryCreation, + VPCImporter: vpcImporter, + }) if nodeGroupTasks.Len() > 0 { allNodeGroupTasks.Append(nodeGroupTasks) } diff --git a/pkg/actions/nodegroup/create_test.go b/pkg/actions/nodegroup/create_test.go index 19765ae44cc..c574668f2fa 100644 --- a/pkg/actions/nodegroup/create_test.go +++ b/pkg/actions/nodegroup/create_test.go @@ -5,6 +5,8 @@ import ( "fmt" "os" + "github.com/weaveworks/eksctl/pkg/actions/nodegroup/fakes" + "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/cloudformation" cftypes "github.com/aws/aws-sdk-go-v2/service/cloudformation/types" @@ -21,7 +23,6 @@ import ( core "k8s.io/client-go/testing" "github.com/weaveworks/eksctl/pkg/actions/nodegroup" - ngfakes "github.com/weaveworks/eksctl/pkg/actions/nodegroup/fakes" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/authconfigmap" "github.com/weaveworks/eksctl/pkg/cfn/manager" @@ -58,22 +59,12 @@ type mockCalls struct { type expectedCalls struct { kubeProvider *eksfakes.FakeKubeProvider nodeGroupFilter *utilfakes.FakeNodegroupFilter - nodeGroupTaskCreator *ngfakes.FakeNodeGroupTaskCreator clientset *fake.Clientset -} - -//counterfeiter:generate -o fakes/fake_nodegroup_task_creator.go . nodeGroupTaskCreator -type nodeGroupTaskCreator interface { - NewUnmanagedNodeGroupTask(context.Context, []*api.NodeGroup, bool, bool, bool, vpc.Importer) *tasks.TaskTree + nodeGroupTaskCreator *fakes.FakeUnmanagedNodeGroupTaskCreator } type stackManagerDelegate struct { manager.StackManager - ngTaskCreator nodeGroupTaskCreator -} - -func (s *stackManagerDelegate) NewUnmanagedNodeGroupTask(ctx context.Context, nodeGroups []*api.NodeGroup, forceAddCNIPolicy, skipEgressRules, disableAccessEntryCreation bool, vpcImporter vpc.Importer) *tasks.TaskTree { - return s.ngTaskCreator.NewUnmanagedNodeGroupTask(ctx, nodeGroups, forceAddCNIPolicy, skipEgressRules, disableAccessEntryCreation, vpcImporter) } func (s *stackManagerDelegate) NewManagedNodeGroupTask(context.Context, []*api.ManagedNodeGroup, bool, vpc.Importer) *tasks.TaskTree { @@ -106,20 +97,18 @@ var _ = DescribeTable("Create", func(t ngEntry) { } clientset := fake.NewSimpleClientset() - m := nodegroup.New(cfg, ctl, clientset, nil) + var fakeTask fakes.FakeUnmanagedNodeGroupTask + var fakeCreator fakes.FakeUnmanagedNodeGroupTaskCreator + fakeCreator.CreateReturns(&tasks.TaskTree{}) + fakeTask.NewCreatorReturns(&fakeCreator) + + m := nodegroup.New(cfg, ctl, clientset, nil, &fakeTask) k := &eksfakes.FakeKubeProvider{} m.MockKubeProvider(k) - var ngTaskCreator ngfakes.FakeNodeGroupTaskCreator - ngTaskCreator.NewUnmanagedNodeGroupTaskStub = func(_ context.Context, _ []*api.NodeGroup, _, _, _ bool, _ vpc.Importer) *tasks.TaskTree { - return &tasks.TaskTree{ - Tasks: []tasks.Task{noopTask}, - } - } stackManager := &stackManagerDelegate{ - ngTaskCreator: &ngTaskCreator, - StackManager: m.GetStackManager(), + StackManager: m.GetStackManager(), } m.SetStackManager(stackManager) @@ -154,8 +143,8 @@ var _ = DescribeTable("Create", func(t ngEntry) { t.expectedCalls(expectedCalls{ kubeProvider: k, nodeGroupFilter: &ngFilter, - nodeGroupTaskCreator: &ngTaskCreator, clientset: clientset, + nodeGroupTaskCreator: &fakeCreator, }) } }, @@ -534,7 +523,7 @@ var _ = DescribeTable("Create", func(t ngEntry) { expectedErr: errors.New("--update-auth-configmap is not supported when authenticationMode is set to API"), }), - Entry("creates nodegroup using access entries when authenticationMode is API_AND_CONFIG_MAP and updateAuthConfigMap is not supplied", ngEntry{ + FEntry("creates nodegroup using access entries when authenticationMode is API_AND_CONFIG_MAP and updateAuthConfigMap is not supplied", ngEntry{ mockCalls: func(m mockCalls) { mockProviderWithConfig(m.mockProvider, defaultOutput, nil, nil, &ekstypes.AccessConfigResponse{ AuthenticationMode: ekstypes.AuthenticationModeApiAndConfigMap, @@ -544,9 +533,9 @@ var _ = DescribeTable("Create", func(t ngEntry) { expectedCalls: func(e expectedCalls) { Expect(e.kubeProvider.NewRawClientCallCount()).To(Equal(1)) Expect(e.nodeGroupFilter.SetOnlyLocalCallCount()).To(Equal(1)) - Expect(e.nodeGroupTaskCreator.NewUnmanagedNodeGroupTaskCallCount()).To(Equal(1)) - _, _, _, _, disableAccessEntryCreation, _ := e.nodeGroupTaskCreator.NewUnmanagedNodeGroupTaskArgsForCall(0) - Expect(disableAccessEntryCreation).To(BeFalse()) + Expect(e.nodeGroupTaskCreator.CreateCallCount()).To(Equal(1)) + _, options := e.nodeGroupTaskCreator.CreateArgsForCall(0) + Expect(options.DisableAccessEntryCreation).To(BeFalse()) Expect(getIAMIdentities(e.clientset)).To(HaveLen(0)) }, }), @@ -593,9 +582,9 @@ var _ = DescribeTable("Create", func(t ngEntry) { expectedCalls: func(e expectedCalls) { Expect(e.kubeProvider.NewRawClientCallCount()).To(Equal(1)) Expect(e.nodeGroupFilter.SetOnlyLocalCallCount()).To(Equal(1)) - Expect(e.nodeGroupTaskCreator.NewUnmanagedNodeGroupTaskCallCount()).To(Equal(1)) - _, _, _, _, disableAccessEntryCreation, _ := e.nodeGroupTaskCreator.NewUnmanagedNodeGroupTaskArgsForCall(0) - Expect(disableAccessEntryCreation).To(BeTrue()) + Expect(e.nodeGroupTaskCreator.CreateCallCount()).To(Equal(1)) + _, options := e.nodeGroupTaskCreator.CreateArgsForCall(0) + Expect(options.DisableAccessEntryCreation).To(BeTrue()) Expect(getIAMIdentities(e.clientset)).To(HaveLen(0)) }, }), @@ -614,9 +603,9 @@ var _ = DescribeTable("Create", func(t ngEntry) { expectedCalls: func(e expectedCalls) { Expect(e.kubeProvider.NewRawClientCallCount()).To(Equal(1)) Expect(e.nodeGroupFilter.SetOnlyLocalCallCount()).To(Equal(1)) - Expect(e.nodeGroupTaskCreator.NewUnmanagedNodeGroupTaskCallCount()).To(Equal(1)) - _, _, _, _, disableAccessEntryCreation, _ := e.nodeGroupTaskCreator.NewUnmanagedNodeGroupTaskArgsForCall(0) - Expect(disableAccessEntryCreation).To(BeTrue()) + Expect(e.nodeGroupTaskCreator.CreateCallCount()).To(Equal(1)) + _, options := e.nodeGroupTaskCreator.CreateArgsForCall(0) + Expect(options.DisableAccessEntryCreation).To(BeTrue()) Expect(getIAMIdentities(e.clientset)).To(HaveLen(0)) }, }), @@ -668,19 +657,39 @@ var _ = DescribeTable("Create", func(t ngEntry) { }), ) -var noopTask = &tasks.GenericTask{ - Doer: func() error { - return nil - }, -} - func newClusterConfig() *api.ClusterConfig { + ng := &api.NodeGroup{ + NodeGroupBase: &api.NodeGroupBase{ + Name: "my-ng", + AMIFamily: api.NodeImageFamilyAmazonLinux2, + AMI: "ami-123", + SSH: &api.NodeGroupSSH{Allow: api.Disabled()}, + InstanceSelector: &api.InstanceSelector{}, + ScalingConfig: &api.ScalingConfig{}, + IAM: &api.NodeGroupIAM{ + InstanceRoleARN: "arn:aws:iam::1234567890:role/my-ng", + }, + }, + } + mng := &api.ManagedNodeGroup{ + NodeGroupBase: &api.NodeGroupBase{ + Name: "my-ng", + AMIFamily: api.NodeImageFamilyAmazonLinux2, + SSH: &api.NodeGroupSSH{Allow: api.Disabled()}, + InstanceSelector: &api.InstanceSelector{}, + ScalingConfig: &api.ScalingConfig{}, + }, + } + meta := &api.ClusterMeta{ + Name: "my-cluster", + Version: api.DefaultVersion, + } + api.SetNodeGroupDefaults(ng, meta, false) + api.SetManagedNodeGroupDefaults(mng, meta, false) + return &api.ClusterConfig{ TypeMeta: api.ClusterConfigTypeMeta(), - Metadata: &api.ClusterMeta{ - Name: "my-cluster", - Version: api.DefaultVersion, - }, + Metadata: meta, Status: &api.ClusterStatus{ Endpoint: "https://localhost/", CertificateAuthorityData: []byte("dGVzdAo="), @@ -690,30 +699,10 @@ func newClusterConfig() *api.ClusterConfig { CloudWatch: &api.ClusterCloudWatch{ ClusterLogging: &api.ClusterCloudWatchLogging{}, }, - AccessConfig: &api.AccessConfig{}, - PrivateCluster: &api.PrivateCluster{}, - NodeGroups: []*api.NodeGroup{{ - NodeGroupBase: &api.NodeGroupBase{ - Name: "my-ng", - AMIFamily: api.NodeImageFamilyAmazonLinux2, - AMI: "ami-123", - SSH: &api.NodeGroupSSH{Allow: api.Disabled()}, - InstanceSelector: &api.InstanceSelector{}, - ScalingConfig: &api.ScalingConfig{}, - IAM: &api.NodeGroupIAM{ - InstanceRoleARN: "arn:aws:iam::1234567890:role/my-ng", - }, - }}, - }, - ManagedNodeGroups: []*api.ManagedNodeGroup{{ - NodeGroupBase: &api.NodeGroupBase{ - Name: "my-ng", - AMIFamily: api.NodeImageFamilyAmazonLinux2, - SSH: &api.NodeGroupSSH{Allow: api.Disabled()}, - InstanceSelector: &api.InstanceSelector{}, - ScalingConfig: &api.ScalingConfig{}, - }}, - }, + AccessConfig: &api.AccessConfig{}, + PrivateCluster: &api.PrivateCluster{}, + NodeGroups: []*api.NodeGroup{ng}, + ManagedNodeGroups: []*api.ManagedNodeGroup{mng}, } } @@ -747,9 +736,9 @@ func getIAMIdentities(clientset kubernetes.Interface) []iam.Identity { func expectedCallsForAWSAuth(e expectedCalls) { Expect(e.kubeProvider.NewRawClientCallCount()).To(Equal(1)) Expect(e.nodeGroupFilter.SetOnlyLocalCallCount()).To(Equal(1)) - Expect(e.nodeGroupTaskCreator.NewUnmanagedNodeGroupTaskCallCount()).To(Equal(1)) - _, _, _, _, disableAccessEntryCreation, _ := e.nodeGroupTaskCreator.NewUnmanagedNodeGroupTaskArgsForCall(0) - Expect(disableAccessEntryCreation).To(BeTrue()) + Expect(e.nodeGroupTaskCreator.CreateCallCount()).To(Equal(1)) + _, options := e.nodeGroupTaskCreator.CreateArgsForCall(0) + Expect(options.DisableAccessEntryCreation).To(BeTrue()) identities := getIAMIdentities(e.clientset) Expect(identities).To(HaveLen(1)) for _, id := range identities { diff --git a/pkg/actions/nodegroup/fakes/fake_nodegroup_task_creator.go b/pkg/actions/nodegroup/fakes/fake_nodegroup_task_creator.go deleted file mode 100644 index b06eb016ec0..00000000000 --- a/pkg/actions/nodegroup/fakes/fake_nodegroup_task_creator.go +++ /dev/null @@ -1,127 +0,0 @@ -// Code generated by counterfeiter. DO NOT EDIT. -package fakes - -import ( - "context" - "sync" - - "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" - "github.com/weaveworks/eksctl/pkg/utils/tasks" - "github.com/weaveworks/eksctl/pkg/vpc" -) - -type FakeNodeGroupTaskCreator struct { - NewUnmanagedNodeGroupTaskStub func(context.Context, []*v1alpha5.NodeGroup, bool, bool, bool, vpc.Importer) *tasks.TaskTree - newUnmanagedNodeGroupTaskMutex sync.RWMutex - newUnmanagedNodeGroupTaskArgsForCall []struct { - arg1 context.Context - arg2 []*v1alpha5.NodeGroup - arg3 bool - arg4 bool - arg5 bool - arg6 vpc.Importer - } - newUnmanagedNodeGroupTaskReturns struct { - result1 *tasks.TaskTree - } - newUnmanagedNodeGroupTaskReturnsOnCall map[int]struct { - result1 *tasks.TaskTree - } - invocations map[string][][]interface{} - invocationsMutex sync.RWMutex -} - -func (fake *FakeNodeGroupTaskCreator) NewUnmanagedNodeGroupTask(arg1 context.Context, arg2 []*v1alpha5.NodeGroup, arg3 bool, arg4 bool, arg5 bool, arg6 vpc.Importer) *tasks.TaskTree { - var arg2Copy []*v1alpha5.NodeGroup - if arg2 != nil { - arg2Copy = make([]*v1alpha5.NodeGroup, len(arg2)) - copy(arg2Copy, arg2) - } - fake.newUnmanagedNodeGroupTaskMutex.Lock() - ret, specificReturn := fake.newUnmanagedNodeGroupTaskReturnsOnCall[len(fake.newUnmanagedNodeGroupTaskArgsForCall)] - fake.newUnmanagedNodeGroupTaskArgsForCall = append(fake.newUnmanagedNodeGroupTaskArgsForCall, struct { - arg1 context.Context - arg2 []*v1alpha5.NodeGroup - arg3 bool - arg4 bool - arg5 bool - arg6 vpc.Importer - }{arg1, arg2Copy, arg3, arg4, arg5, arg6}) - stub := fake.NewUnmanagedNodeGroupTaskStub - fakeReturns := fake.newUnmanagedNodeGroupTaskReturns - fake.recordInvocation("NewUnmanagedNodeGroupTask", []interface{}{arg1, arg2Copy, arg3, arg4, arg5, arg6}) - fake.newUnmanagedNodeGroupTaskMutex.Unlock() - if stub != nil { - return stub(arg1, arg2, arg3, arg4, arg5, arg6) - } - if specificReturn { - return ret.result1 - } - return fakeReturns.result1 -} - -func (fake *FakeNodeGroupTaskCreator) NewUnmanagedNodeGroupTaskCallCount() int { - fake.newUnmanagedNodeGroupTaskMutex.RLock() - defer fake.newUnmanagedNodeGroupTaskMutex.RUnlock() - return len(fake.newUnmanagedNodeGroupTaskArgsForCall) -} - -func (fake *FakeNodeGroupTaskCreator) NewUnmanagedNodeGroupTaskCalls(stub func(context.Context, []*v1alpha5.NodeGroup, bool, bool, bool, vpc.Importer) *tasks.TaskTree) { - fake.newUnmanagedNodeGroupTaskMutex.Lock() - defer fake.newUnmanagedNodeGroupTaskMutex.Unlock() - fake.NewUnmanagedNodeGroupTaskStub = stub -} - -func (fake *FakeNodeGroupTaskCreator) NewUnmanagedNodeGroupTaskArgsForCall(i int) (context.Context, []*v1alpha5.NodeGroup, bool, bool, bool, vpc.Importer) { - fake.newUnmanagedNodeGroupTaskMutex.RLock() - defer fake.newUnmanagedNodeGroupTaskMutex.RUnlock() - argsForCall := fake.newUnmanagedNodeGroupTaskArgsForCall[i] - return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4, argsForCall.arg5, argsForCall.arg6 -} - -func (fake *FakeNodeGroupTaskCreator) NewUnmanagedNodeGroupTaskReturns(result1 *tasks.TaskTree) { - fake.newUnmanagedNodeGroupTaskMutex.Lock() - defer fake.newUnmanagedNodeGroupTaskMutex.Unlock() - fake.NewUnmanagedNodeGroupTaskStub = nil - fake.newUnmanagedNodeGroupTaskReturns = struct { - result1 *tasks.TaskTree - }{result1} -} - -func (fake *FakeNodeGroupTaskCreator) NewUnmanagedNodeGroupTaskReturnsOnCall(i int, result1 *tasks.TaskTree) { - fake.newUnmanagedNodeGroupTaskMutex.Lock() - defer fake.newUnmanagedNodeGroupTaskMutex.Unlock() - fake.NewUnmanagedNodeGroupTaskStub = nil - if fake.newUnmanagedNodeGroupTaskReturnsOnCall == nil { - fake.newUnmanagedNodeGroupTaskReturnsOnCall = make(map[int]struct { - result1 *tasks.TaskTree - }) - } - fake.newUnmanagedNodeGroupTaskReturnsOnCall[i] = struct { - result1 *tasks.TaskTree - }{result1} -} - -func (fake *FakeNodeGroupTaskCreator) Invocations() map[string][][]interface{} { - fake.invocationsMutex.RLock() - defer fake.invocationsMutex.RUnlock() - fake.newUnmanagedNodeGroupTaskMutex.RLock() - defer fake.newUnmanagedNodeGroupTaskMutex.RUnlock() - copiedInvocations := map[string][][]interface{}{} - for key, value := range fake.invocations { - copiedInvocations[key] = value - } - return copiedInvocations -} - -func (fake *FakeNodeGroupTaskCreator) recordInvocation(key string, args []interface{}) { - fake.invocationsMutex.Lock() - defer fake.invocationsMutex.Unlock() - if fake.invocations == nil { - fake.invocations = map[string][][]interface{}{} - } - if fake.invocations[key] == nil { - fake.invocations[key] = [][]interface{}{} - } - fake.invocations[key] = append(fake.invocations[key], args) -} diff --git a/pkg/actions/nodegroup/fakes/fake_unmanaged_nodegroup_task.go b/pkg/actions/nodegroup/fakes/fake_unmanaged_nodegroup_task.go new file mode 100644 index 00000000000..bdf34fdef4d --- /dev/null +++ b/pkg/actions/nodegroup/fakes/fake_unmanaged_nodegroup_task.go @@ -0,0 +1,117 @@ +// Code generated by counterfeiter. DO NOT EDIT. +package fakes + +import ( + "sync" + + "github.com/weaveworks/eksctl/pkg/actions/nodegroup" + "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" + "github.com/weaveworks/eksctl/pkg/cfn/manager" +) + +type FakeUnmanagedNodeGroupTask struct { + NewCreatorStub func(*v1alpha5.ClusterConfig, v1alpha5.ClusterProvider, manager.NodeGroupStackManager) nodegroup.UnmanagedNodeGroupTaskCreator + newCreatorMutex sync.RWMutex + newCreatorArgsForCall []struct { + arg1 *v1alpha5.ClusterConfig + arg2 v1alpha5.ClusterProvider + arg3 manager.NodeGroupStackManager + } + newCreatorReturns struct { + result1 nodegroup.UnmanagedNodeGroupTaskCreator + } + newCreatorReturnsOnCall map[int]struct { + result1 nodegroup.UnmanagedNodeGroupTaskCreator + } + invocations map[string][][]interface{} + invocationsMutex sync.RWMutex +} + +func (fake *FakeUnmanagedNodeGroupTask) NewCreator(arg1 *v1alpha5.ClusterConfig, arg2 v1alpha5.ClusterProvider, arg3 manager.NodeGroupStackManager) nodegroup.UnmanagedNodeGroupTaskCreator { + fake.newCreatorMutex.Lock() + ret, specificReturn := fake.newCreatorReturnsOnCall[len(fake.newCreatorArgsForCall)] + fake.newCreatorArgsForCall = append(fake.newCreatorArgsForCall, struct { + arg1 *v1alpha5.ClusterConfig + arg2 v1alpha5.ClusterProvider + arg3 manager.NodeGroupStackManager + }{arg1, arg2, arg3}) + stub := fake.NewCreatorStub + fakeReturns := fake.newCreatorReturns + fake.recordInvocation("NewCreator", []interface{}{arg1, arg2, arg3}) + fake.newCreatorMutex.Unlock() + if stub != nil { + return stub(arg1, arg2, arg3) + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeUnmanagedNodeGroupTask) NewCreatorCallCount() int { + fake.newCreatorMutex.RLock() + defer fake.newCreatorMutex.RUnlock() + return len(fake.newCreatorArgsForCall) +} + +func (fake *FakeUnmanagedNodeGroupTask) NewCreatorCalls(stub func(*v1alpha5.ClusterConfig, v1alpha5.ClusterProvider, manager.NodeGroupStackManager) nodegroup.UnmanagedNodeGroupTaskCreator) { + fake.newCreatorMutex.Lock() + defer fake.newCreatorMutex.Unlock() + fake.NewCreatorStub = stub +} + +func (fake *FakeUnmanagedNodeGroupTask) NewCreatorArgsForCall(i int) (*v1alpha5.ClusterConfig, v1alpha5.ClusterProvider, manager.NodeGroupStackManager) { + fake.newCreatorMutex.RLock() + defer fake.newCreatorMutex.RUnlock() + argsForCall := fake.newCreatorArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3 +} + +func (fake *FakeUnmanagedNodeGroupTask) NewCreatorReturns(result1 nodegroup.UnmanagedNodeGroupTaskCreator) { + fake.newCreatorMutex.Lock() + defer fake.newCreatorMutex.Unlock() + fake.NewCreatorStub = nil + fake.newCreatorReturns = struct { + result1 nodegroup.UnmanagedNodeGroupTaskCreator + }{result1} +} + +func (fake *FakeUnmanagedNodeGroupTask) NewCreatorReturnsOnCall(i int, result1 nodegroup.UnmanagedNodeGroupTaskCreator) { + fake.newCreatorMutex.Lock() + defer fake.newCreatorMutex.Unlock() + fake.NewCreatorStub = nil + if fake.newCreatorReturnsOnCall == nil { + fake.newCreatorReturnsOnCall = make(map[int]struct { + result1 nodegroup.UnmanagedNodeGroupTaskCreator + }) + } + fake.newCreatorReturnsOnCall[i] = struct { + result1 nodegroup.UnmanagedNodeGroupTaskCreator + }{result1} +} + +func (fake *FakeUnmanagedNodeGroupTask) Invocations() map[string][][]interface{} { + fake.invocationsMutex.RLock() + defer fake.invocationsMutex.RUnlock() + fake.newCreatorMutex.RLock() + defer fake.newCreatorMutex.RUnlock() + copiedInvocations := map[string][][]interface{}{} + for key, value := range fake.invocations { + copiedInvocations[key] = value + } + return copiedInvocations +} + +func (fake *FakeUnmanagedNodeGroupTask) recordInvocation(key string, args []interface{}) { + fake.invocationsMutex.Lock() + defer fake.invocationsMutex.Unlock() + if fake.invocations == nil { + fake.invocations = map[string][][]interface{}{} + } + if fake.invocations[key] == nil { + fake.invocations[key] = [][]interface{}{} + } + fake.invocations[key] = append(fake.invocations[key], args) +} + +var _ nodegroup.UnmanagedNodeGroupTask = new(FakeUnmanagedNodeGroupTask) diff --git a/pkg/actions/nodegroup/fakes/fake_unmanaged_nodegroup_task_creator.go b/pkg/actions/nodegroup/fakes/fake_unmanaged_nodegroup_task_creator.go new file mode 100644 index 00000000000..d5b4f70d0d7 --- /dev/null +++ b/pkg/actions/nodegroup/fakes/fake_unmanaged_nodegroup_task_creator.go @@ -0,0 +1,116 @@ +// Code generated by counterfeiter. DO NOT EDIT. +package fakes + +import ( + "context" + "sync" + + "github.com/weaveworks/eksctl/pkg/actions/nodegroup" + "github.com/weaveworks/eksctl/pkg/cfn/manager" + "github.com/weaveworks/eksctl/pkg/utils/tasks" +) + +type FakeUnmanagedNodeGroupTaskCreator struct { + CreateStub func(context.Context, manager.CreateNodeGroupOptions) *tasks.TaskTree + createMutex sync.RWMutex + createArgsForCall []struct { + arg1 context.Context + arg2 manager.CreateNodeGroupOptions + } + createReturns struct { + result1 *tasks.TaskTree + } + createReturnsOnCall map[int]struct { + result1 *tasks.TaskTree + } + invocations map[string][][]interface{} + invocationsMutex sync.RWMutex +} + +func (fake *FakeUnmanagedNodeGroupTaskCreator) Create(arg1 context.Context, arg2 manager.CreateNodeGroupOptions) *tasks.TaskTree { + fake.createMutex.Lock() + ret, specificReturn := fake.createReturnsOnCall[len(fake.createArgsForCall)] + fake.createArgsForCall = append(fake.createArgsForCall, struct { + arg1 context.Context + arg2 manager.CreateNodeGroupOptions + }{arg1, arg2}) + stub := fake.CreateStub + fakeReturns := fake.createReturns + fake.recordInvocation("Create", []interface{}{arg1, arg2}) + fake.createMutex.Unlock() + if stub != nil { + return stub(arg1, arg2) + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeUnmanagedNodeGroupTaskCreator) CreateCallCount() int { + fake.createMutex.RLock() + defer fake.createMutex.RUnlock() + return len(fake.createArgsForCall) +} + +func (fake *FakeUnmanagedNodeGroupTaskCreator) CreateCalls(stub func(context.Context, manager.CreateNodeGroupOptions) *tasks.TaskTree) { + fake.createMutex.Lock() + defer fake.createMutex.Unlock() + fake.CreateStub = stub +} + +func (fake *FakeUnmanagedNodeGroupTaskCreator) CreateArgsForCall(i int) (context.Context, manager.CreateNodeGroupOptions) { + fake.createMutex.RLock() + defer fake.createMutex.RUnlock() + argsForCall := fake.createArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2 +} + +func (fake *FakeUnmanagedNodeGroupTaskCreator) CreateReturns(result1 *tasks.TaskTree) { + fake.createMutex.Lock() + defer fake.createMutex.Unlock() + fake.CreateStub = nil + fake.createReturns = struct { + result1 *tasks.TaskTree + }{result1} +} + +func (fake *FakeUnmanagedNodeGroupTaskCreator) CreateReturnsOnCall(i int, result1 *tasks.TaskTree) { + fake.createMutex.Lock() + defer fake.createMutex.Unlock() + fake.CreateStub = nil + if fake.createReturnsOnCall == nil { + fake.createReturnsOnCall = make(map[int]struct { + result1 *tasks.TaskTree + }) + } + fake.createReturnsOnCall[i] = struct { + result1 *tasks.TaskTree + }{result1} +} + +func (fake *FakeUnmanagedNodeGroupTaskCreator) Invocations() map[string][][]interface{} { + fake.invocationsMutex.RLock() + defer fake.invocationsMutex.RUnlock() + fake.createMutex.RLock() + defer fake.createMutex.RUnlock() + copiedInvocations := map[string][][]interface{}{} + for key, value := range fake.invocations { + copiedInvocations[key] = value + } + return copiedInvocations +} + +func (fake *FakeUnmanagedNodeGroupTaskCreator) recordInvocation(key string, args []interface{}) { + fake.invocationsMutex.Lock() + defer fake.invocationsMutex.Unlock() + if fake.invocations == nil { + fake.invocations = map[string][][]interface{}{} + } + if fake.invocations[key] == nil { + fake.invocations[key] = [][]interface{}{} + } + fake.invocations[key] = append(fake.invocations[key], args) +} + +var _ nodegroup.UnmanagedNodeGroupTaskCreator = new(FakeUnmanagedNodeGroupTaskCreator) diff --git a/pkg/actions/nodegroup/get_test.go b/pkg/actions/nodegroup/get_test.go index 655baae3da6..9fd7489d56d 100644 --- a/pkg/actions/nodegroup/get_test.go +++ b/pkg/actions/nodegroup/get_test.go @@ -50,7 +50,7 @@ var _ = Describe("Get", func() { cfg.Metadata.Name = clusterName p = mockprovider.NewMockProvider() fakeClientSet = fake.NewSimpleClientset() - m = nodegroup.New(cfg, &eks.ClusterProvider{AWSProvider: p}, fakeClientSet, nil) + m = nodegroup.New(cfg, &eks.ClusterProvider{AWSProvider: p}, fakeClientSet, nil, nil) fakeStackManager = new(fakes.FakeStackManager) m.SetStackManager(fakeStackManager) }) diff --git a/pkg/actions/nodegroup/nodegroup.go b/pkg/actions/nodegroup/nodegroup.go index f4ce30e85a8..c2b7d6a24e0 100644 --- a/pkg/actions/nodegroup/nodegroup.go +++ b/pkg/actions/nodegroup/nodegroup.go @@ -1,13 +1,15 @@ package nodegroup import ( + "context" "time" - "github.com/weaveworks/eksctl/pkg/accessentry" + "github.com/weaveworks/eksctl/pkg/utils/tasks" "github.com/aws/aws-sdk-go/aws/request" "k8s.io/client-go/kubernetes" + "github.com/weaveworks/eksctl/pkg/accessentry" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/cfn/builder" "github.com/weaveworks/eksctl/pkg/cfn/manager" @@ -15,29 +17,42 @@ import ( "github.com/weaveworks/eksctl/pkg/utils/waiters" ) +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate +//counterfeiter:generate -o fakes/fake_unmanaged_nodegroup_task.go . UnmanagedNodeGroupTask +type UnmanagedNodeGroupTask interface { + NewCreator(clusterConfig *api.ClusterConfig, awsProvider api.ClusterProvider, stackManager manager.NodeGroupStackManager) UnmanagedNodeGroupTaskCreator +} + +//counterfeiter:generate -o fakes/fake_unmanaged_nodegroup_task_creator.go . UnmanagedNodeGroupTaskCreator +type UnmanagedNodeGroupTaskCreator interface { + Create(ctx context.Context, options manager.CreateNodeGroupOptions) *tasks.TaskTree +} + type Manager struct { - stackManager manager.StackManager - ctl *eks.ClusterProvider - cfg *api.ClusterConfig - clientSet kubernetes.Interface - wait WaitFunc - instanceSelector eks.InstanceSelector - launchTemplateFetcher *builder.LaunchTemplateFetcher - accessEntry *accessentry.Service + stackManager manager.StackManager + unmanagedNodeGroupTask UnmanagedNodeGroupTask + ctl *eks.ClusterProvider + cfg *api.ClusterConfig + clientSet kubernetes.Interface + wait WaitFunc + instanceSelector eks.InstanceSelector + launchTemplateFetcher *builder.LaunchTemplateFetcher + accessEntry *accessentry.Service } type WaitFunc func(name, msg string, acceptors []request.WaiterAcceptor, newRequest func() *request.Request, waitTimeout time.Duration, troubleshoot func(string) error) error // New creates a new manager. -func New(cfg *api.ClusterConfig, ctl *eks.ClusterProvider, clientSet kubernetes.Interface, instanceSelector eks.InstanceSelector) *Manager { +func New(cfg *api.ClusterConfig, ctl *eks.ClusterProvider, clientSet kubernetes.Interface, instanceSelector eks.InstanceSelector, unmanagedNodeGroupTask UnmanagedNodeGroupTask) *Manager { return &Manager{ - stackManager: ctl.NewStackManager(cfg), - ctl: ctl, - cfg: cfg, - clientSet: clientSet, - wait: waiters.Wait, - instanceSelector: instanceSelector, - launchTemplateFetcher: builder.NewLaunchTemplateFetcher(ctl.AWSProvider.EC2()), + stackManager: ctl.NewStackManager(cfg), + unmanagedNodeGroupTask: unmanagedNodeGroupTask, + ctl: ctl, + cfg: cfg, + clientSet: clientSet, + wait: waiters.Wait, + instanceSelector: instanceSelector, + launchTemplateFetcher: builder.NewLaunchTemplateFetcher(ctl.AWSProvider.EC2()), accessEntry: &accessentry.Service{ ClusterStateGetter: ctl, }, diff --git a/pkg/actions/nodegroup/scale_test.go b/pkg/actions/nodegroup/scale_test.go index 234725b19ea..acfb32fc105 100644 --- a/pkg/actions/nodegroup/scale_test.go +++ b/pkg/actions/nodegroup/scale_test.go @@ -52,7 +52,7 @@ var _ = Describe("Scale", func() { }, } - m = nodegroup.New(cfg, &eks.ClusterProvider{AWSProvider: p}, fake.NewSimpleClientset(), nil) + m = nodegroup.New(cfg, &eks.ClusterProvider{AWSProvider: p}, fake.NewSimpleClientset(), nil, nil) fakeStackManager = new(fakes.FakeStackManager) m.SetStackManager(fakeStackManager) p.MockCloudFormation().On("ListStacksPages", mock.Anything, mock.Anything).Return(nil, nil) diff --git a/pkg/actions/nodegroup/update_test.go b/pkg/actions/nodegroup/update_test.go index a0297885ac4..240380b9b05 100644 --- a/pkg/actions/nodegroup/update_test.go +++ b/pkg/actions/nodegroup/update_test.go @@ -46,7 +46,7 @@ var _ = Describe("Update", func() { NodegroupName: &ngName, }).Return(nil, &ekstypes.ResourceNotFoundException{}) - m = New(cfg, &eks.ClusterProvider{AWSProvider: p}, nil, nil) + m = New(cfg, &eks.ClusterProvider{AWSProvider: p}, nil, nil, nil) err := m.Update(context.Background(), false) Expect(err).To(HaveOccurred()) Expect(err).To(MatchError(ContainSubstring("could not find managed nodegroup with name \"my-ng\""))) @@ -76,7 +76,7 @@ var _ = Describe("Update", func() { MaxUnavailable: aws.Int(6), } - m = New(cfg, &eks.ClusterProvider{AWSProvider: p}, nil, nil) + m = New(cfg, &eks.ClusterProvider{AWSProvider: p}, nil, nil, nil) err := m.Update(context.Background(), false) Expect(err).NotTo(HaveOccurred()) }) @@ -135,7 +135,7 @@ var _ = Describe("Update", func() { cfg.ManagedNodeGroups = append(cfg.ManagedNodeGroups, newNg) - m = New(cfg, &eks.ClusterProvider{AWSProvider: p}, nil, nil) + m = New(cfg, &eks.ClusterProvider{AWSProvider: p}, nil, nil, nil) err := m.Update(context.Background(), false) Expect(err).NotTo(HaveOccurred()) }) diff --git a/pkg/actions/nodegroup/upgrade_test.go b/pkg/actions/nodegroup/upgrade_test.go index bc258a7ba15..a1698e9f1c5 100644 --- a/pkg/actions/nodegroup/upgrade_test.go +++ b/pkg/actions/nodegroup/upgrade_test.go @@ -57,7 +57,7 @@ var _ = Describe("Upgrade", func() { cfg.Metadata.Name = clusterName p = mockprovider.NewMockProvider() fakeClientSet = fake.NewSimpleClientset() - m = nodegroup.New(cfg, &eks.ClusterProvider{AWSProvider: p}, fakeClientSet, nil) + m = nodegroup.New(cfg, &eks.ClusterProvider{AWSProvider: p}, fakeClientSet, nil, nil) fakeStackManager = new(fakes.FakeStackManager) m.SetStackManager(fakeStackManager) diff --git a/pkg/awsapi/cloudformation.go b/pkg/awsapi/cloudformation.go index 6b2f8f87cd8..07980b1dd2f 100644 --- a/pkg/awsapi/cloudformation.go +++ b/pkg/awsapi/cloudformation.go @@ -26,12 +26,12 @@ type CloudFormation interface { // in the CloudFormation User Guide. Once you have activated a public third-party // extension in your account and Region, use SetTypeConfiguration (https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_SetTypeConfiguration.html) // to specify configuration properties for the extension. For more information, see - // Configuring extensions at the account level (https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/registry-register.html#registry-set-configuration) + // Configuring extensions at the account level (https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/registry-private.html#registry-set-configuration) // in the CloudFormation User Guide. ActivateType(ctx context.Context, params *ActivateTypeInput, optFns ...func(*Options)) (*ActivateTypeOutput, error) // Returns configuration data for the specified CloudFormation extensions, from // the CloudFormation registry for the account and Region. For more information, - // see Configuring extensions at the account level (https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/registry-register.html#registry-set-configuration) + // see Configuring extensions at the account level (https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/registry-private.html#registry-set-configuration) // in the CloudFormation User Guide. BatchDescribeTypeConfigurations(ctx context.Context, params *BatchDescribeTypeConfigurationsInput, optFns ...func(*Options)) (*BatchDescribeTypeConfigurationsOutput, error) // Cancels an update on the specified stack. If the call completes successfully, @@ -454,7 +454,7 @@ type CloudFormation interface { // to monitor the progress of the registration request. Once you have registered a // private extension in your account and Region, use SetTypeConfiguration (https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_SetTypeConfiguration.html) // to specify configuration properties for the extension. For more information, see - // Configuring extensions at the account level (https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/registry-register.html#registry-set-configuration) + // Configuring extensions at the account level (https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/registry-private.html#registry-set-configuration) // in the CloudFormation User Guide. RegisterType(ctx context.Context, params *RegisterTypeInput, optFns ...func(*Options)) (*RegisterTypeOutput, error) // When specifying RollbackStack , you preserve the state of previously provisioned @@ -475,7 +475,7 @@ type CloudFormation interface { // Specifies the configuration data for a registered CloudFormation extension, in // the given account and Region. To view the current configuration data for an // extension, refer to the ConfigurationSchema element of DescribeType (https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_DescribeType.html) - // . For more information, see Configuring extensions at the account level (https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/registry-register.html#registry-set-configuration) + // . For more information, see Configuring extensions at the account level (https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/registry-private.html#registry-set-configuration) // in the CloudFormation User Guide. It's strongly recommended that you use dynamic // references to restrict sensitive configuration definitions, such as third-party // credentials. For more details on dynamic references, see Using dynamic diff --git a/pkg/cfn/builder/iam.go b/pkg/cfn/builder/iam.go index 422a03d3230..d2be78ca074 100644 --- a/pkg/cfn/builder/iam.go +++ b/pkg/cfn/builder/iam.go @@ -132,6 +132,7 @@ func (n *NodeGroupResourceSet) addResourcesForIAM(ctx context.Context) error { // (which is needed in order to authorise the nodegroup) n.instanceProfileARN = gfnt.NewString(n.spec.IAM.InstanceProfileARN) if n.spec.IAM.InstanceRoleARN != "" { + // TODO n.rs.defineOutputWithoutCollector(outputs.NodeGroupInstanceProfileARN, n.spec.IAM.InstanceProfileARN, true) n.rs.defineOutputWithoutCollector(outputs.NodeGroupInstanceRoleARN, n.spec.IAM.InstanceRoleARN, true) return nil diff --git a/pkg/cfn/builder/nodegroup.go b/pkg/cfn/builder/nodegroup.go index e9bbc63759a..859ed41b3e2 100644 --- a/pkg/cfn/builder/nodegroup.go +++ b/pkg/cfn/builder/nodegroup.go @@ -13,7 +13,6 @@ import ( gfn "github.com/weaveworks/goformation/v4/cloudformation" gfncfn "github.com/weaveworks/goformation/v4/cloudformation/cloudformation" gfnec2 "github.com/weaveworks/goformation/v4/cloudformation/ec2" - gfneks "github.com/weaveworks/goformation/v4/cloudformation/eks" gfnt "github.com/weaveworks/goformation/v4/cloudformation/types" "github.com/kris-nova/logger" @@ -145,7 +144,7 @@ func (n *NodeGroupResourceSet) AddAllResources(ctx context.Context) error { } n.addResourcesForSecurityGroups() if !n.disableAccessEntryCreation { - n.addAccessEntry() + n.addAccessEntryOutput() } return n.addResourcesForNodeGroup(ctx) @@ -179,26 +178,7 @@ var ControlPlaneNodeGroupEgressRules = []PartialEgressRule{ // ControlPlaneEgressRuleDescriptionPrefix is the prefix applied to the description for control plane security group egress rules. var ControlPlaneEgressRuleDescriptionPrefix = "Allow control plane to communicate with " -func (n *NodeGroupResourceSet) addAccessEntry() { - // TODO: SDK types. - var amiType string - if api.IsWindowsImage(n.spec.AMIFamily) { - amiType = "EC2_WINDOWS" - } else { - amiType = "EC2_LINUX" - } - - var principalARN *gfnt.Value - if roleARN := n.spec.IAM.InstanceRoleARN; roleARN != "" { - principalARN = gfnt.NewString(roleARN) - } else { - principalARN = gfnt.MakeFnGetAttString(cfnIAMInstanceRoleName, "Arn") - } - n.newResource("AccessEntry", &gfneks.AccessEntry{ - PrincipalArn: principalARN, - ClusterName: gfnt.NewString(n.clusterSpec.Metadata.Name), - Type: gfnt.NewString(amiType), - }) +func (n *NodeGroupResourceSet) addAccessEntryOutput() { n.rs.defineOutputWithoutCollector(outputs.NodeGroupUsesAccessEntry, true, false) } diff --git a/pkg/cfn/manager/create_tasks.go b/pkg/cfn/manager/create_tasks.go index ea0b596d6a3..2b63a41680a 100644 --- a/pkg/cfn/manager/create_tasks.go +++ b/pkg/cfn/manager/create_tasks.go @@ -47,7 +47,19 @@ func (c *StackCollection) NewTasksToCreateCluster(ctx context.Context, nodeGroup IsSubTask: true, } disableAccessEntryCreation := accessConfig.AuthenticationMode == ekstypes.AuthenticationModeConfigMap - if unmanagedNodeGroupTasks := c.NewUnmanagedNodeGroupTask(ctx, nodeGroups, false, false, disableAccessEntryCreation, vpcImporter); unmanagedNodeGroupTasks.Len() > 0 { + unmanagedNodeGroupTask := &NodeGroupTask{ + ClusterConfig: c.spec, + EC2API: c.ec2API, + IAMAPI: c.iamAPI, + EKSAPI: c.eksAPI, + StackManager: c, + } + if unmanagedNodeGroupTasks := unmanagedNodeGroupTask.Create(ctx, CreateNodeGroupOptions{ + ForceAddCNIPolicy: false, + SkipEgressRules: false, + DisableAccessEntryCreation: disableAccessEntryCreation, + VPCImporter: vpcImporter, + }); unmanagedNodeGroupTasks.Len() > 0 { unmanagedNodeGroupTasks.IsSubTask = true nodeGroupTasks.Append(unmanagedNodeGroupTasks) } @@ -75,27 +87,6 @@ func (c *StackCollection) NewTasksToCreateCluster(ctx context.Context, nodeGroup return &taskTree } -// NewUnmanagedNodeGroupTask defines tasks required to create all nodegroups. -func (c *StackCollection) NewUnmanagedNodeGroupTask(ctx context.Context, nodeGroups []*api.NodeGroup, forceAddCNIPolicy, skipEgressRules, disableAccessEntryCreation bool, vpcImporter vpc.Importer) *tasks.TaskTree { - taskTree := &tasks.TaskTree{Parallel: true} - - for _, ng := range nodeGroups { - taskTree.Append(&nodeGroupTask{ - info: fmt.Sprintf("create nodegroup %q", ng.NameString()), - ctx: ctx, - nodeGroup: ng, - stackCollection: c, - forceAddCNIPolicy: forceAddCNIPolicy, - vpcImporter: vpcImporter, - skipEgressRules: skipEgressRules, - disableAccessEntryCreation: disableAccessEntryCreation, - }) - // TODO: move authconfigmap tasks here using kubernetesTask and kubernetes.CallbackClientSet - } - - return taskTree -} - // NewManagedNodeGroupTask defines tasks required to create managed nodegroups func (c *StackCollection) NewManagedNodeGroupTask(ctx context.Context, nodeGroups []*api.ManagedNodeGroup, forceAddCNIPolicy bool, vpcImporter vpc.Importer) *tasks.TaskTree { taskTree := &tasks.TaskTree{Parallel: true} diff --git a/pkg/cfn/manager/fakes/fake_stack_creator.go b/pkg/cfn/manager/fakes/fake_stack_creator.go index 479ffd1c2a6..7075ce790a3 100644 --- a/pkg/cfn/manager/fakes/fake_stack_creator.go +++ b/pkg/cfn/manager/fakes/fake_stack_creator.go @@ -6,6 +6,7 @@ import ( "sync" "github.com/weaveworks/eksctl/pkg/cfn/builder" + "github.com/weaveworks/eksctl/pkg/cfn/manager" ) type FakeStackCreator struct { @@ -118,3 +119,5 @@ func (fake *FakeStackCreator) recordInvocation(key string, args []interface{}) { } fake.invocations[key] = append(fake.invocations[key], args) } + +var _ manager.StackCreator = new(FakeStackCreator) diff --git a/pkg/cfn/manager/fakes/fake_stack_manager.go b/pkg/cfn/manager/fakes/fake_stack_manager.go index 2f03f615c61..020d43088b2 100644 --- a/pkg/cfn/manager/fakes/fake_stack_manager.go +++ b/pkg/cfn/manager/fakes/fake_stack_manager.go @@ -776,22 +776,6 @@ type FakeStackManager struct { result1 *tasks.TaskTree result2 error } - NewUnmanagedNodeGroupTaskStub func(context.Context, []*v1alpha5.NodeGroup, bool, bool, bool, vpc.Importer) *tasks.TaskTree - newUnmanagedNodeGroupTaskMutex sync.RWMutex - newUnmanagedNodeGroupTaskArgsForCall []struct { - arg1 context.Context - arg2 []*v1alpha5.NodeGroup - arg3 bool - arg4 bool - arg5 bool - arg6 vpc.Importer - } - newUnmanagedNodeGroupTaskReturns struct { - result1 *tasks.TaskTree - } - newUnmanagedNodeGroupTaskReturnsOnCall map[int]struct { - result1 *tasks.TaskTree - } PropagateManagedNodeGroupTagsToASGStub func(string, map[string]string, []string, chan error) error propagateManagedNodeGroupTagsToASGMutex sync.RWMutex propagateManagedNodeGroupTagsToASGArgsForCall []struct { @@ -4442,77 +4426,6 @@ func (fake *FakeStackManager) NewTasksToDeleteOIDCProviderWithIAMServiceAccounts }{result1, result2} } -func (fake *FakeStackManager) NewUnmanagedNodeGroupTask(arg1 context.Context, arg2 []*v1alpha5.NodeGroup, arg3 bool, arg4 bool, arg5 bool, arg6 vpc.Importer) *tasks.TaskTree { - var arg2Copy []*v1alpha5.NodeGroup - if arg2 != nil { - arg2Copy = make([]*v1alpha5.NodeGroup, len(arg2)) - copy(arg2Copy, arg2) - } - fake.newUnmanagedNodeGroupTaskMutex.Lock() - ret, specificReturn := fake.newUnmanagedNodeGroupTaskReturnsOnCall[len(fake.newUnmanagedNodeGroupTaskArgsForCall)] - fake.newUnmanagedNodeGroupTaskArgsForCall = append(fake.newUnmanagedNodeGroupTaskArgsForCall, struct { - arg1 context.Context - arg2 []*v1alpha5.NodeGroup - arg3 bool - arg4 bool - arg5 bool - arg6 vpc.Importer - }{arg1, arg2Copy, arg3, arg4, arg5, arg6}) - stub := fake.NewUnmanagedNodeGroupTaskStub - fakeReturns := fake.newUnmanagedNodeGroupTaskReturns - fake.recordInvocation("NewUnmanagedNodeGroupTask", []interface{}{arg1, arg2Copy, arg3, arg4, arg5, arg6}) - fake.newUnmanagedNodeGroupTaskMutex.Unlock() - if stub != nil { - return stub(arg1, arg2, arg3, arg4, arg5, arg6) - } - if specificReturn { - return ret.result1 - } - return fakeReturns.result1 -} - -func (fake *FakeStackManager) NewUnmanagedNodeGroupTaskCallCount() int { - fake.newUnmanagedNodeGroupTaskMutex.RLock() - defer fake.newUnmanagedNodeGroupTaskMutex.RUnlock() - return len(fake.newUnmanagedNodeGroupTaskArgsForCall) -} - -func (fake *FakeStackManager) NewUnmanagedNodeGroupTaskCalls(stub func(context.Context, []*v1alpha5.NodeGroup, bool, bool, bool, vpc.Importer) *tasks.TaskTree) { - fake.newUnmanagedNodeGroupTaskMutex.Lock() - defer fake.newUnmanagedNodeGroupTaskMutex.Unlock() - fake.NewUnmanagedNodeGroupTaskStub = stub -} - -func (fake *FakeStackManager) NewUnmanagedNodeGroupTaskArgsForCall(i int) (context.Context, []*v1alpha5.NodeGroup, bool, bool, bool, vpc.Importer) { - fake.newUnmanagedNodeGroupTaskMutex.RLock() - defer fake.newUnmanagedNodeGroupTaskMutex.RUnlock() - argsForCall := fake.newUnmanagedNodeGroupTaskArgsForCall[i] - return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4, argsForCall.arg5, argsForCall.arg6 -} - -func (fake *FakeStackManager) NewUnmanagedNodeGroupTaskReturns(result1 *tasks.TaskTree) { - fake.newUnmanagedNodeGroupTaskMutex.Lock() - defer fake.newUnmanagedNodeGroupTaskMutex.Unlock() - fake.NewUnmanagedNodeGroupTaskStub = nil - fake.newUnmanagedNodeGroupTaskReturns = struct { - result1 *tasks.TaskTree - }{result1} -} - -func (fake *FakeStackManager) NewUnmanagedNodeGroupTaskReturnsOnCall(i int, result1 *tasks.TaskTree) { - fake.newUnmanagedNodeGroupTaskMutex.Lock() - defer fake.newUnmanagedNodeGroupTaskMutex.Unlock() - fake.NewUnmanagedNodeGroupTaskStub = nil - if fake.newUnmanagedNodeGroupTaskReturnsOnCall == nil { - fake.newUnmanagedNodeGroupTaskReturnsOnCall = make(map[int]struct { - result1 *tasks.TaskTree - }) - } - fake.newUnmanagedNodeGroupTaskReturnsOnCall[i] = struct { - result1 *tasks.TaskTree - }{result1} -} - func (fake *FakeStackManager) PropagateManagedNodeGroupTagsToASG(arg1 string, arg2 map[string]string, arg3 []string, arg4 chan error) error { var arg3Copy []string if arg3 != nil { @@ -4977,8 +4890,6 @@ func (fake *FakeStackManager) Invocations() map[string][][]interface{} { defer fake.newTasksToDeleteNodeGroupsMutex.RUnlock() fake.newTasksToDeleteOIDCProviderWithIAMServiceAccountsMutex.RLock() defer fake.newTasksToDeleteOIDCProviderWithIAMServiceAccountsMutex.RUnlock() - fake.newUnmanagedNodeGroupTaskMutex.RLock() - defer fake.newUnmanagedNodeGroupTaskMutex.RUnlock() fake.propagateManagedNodeGroupTagsToASGMutex.RLock() defer fake.propagateManagedNodeGroupTagsToASGMutex.RUnlock() fake.refreshFargatePodExecutionRoleARNMutex.RLock() diff --git a/pkg/cfn/manager/interface.go b/pkg/cfn/manager/interface.go index b87d0adbc75..f0d24955ba8 100644 --- a/pkg/cfn/manager/interface.go +++ b/pkg/cfn/manager/interface.go @@ -93,7 +93,6 @@ type StackManager interface { NewTasksToDeleteIAMServiceAccounts(ctx context.Context, serviceAccounts []string, clientSetGetter kubernetes.ClientSetGetter, wait bool) (*tasks.TaskTree, error) NewTasksToDeleteNodeGroups(stacks []NodeGroupStack, shouldDelete func(_ string) bool, wait bool, cleanup func(chan error, string) error) (*tasks.TaskTree, error) NewTasksToDeleteOIDCProviderWithIAMServiceAccounts(ctx context.Context, newOIDCManager NewOIDCManager, cluster *ekstypes.Cluster, clientSetGetter kubernetes.ClientSetGetter, force bool) (*tasks.TaskTree, error) - NewUnmanagedNodeGroupTask(ctx context.Context, nodeGroups []*api.NodeGroup, forceAddCNIPolicy, skipEgressRules, disableAccessEntryCreation bool, importer vpc.Importer) *tasks.TaskTree PropagateManagedNodeGroupTagsToASG(ngName string, ngTags map[string]string, asgNames []string, errCh chan error) error RefreshFargatePodExecutionRoleARN(ctx context.Context) error StackStatusIsNotTransitional(s *Stack) bool diff --git a/pkg/cfn/manager/nodegroup.go b/pkg/cfn/manager/nodegroup.go index d4373b33764..dadb143e9da 100644 --- a/pkg/cfn/manager/nodegroup.go +++ b/pkg/cfn/manager/nodegroup.go @@ -5,6 +5,12 @@ import ( "fmt" "strings" + "github.com/weaveworks/eksctl/pkg/cfn/outputs" + + "github.com/weaveworks/eksctl/pkg/utils/tasks" + + "github.com/weaveworks/eksctl/pkg/awsapi" + "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/autoscaling" asgtypes "github.com/aws/aws-sdk-go-v2/service/autoscaling/types" @@ -19,6 +25,7 @@ import ( api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/cfn/builder" "github.com/weaveworks/eksctl/pkg/nodebootstrap" + eksutils "github.com/weaveworks/eksctl/pkg/utils/eks" "github.com/weaveworks/eksctl/pkg/version" "github.com/weaveworks/eksctl/pkg/vpc" ) @@ -31,28 +38,81 @@ type NodeGroupStack struct { Stack *Stack } -// makeNodeGroupStackName generates the name of the nodegroup stack identified by its name, isolated by the cluster this StackCollection operates on -func (c *StackCollection) makeNodeGroupStackName(name string) string { - return fmt.Sprintf("eksctl-%s-nodegroup-%s", c.spec.Metadata.Name, name) +// makeNodeGroupStackName generates the name of the nodegroup stack identified by its name. +func makeNodeGroupStackName(clusterName, ngName string) string { + return fmt.Sprintf("eksctl-%s-nodegroup-%s", clusterName, ngName) } -// createNodeGroupTask creates the nodegroup -func (c *StackCollection) createNodeGroupTask(ctx context.Context, errs chan error, ng *api.NodeGroup, forceAddCNIPolicy, skipEgressRules, disableAccessEntryCreation bool, vpcImporter vpc.Importer) error { - name := c.makeNodeGroupStackName(ng.Name) +// CreateNodeGroupOptions holds options for creating nodegroup tasks. +type CreateNodeGroupOptions struct { + ForceAddCNIPolicy bool + SkipEgressRules bool + DisableAccessEntryCreation bool + VPCImporter vpc.Importer +} + +// A NodeGroupStackManager describes and creates nodegroup stacks. +type NodeGroupStackManager interface { + DescribeNodeGroupStack(ctx context.Context, nodeGroupName string) (*Stack, error) + CreateStack(ctx context.Context, stackName string, resourceSet builder.ResourceSetReader, tags, parameters map[string]string, errs chan error) error +} + +// NodeGroupTask creates tasks for creating self-managed nodegroups. +type NodeGroupTask struct { + ClusterConfig *api.ClusterConfig + EC2API awsapi.EC2 + IAMAPI awsapi.IAM + EKSAPI awsapi.EKS + StackManager NodeGroupStackManager +} + +// Create creates a TaskTree for creating nodegroups. +func (n *NodeGroupTask) Create(ctx context.Context, options CreateNodeGroupOptions) *tasks.TaskTree { + taskTree := &tasks.TaskTree{Parallel: true} + + for _, ng := range n.ClusterConfig.NodeGroups { + ng := ng + createNodeGroupTask := &tasks.GenericTask{ + Description: fmt.Sprintf("create nodegroup %q", ng.NameString()), + Doer: func() error { + return n.createNodeGroup(ctx, ng, options) + }, + } + + if options.DisableAccessEntryCreation { + taskTree.Append(createNodeGroupTask) + } else { + var ngTask tasks.TaskTree + ngTask.Append(createNodeGroupTask) + ngTask.Append(&tasks.GenericTask{ + Description: fmt.Sprintf("create access entry for nodegroup %q", ng.NameString()), + Doer: func() error { + return n.maybeCreateAccessEntry(ctx, ng) + }, + }) + taskTree.Append(&ngTask) + } + } + + return taskTree +} + +func (n *NodeGroupTask) createNodeGroup(ctx context.Context, ng *api.NodeGroup, options CreateNodeGroupOptions) error { + name := makeNodeGroupStackName(n.ClusterConfig.Metadata.Name, ng.Name) logger.Info("building nodegroup stack %q", name) - bootstrapper, err := nodebootstrap.NewBootstrapper(c.spec, ng) + bootstrapper, err := nodebootstrap.NewBootstrapper(n.ClusterConfig, ng) if err != nil { return errors.Wrap(err, "error creating bootstrapper") } - stack := builder.NewNodeGroupResourceSet(c.ec2API, c.iamAPI, builder.NodeGroupOptions{ - ClusterConfig: c.spec, + stack := builder.NewNodeGroupResourceSet(n.EC2API, n.IAMAPI, builder.NodeGroupOptions{ + ClusterConfig: n.ClusterConfig, NodeGroup: ng, Bootstrapper: bootstrapper, - ForceAddCNIPolicy: forceAddCNIPolicy, - VPCImporter: vpcImporter, - SkipEgressRules: skipEgressRules, - DisableAccessEntryCreation: disableAccessEntryCreation, + ForceAddCNIPolicy: options.ForceAddCNIPolicy, + VPCImporter: options.VPCImporter, + SkipEgressRules: options.SkipEgressRules, + DisableAccessEntryCreation: options.DisableAccessEntryCreation, }) if err := stack.AddAllResources(ctx); err != nil { return err @@ -65,7 +125,63 @@ func (c *StackCollection) createNodeGroupTask(ctx context.Context, errs chan err ng.Tags[api.OldNodeGroupNameTag] = ng.Name ng.Tags[api.NodeGroupTypeTag] = string(api.NodeGroupTypeUnmanaged) - return c.CreateStack(ctx, name, stack, ng.Tags, nil, errs) + errCh := make(chan error) + if err := n.StackManager.CreateStack(ctx, name, stack, ng.Tags, nil, errCh); err != nil { + return err + } + return <-errCh +} + +func (n *NodeGroupTask) maybeCreateAccessEntry(ctx context.Context, ng *api.NodeGroup) error { + stack, err := n.StackManager.DescribeNodeGroupStack(ctx, ng.Name) + if err != nil { + return fmt.Errorf("error describing nodegroup stack: %w", err) + } + var roleARN string + if err := outputs.Collect(*stack, map[string]outputs.Collector{ + outputs.NodeGroupInstanceRoleARN: func(val string) error { + roleARN = val + return nil + }, + }, nil); err != nil { + return fmt.Errorf("failed to find node instance role ARN in stack: %w", err) + } + + _, err = n.EKSAPI.DescribeAccessEntry(ctx, &eks.DescribeAccessEntryInput{ + ClusterName: aws.String(n.ClusterConfig.Metadata.Name), + PrincipalArn: aws.String(roleARN), + }) + switch { + case err == nil: + return nil + case eksutils.IsNotFound(err): + if err := n.createAccessEntry(ctx, ng, roleARN); err != nil { + return fmt.Errorf("error creating access entry for nodegroup %q: %w", ng.NameString(), err) + } + return nil + default: + return fmt.Errorf("error describing access entry for principal ARN %q: %w", roleARN, err) + } +} + +func (n *NodeGroupTask) createAccessEntry(ctx context.Context, ng *api.NodeGroup, roleARN string) error { + var amiType string + if api.IsWindowsImage(ng.AMIFamily) { + amiType = "EC2_WINDOWS" + } else { + amiType = "EC2_LINUX" + } + _, err := n.EKSAPI.CreateAccessEntry(ctx, &eks.CreateAccessEntryInput{ + ClusterName: aws.String(n.ClusterConfig.Metadata.Name), + PrincipalArn: aws.String(roleARN), + Type: aws.String(amiType), + }) + return err +} + +// makeNodeGroupStackName generates the name of the nodegroup stack identified by its name and this StackCollection's cluster. +func (c *StackCollection) makeNodeGroupStackName(ngName string) string { + return makeNodeGroupStackName(c.spec.Metadata.Name, ngName) } func (c *StackCollection) createManagedNodeGroupTask(ctx context.Context, errorCh chan error, ng *api.ManagedNodeGroup, forceAddCNIPolicy bool, vpcImporter vpc.Importer) error { diff --git a/pkg/cfn/manager/tasks.go b/pkg/cfn/manager/tasks.go index 59d719b8828..05be123cf80 100644 --- a/pkg/cfn/manager/tasks.go +++ b/pkg/cfn/manager/tasks.go @@ -26,22 +26,6 @@ func (t *createClusterTask) Do(errorCh chan error) error { return t.stackCollection.createClusterTask(t.ctx, errorCh, t.supportsManagedNodes) } -type nodeGroupTask struct { - info string - ctx context.Context - nodeGroup *api.NodeGroup - forceAddCNIPolicy bool - disableAccessEntryCreation bool - skipEgressRules bool - vpcImporter vpc.Importer - stackCollection *StackCollection -} - -func (t *nodeGroupTask) Describe() string { return t.info } -func (t *nodeGroupTask) Do(errs chan error) error { - return t.stackCollection.createNodeGroupTask(t.ctx, errs, t.nodeGroup, t.forceAddCNIPolicy, t.skipEgressRules, t.disableAccessEntryCreation, t.vpcImporter) -} - type managedNodeGroupTask struct { info string nodeGroup *api.ManagedNodeGroup diff --git a/pkg/cfn/manager/tasks_test.go b/pkg/cfn/manager/tasks_test.go index ba1066cbc31..8785e4e0834 100644 --- a/pkg/cfn/manager/tasks_test.go +++ b/pkg/cfn/manager/tasks_test.go @@ -12,6 +12,7 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + format "github.com/onsi/gomega/format" "github.com/pkg/errors" "github.com/stretchr/testify/mock" @@ -33,6 +34,8 @@ func (t *task) Do(chan error) error { } var _ = Describe("StackCollection Tasks", func() { + format.MaxLength = 9999 + format.MaxDepth = 999999 var ( p *mockprovider.MockProvider cfg *api.ClusterConfig @@ -73,32 +76,61 @@ var _ = Describe("StackCollection Tasks", func() { stackManager = NewStackCollection(p, cfg) }) + type unmanagedNodeGroupTaskEntry struct { + nodegroups []*api.NodeGroup + + expectedOutput string + } + DescribeTable("should have nice description for unmanaged nodegroups", func(e unmanagedNodeGroupTaskEntry) { + clusterConfig := api.NewClusterConfig() + clusterConfig.NodeGroups = e.nodegroups + nodeGroupTask := &NodeGroupTask{ + ClusterConfig: clusterConfig, + } + tasks := nodeGroupTask.Create(context.Background(), CreateNodeGroupOptions{}) + Expect(tasks.Describe()).To(Equal(e.expectedOutput)) + }, + Entry("2 nodegroups", unmanagedNodeGroupTaskEntry{ + nodegroups: makeNodeGroups("foo", "bar"), + expectedOutput: ` +2 parallel tasks: { +2 sequential tasks: { create nodegroup "foo", create access entry for nodegroup "foo" + +}, +2 sequential tasks: { create nodegroup "bar", create access entry for nodegroup "bar" +} +} +`, + }), + + Entry("1 nodegroup", unmanagedNodeGroupTaskEntry{ + nodegroups: makeNodeGroups("bar"), + expectedOutput: `1 task: { +2 sequential tasks: { create nodegroup "bar", create access entry for nodegroup "bar" +} }`, + }), + + Entry("1 nodegroup", unmanagedNodeGroupTaskEntry{ + nodegroups: makeNodeGroups("foo"), + expectedOutput: `1 task: { +2 sequential tasks: { create nodegroup "foo", create access entry for nodegroup "foo" +} }`, + }), + + Entry("no nodegroups", unmanagedNodeGroupTaskEntry{ + expectedOutput: `no tasks`, + }), + ) + It("should have nice description", func() { - fakeVPCImporter := new(vpcfakes.FakeImporter) - accessConfig := &api.AccessConfig{} + accessConfig := &api.AccessConfig{ + AuthenticationMode: ekstypes.AuthenticationModeConfigMap, + } // TODO use DescribeTable // The supportsManagedNodes argument has no effect on the Describe call, so the values are alternated // in these tests - { - tasks := stackManager.NewUnmanagedNodeGroupTask(context.Background(), makeNodeGroups("bar", "foo"), false, false, false, fakeVPCImporter) - Expect(tasks.Describe()).To(Equal(` -2 parallel tasks: { create nodegroup "bar", create nodegroup "foo" -} -`)) - } - { - tasks := stackManager.NewUnmanagedNodeGroupTask(context.Background(), makeNodeGroups("bar"), false, false, false, fakeVPCImporter) - Expect(tasks.Describe()).To(Equal(`1 task: { create nodegroup "bar" }`)) - } - { - tasks := stackManager.NewUnmanagedNodeGroupTask(context.Background(), makeNodeGroups("foo"), false, false, false, fakeVPCImporter) - Expect(tasks.Describe()).To(Equal(`1 task: { create nodegroup "foo" }`)) - } - { - tasks := stackManager.NewUnmanagedNodeGroupTask(context.Background(), nil, false, false, false, fakeVPCImporter) - Expect(tasks.Describe()).To(Equal(`no tasks`)) - } + { tasks := stackManager.NewTasksToCreateCluster(context.Background(), makeNodeGroups("bar", "foo"), nil, accessConfig, nil) Expect(tasks.Describe()).To(Equal(` diff --git a/pkg/ctl/create/nodegroup.go b/pkg/ctl/create/nodegroup.go index c042478385d..ebdd6c307ba 100644 --- a/pkg/ctl/create/nodegroup.go +++ b/pkg/ctl/create/nodegroup.go @@ -6,6 +6,8 @@ import ( "io" "strings" + "github.com/weaveworks/eksctl/pkg/cfn/manager" + "github.com/aws/amazon-ec2-instance-selector/v2/pkg/selector" "github.com/kris-nova/logger" @@ -71,7 +73,7 @@ func createNodeGroupCmd(cmd *cmdutils.Cmd) { return err } - manager := nodegroup.New(cmd.ClusterConfig, ctl, clientSet, instanceSelector) + manager := nodegroup.New(cmd.ClusterConfig, ctl, clientSet, instanceSelector, &unmanagedNodeGroupTask{}) return manager.Create(ctx, nodegroup.CreateOpts{ InstallNeuronDevicePlugin: options.InstallNeuronDevicePlugin, InstallNvidiaDevicePlugin: options.InstallNvidiaDevicePlugin, @@ -86,6 +88,20 @@ func createNodeGroupCmd(cmd *cmdutils.Cmd) { }) } +// a pattern to define a no-field struct. +type unmanagedNodeGroupTask struct { +} + +func (u *unmanagedNodeGroupTask) NewCreator(clusterConfig *api.ClusterConfig, awsProvider api.ClusterProvider, stackManager manager.NodeGroupStackManager) nodegroup.UnmanagedNodeGroupTaskCreator { + return &manager.NodeGroupTask{ + ClusterConfig: clusterConfig, + EC2API: awsProvider.EC2(), + IAMAPI: awsProvider.IAM(), + EKSAPI: awsProvider.EKS(), + StackManager: stackManager, + } +} + type runFn func(cmd *cmdutils.Cmd, ng *api.NodeGroup, options *cmdutils.NodeGroupOptions) error func createNodeGroupCmdWithRunFunc(cmd *cmdutils.Cmd, runFunc runFn) { diff --git a/pkg/ctl/get/nodegroup.go b/pkg/ctl/get/nodegroup.go index a203a70827e..ab9fc478f62 100644 --- a/pkg/ctl/get/nodegroup.go +++ b/pkg/ctl/get/nodegroup.go @@ -79,7 +79,7 @@ func doGetNodeGroup(cmd *cmdutils.Cmd, ng *api.NodeGroup, params *getCmdParams) } var summaries []*nodegroup.Summary - manager := nodegroup.New(cfg, ctl, clientSet, instanceSelector) + manager := nodegroup.New(cfg, ctl, clientSet, instanceSelector, nil) if ng.Name == "" { summaries, err = manager.GetAll(ctx) if err != nil { diff --git a/pkg/ctl/scale/nodegroup.go b/pkg/ctl/scale/nodegroup.go index 1126480b57e..738ada877ab 100644 --- a/pkg/ctl/scale/nodegroup.go +++ b/pkg/ctl/scale/nodegroup.go @@ -104,5 +104,5 @@ func scaleNodegroup(cmd *cmdutils.Cmd, ng *api.NodeGroupBase) error { return err } - return nodegroup.New(cfg, ctl, clientSet, instanceSelector).Scale(ctx, ng, cmd.Wait) + return nodegroup.New(cfg, ctl, clientSet, instanceSelector, nil).Scale(ctx, ng, cmd.Wait) } diff --git a/pkg/ctl/update/nodegroup.go b/pkg/ctl/update/nodegroup.go index e4e75f4a049..d80446999f2 100644 --- a/pkg/ctl/update/nodegroup.go +++ b/pkg/ctl/update/nodegroup.go @@ -61,5 +61,5 @@ func updateNodegroup(cmd *cmdutils.Cmd) error { if err != nil { return err } - return nodegroup.New(cmd.ClusterConfig, ctl, nil, instanceSelector).Update(ctx, cmd.Wait) + return nodegroup.New(cmd.ClusterConfig, ctl, nil, instanceSelector, nil).Update(ctx, cmd.Wait) } diff --git a/pkg/ctl/upgrade/nodegroup.go b/pkg/ctl/upgrade/nodegroup.go index 7bf566cf110..5ca3a336368 100644 --- a/pkg/ctl/upgrade/nodegroup.go +++ b/pkg/ctl/upgrade/nodegroup.go @@ -85,5 +85,5 @@ func upgradeNodeGroup(cmd *cmdutils.Cmd, options nodegroup.UpgradeOptions) error if err != nil { return err } - return nodegroup.New(cfg, ctl, clientSet, instanceSelector).Upgrade(ctx, options) + return nodegroup.New(cfg, ctl, clientSet, instanceSelector, nil).Upgrade(ctx, options) }