3
3
package karpenter
4
4
5
5
import (
6
+ "bytes"
7
+ "context"
8
+ "encoding/json"
6
9
"fmt"
7
10
"testing"
8
11
"time"
9
12
13
+ "github.com/aws/aws-sdk-go-v2/aws"
14
+ "github.com/aws/aws-sdk-go-v2/config"
15
+ cfn "github.com/aws/aws-sdk-go-v2/service/cloudformation"
16
+ awsec2 "github.com/aws/aws-sdk-go-v2/service/ec2"
17
+
10
18
. "github.com/onsi/ginkgo/v2"
11
19
. "github.com/onsi/gomega"
12
20
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -16,6 +24,7 @@ import (
16
24
clusterutils "github.com/weaveworks/eksctl/integration/utilities/cluster"
17
25
"github.com/weaveworks/eksctl/integration/utilities/kube"
18
26
api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5"
27
+ "github.com/weaveworks/eksctl/pkg/cfn/outputs"
19
28
"github.com/weaveworks/eksctl/pkg/karpenter"
20
29
"github.com/weaveworks/eksctl/pkg/testutils"
21
30
)
@@ -27,13 +36,20 @@ func init() {
27
36
if err := api .Register (); err != nil {
28
37
panic (fmt .Errorf ("unexpected error registering API scheme: %w" , err ))
29
38
}
30
- params = tests .NewParams ("" )
39
+ params = tests .NewParams ("karpenter " )
31
40
}
32
41
33
42
func TestKarpenter (t * testing.T ) {
34
43
testutils .RegisterAndRun (t )
35
44
}
36
45
46
+ // NewConfig creates an AWS config for the given region
47
+ func NewConfig (region string ) aws.Config {
48
+ cfg , err := config .LoadDefaultConfig (context .Background (), config .WithRegion (region ))
49
+ Expect (err ).NotTo (HaveOccurred ())
50
+ return cfg
51
+ }
52
+
37
53
var _ = Describe ("(Integration) Karpenter" , func () {
38
54
var (
39
55
clusterName string
@@ -51,10 +67,117 @@ var _ = Describe("(Integration) Karpenter", func() {
51
67
Expect (cmd ).To (RunSuccessfully ())
52
68
})
53
69
54
- Context ("Creating a cluster with Karpenter" , func () {
70
+ Context ("Creating a cluster with Karpenter and security group tagging" , func () {
71
+ params .LogStacksEventsOnFailure ()
72
+
73
+ It ("should deploy Karpenter successfully and tag security group with karpenter.sh/discovery" , func () {
74
+ By ("creating a cluster with both Karpenter enabled and karpenter.sh/discovery in metadata.tags" )
75
+
76
+ clusterConfig := & api.ClusterConfig {
77
+ TypeMeta : metav1.TypeMeta {
78
+ Kind : api .ClusterConfigKind ,
79
+ APIVersion : api .SchemeGroupVersion .String (),
80
+ },
81
+ Metadata : & api.ClusterMeta {
82
+ Name : clusterName ,
83
+ Region : params .Region ,
84
+ Version : api .DefaultVersion ,
85
+ Tags : map [string ]string {
86
+ "karpenter.sh/discovery" : clusterName ,
87
+ },
88
+ },
89
+ IAM : & api.ClusterIAM {
90
+ WithOIDC : api .Enabled (),
91
+ },
92
+ Karpenter : & api.Karpenter {
93
+ Version : "1.6.3" ,
94
+ },
95
+ ManagedNodeGroups : []* api.ManagedNodeGroup {
96
+ {
97
+ NodeGroupBase : & api.NodeGroupBase {
98
+ Name : "managed-ng-1" ,
99
+ ScalingConfig : & api.ScalingConfig {
100
+ MinSize : aws .Int (1 ),
101
+ MaxSize : aws .Int (2 ),
102
+ DesiredCapacity : aws .Int (1 ),
103
+ },
104
+ },
105
+ },
106
+ },
107
+ }
108
+
109
+ data , err := json .Marshal (clusterConfig )
110
+ Expect (err ).NotTo (HaveOccurred ())
111
+
112
+ cmd := params .EksctlCreateCmd .
113
+ WithArgs (
114
+ "cluster" ,
115
+ "--config-file=-" ,
116
+ "--verbose=4" ,
117
+ "--kubeconfig" , params .KubeconfigPath ,
118
+ ).
119
+ WithoutArg ("--region" , params .Region ).
120
+ WithStdin (bytes .NewReader (data ))
121
+ Expect (cmd ).To (RunSuccessfully ())
122
+
123
+ By ("verifying Karpenter pods are healthy" )
124
+ kubeTest , err := kube .NewTest (params .KubeconfigPath )
125
+ Expect (err ).NotTo (HaveOccurred ())
126
+
127
+ // Check that Karpenter webhook pod is ready
128
+ Expect (kubeTest .WaitForPodsReady (karpenter .DefaultNamespace , metav1.ListOptions {
129
+ LabelSelector : "app.kubernetes.io/instance=karpenter" ,
130
+ }, 1 , 10 * time .Minute )).To (Succeed ())
131
+
132
+ By ("verifying the cluster shared node security group has karpenter.sh/discovery tags" )
133
+ config := NewConfig (params .Region )
134
+ cfnSession := cfn .NewFromConfig (config )
135
+ ec2Session := awsec2 .NewFromConfig (config )
136
+
137
+ // Get the cluster stack to find the node security group
138
+ describeStackOut , err := cfnSession .DescribeStacks (context .Background (), & cfn.DescribeStacksInput {
139
+ StackName : aws .String (fmt .Sprintf ("eksctl-%s-cluster" , clusterName )),
140
+ })
141
+ Expect (err ).NotTo (HaveOccurred ())
142
+
143
+ var nodeSecurityGroupID string
144
+ for _ , output := range describeStackOut .Stacks [0 ].Outputs {
145
+ if * output .OutputKey == outputs .ClusterSharedNodeSecurityGroup {
146
+ nodeSecurityGroupID = * output .OutputValue
147
+ break
148
+ }
149
+ }
150
+ Expect (nodeSecurityGroupID ).NotTo (BeEmpty (), "ClusterSharedNodeSecurityGroup should be found in stack outputs" )
151
+
152
+ // Verify the security group has the expected karpenter.sh/discovery tag
153
+ sgOutput , err := ec2Session .DescribeSecurityGroups (context .Background (), & awsec2.DescribeSecurityGroupsInput {
154
+ GroupIds : []string {nodeSecurityGroupID },
155
+ })
156
+ Expect (err ).NotTo (HaveOccurred ())
157
+ Expect (sgOutput .SecurityGroups ).To (HaveLen (1 ))
158
+
159
+ securityGroup := sgOutput .SecurityGroups [0 ]
160
+ var foundKarpenterTag bool
161
+ var karpenterTagValue string
162
+
163
+ for _ , tag := range securityGroup .Tags {
164
+ if * tag .Key == "karpenter.sh/discovery" {
165
+ foundKarpenterTag = true
166
+ karpenterTagValue = * tag .Value
167
+ break
168
+ }
169
+ }
170
+
171
+ Expect (foundKarpenterTag ).To (BeTrue (), "Security group should have karpenter.sh/discovery tag" )
172
+ Expect (karpenterTagValue ).To (Equal (clusterName ), "karpenter.sh/discovery tag value should match cluster name" )
173
+ })
174
+
175
+ })
176
+
177
+ Context ("Creating a cluster with Karpenter without any tag" , func () {
55
178
params .LogStacksEventsOnFailure ()
56
179
57
- It ("should support karpenter" , func () {
180
+ It ("should support karpenter and verify security group is NOT tagged when metadata tag is missing " , func () {
58
181
cmd := params .EksctlCreateCmd .
59
182
WithArgs (
60
183
"cluster" ,
@@ -66,12 +189,55 @@ var _ = Describe("(Integration) Karpenter", func() {
66
189
WithStdin (clusterutils .ReaderFromFile (clusterName , params .Region , "testdata/cluster-config.yaml" ))
67
190
Expect (cmd ).To (RunSuccessfully ())
68
191
192
+ By ("verifying Karpenter pods are healthy" )
69
193
kubeTest , err := kube .NewTest (params .KubeconfigPath )
70
194
Expect (err ).NotTo (HaveOccurred ())
71
195
// Check webhook pod
72
196
Expect (kubeTest .WaitForPodsReady (karpenter .DefaultNamespace , metav1.ListOptions {
73
197
LabelSelector : "app.kubernetes.io/instance=karpenter" ,
74
198
}, 1 , 10 * time .Minute )).To (Succeed ())
199
+
200
+ By ("verifying the cluster shared node security group does NOT have karpenter.sh/discovery tags" )
201
+ config := NewConfig (params .Region )
202
+ cfnSession := cfn .NewFromConfig (config )
203
+ ec2Session := awsec2 .NewFromConfig (config )
204
+
205
+ // Get the cluster stack to find the node security group
206
+ describeStackOut , err := cfnSession .DescribeStacks (context .Background (), & cfn.DescribeStacksInput {
207
+ StackName : aws .String (fmt .Sprintf ("eksctl-%s-cluster" , clusterName )),
208
+ })
209
+ Expect (err ).NotTo (HaveOccurred ())
210
+
211
+ var nodeSecurityGroupID string
212
+ for _ , output := range describeStackOut .Stacks [0 ].Outputs {
213
+ if * output .OutputKey == outputs .ClusterSharedNodeSecurityGroup {
214
+ nodeSecurityGroupID = * output .OutputValue
215
+ break
216
+ }
217
+ }
218
+ Expect (nodeSecurityGroupID ).NotTo (BeEmpty (), "ClusterSharedNodeSecurityGroup should be found in stack outputs" )
219
+
220
+ // Verify the security group does NOT have the karpenter.sh/discovery tag
221
+ sgOutput , err := ec2Session .DescribeSecurityGroups (context .Background (), & awsec2.DescribeSecurityGroupsInput {
222
+ GroupIds : []string {nodeSecurityGroupID },
223
+ })
224
+ Expect (err ).NotTo (HaveOccurred ())
225
+ Expect (sgOutput .SecurityGroups ).To (HaveLen (1 ))
226
+
227
+ securityGroup := sgOutput .SecurityGroups [0 ]
228
+ var foundKarpenterTag bool
229
+
230
+ for _ , tag := range securityGroup .Tags {
231
+ if * tag .Key == "karpenter.sh/discovery" {
232
+ foundKarpenterTag = true
233
+ break
234
+ }
235
+ }
236
+
237
+ Expect (foundKarpenterTag ).To (BeFalse (), "Security group should NOT have karpenter.sh/discovery tag when only Karpenter is enabled without metadata tag" )
238
+
239
+ GinkgoWriter .Printf ("Successfully verified Karpenter deployment without security group tagging\n " )
240
+ GinkgoWriter .Printf ("Karpenter pods are healthy but security group %s does NOT have karpenter.sh/discovery tag\n " , nodeSecurityGroupID )
75
241
})
76
242
})
77
243
})
0 commit comments