Skip to content

Commit d1fcc96

Browse files
authored
Merge pull request #3343 from faiq/main
🐛 fixes services for EKS clusters
2 parents f68a146 + e0a1821 commit d1fcc96

File tree

10 files changed

+249
-118
lines changed

10 files changed

+249
-118
lines changed

pkg/cloud/services/autoscaling/autoscalinggroup.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,10 +171,10 @@ func (s *Service) CreateASG(scope *scope.MachinePoolScope) (*expinfrav1.AutoScal
171171
// Make sure to use the MachinePoolScope here to get the merger of AWSCluster and AWSMachinePool tags
172172
additionalTags := scope.AdditionalTags()
173173
// Set the cloud provider tag
174-
additionalTags[infrav1.ClusterAWSCloudProviderTagKey(s.scope.Name())] = string(infrav1.ResourceLifecycleOwned)
174+
additionalTags[infrav1.ClusterAWSCloudProviderTagKey(s.scope.KubernetesClusterName())] = string(infrav1.ResourceLifecycleOwned)
175175

176176
input.Tags = infrav1.Build(infrav1.BuildParams{
177-
ClusterName: s.scope.Name(),
177+
ClusterName: s.scope.KubernetesClusterName(),
178178
Lifecycle: infrav1.ResourceLifecycleOwned,
179179
Name: aws.String(scope.Name()),
180180
Role: aws.String("node"),

pkg/cloud/services/ec2/instances.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,14 +123,13 @@ func (s *Service) CreateInstance(scope *scope.MachineScope, userData []byte, use
123123

124124
// Make sure to use the MachineScope here to get the merger of AWSCluster and AWSMachine tags
125125
additionalTags := scope.AdditionalTags()
126-
127126
input.Tags = infrav1.Build(infrav1.BuildParams{
128-
ClusterName: s.scope.Name(),
127+
ClusterName: s.scope.KubernetesClusterName(),
129128
Lifecycle: infrav1.ResourceLifecycleOwned,
130129
Name: aws.String(scope.Name()),
131130
Role: aws.String(scope.Role()),
132131
Additional: additionalTags,
133-
}.WithCloudProvider(s.scope.Name()).WithMachineName(scope.Machine))
132+
}.WithCloudProvider(s.scope.KubernetesClusterName()).WithMachineName(scope.Machine))
134133

135134
var err error
136135
// Pick image from the machine configuration, or use a default one.

test/e2e/data/e2e_conf.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,3 +303,4 @@ intervals:
303303
default/wait-machine-pool-upgrade: [ "50m", "10s" ]
304304
default/wait-create-identity: ["1m", "10s"]
305305
default/wait-job: ["10m", "10s"]
306+
default/wait-create-service: ["60s", "10s"]

test/e2e/data/e2e_eks_conf.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,3 +236,4 @@ intervals:
236236
default/wait-control-plane-upgrade: ["35m", "30s"]
237237
default/wait-addon-status: ["10m", "30s"]
238238
default/wait-create-identity: ["1m", "10s"]
239+
default/wait-create-service: ["60s", "10s"]

test/e2e/shared/services.go

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
//go:build e2e
2+
// +build e2e
3+
4+
/*
5+
Copyright 2021 The Kubernetes Authors.
6+
7+
Licensed under the Apache License, Version 2.0 (the "License");
8+
you may not use this file except in compliance with the License.
9+
You may obtain a copy of the License at
10+
11+
http://www.apache.org/licenses/LICENSE-2.0
12+
13+
Unless required by applicable law or agreed to in writing, software
14+
distributed under the License is distributed on an "AS IS" BASIS,
15+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
See the License for the specific language governing permissions and
17+
limitations under the License.
18+
*/
19+
20+
package shared
21+
22+
import (
23+
"context"
24+
"strings"
25+
"time"
26+
27+
"github.com/aws/aws-sdk-go/aws"
28+
"github.com/aws/aws-sdk-go/aws/awserr"
29+
"github.com/aws/aws-sdk-go/service/elb"
30+
. "github.com/onsi/gomega"
31+
v1 "k8s.io/api/apps/v1"
32+
corev1 "k8s.io/api/core/v1"
33+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
34+
apimachinerytypes "k8s.io/apimachinery/pkg/types"
35+
"k8s.io/utils/pointer"
36+
crclient "sigs.k8s.io/controller-runtime/pkg/client"
37+
)
38+
39+
func CreateLBService(e2eCtx *E2EContext, svcNamespace string, svcName string, k8sclient crclient.Client) string {
40+
Byf("Creating service of type Load Balancer with name: %s under namespace: %s", svcName, svcNamespace)
41+
svcSpec := corev1.ServiceSpec{
42+
Type: corev1.ServiceTypeLoadBalancer,
43+
Ports: []corev1.ServicePort{
44+
{
45+
Port: 80,
46+
Protocol: corev1.ProtocolTCP,
47+
},
48+
},
49+
Selector: map[string]string{
50+
"app": "nginx",
51+
},
52+
}
53+
CreateService(svcName, svcNamespace, nil, svcSpec, k8sclient)
54+
elbName := ""
55+
Eventually(func() bool {
56+
svcCreated := &corev1.Service{}
57+
err := k8sclient.Get(context.TODO(), apimachinerytypes.NamespacedName{Namespace: svcNamespace, Name: svcName}, svcCreated)
58+
Expect(err).NotTo(HaveOccurred())
59+
if lbs := len(svcCreated.Status.LoadBalancer.Ingress); lbs > 0 {
60+
ingressHostname := svcCreated.Status.LoadBalancer.Ingress[0].Hostname
61+
elbName = strings.Split(ingressHostname, "-")[0]
62+
return true
63+
}
64+
return false
65+
}, e2eCtx.E2EConfig.GetIntervals("", "wait-create-service")...).Should(BeTrue())
66+
Byf("Created Load Balancer service and ELB name is: %s", elbName)
67+
return elbName
68+
}
69+
70+
func DeleteLBService(svcNamespace string, svcName string, k8sclient crclient.Client) {
71+
svcSpec := corev1.ServiceSpec{
72+
Type: corev1.ServiceTypeLoadBalancer,
73+
Ports: []corev1.ServicePort{
74+
{
75+
Port: 80,
76+
Protocol: corev1.ProtocolTCP,
77+
},
78+
},
79+
Selector: map[string]string{
80+
"app": "nginx",
81+
},
82+
}
83+
deleteService(svcName, svcNamespace, nil, svcSpec, k8sclient)
84+
}
85+
86+
func CreateService(svcName string, svcNamespace string, labels map[string]string, serviceSpec corev1.ServiceSpec, k8sClient crclient.Client) {
87+
svcToCreate := corev1.Service{
88+
ObjectMeta: metav1.ObjectMeta{
89+
Namespace: svcNamespace,
90+
Name: svcName,
91+
},
92+
Spec: serviceSpec,
93+
}
94+
if len(labels) > 0 {
95+
svcToCreate.ObjectMeta.Labels = labels
96+
}
97+
Expect(k8sClient.Create(context.TODO(), &svcToCreate)).NotTo(HaveOccurred())
98+
}
99+
100+
func CreateDefaultNginxDeployment(deploymentNamespace, deploymentName string, k8sClient crclient.Client) {
101+
Byf("Creating Deployment with name: %s under namespace: %s", deploymentName, deploymentNamespace)
102+
deployment := defaultNginxDeployment(deploymentName, deploymentNamespace)
103+
Expect(k8sClient.Create(context.TODO(), &deployment)).NotTo(HaveOccurred())
104+
Eventually(func() bool {
105+
getDeployment := &v1.Deployment{}
106+
err := k8sClient.Get(context.TODO(), apimachinerytypes.NamespacedName{Namespace: deploymentNamespace, Name: deploymentName}, getDeployment)
107+
Expect(err).NotTo(HaveOccurred())
108+
for _, c := range getDeployment.Status.Conditions {
109+
if c.Type == v1.DeploymentAvailable && c.Status == corev1.ConditionTrue {
110+
return getDeployment.Status.AvailableReplicas > 0
111+
}
112+
}
113+
return false
114+
}, 60*time.Second).Should(BeTrue())
115+
}
116+
117+
func DeleteDefaultNginxDeployment(deploymentNamespace, deploymentName string, k8sClient crclient.Client) {
118+
Byf("Deleting Deployment with name: %s under namespace: %s", deploymentName, deploymentNamespace)
119+
deployment := defaultNginxDeployment(deploymentName, deploymentNamespace)
120+
Expect(k8sClient.Delete(context.TODO(), &deployment)).NotTo(HaveOccurred())
121+
}
122+
123+
func deleteService(svcName, svcNamespace string, labels map[string]string, serviceSpec corev1.ServiceSpec, k8sClient crclient.Client) {
124+
svcToDelete := corev1.Service{
125+
ObjectMeta: metav1.ObjectMeta{
126+
Namespace: svcNamespace,
127+
Name: svcName,
128+
},
129+
Spec: serviceSpec,
130+
}
131+
if len(labels) > 0 {
132+
svcToDelete.ObjectMeta.Labels = labels
133+
}
134+
Expect(k8sClient.Delete(context.TODO(), &svcToDelete)).NotTo(HaveOccurred())
135+
}
136+
137+
func VerifyElbExists(e2eCtx *E2EContext, elbName string, exists bool) {
138+
Byf("Verifying ELB with name %s present and instances are attached", elbName)
139+
input := &elb.DescribeLoadBalancersInput{
140+
LoadBalancerNames: []*string{
141+
aws.String(elbName),
142+
},
143+
}
144+
elbClient := elb.New(e2eCtx.AWSSession)
145+
elbsOutput, err := elbClient.DescribeLoadBalancers(input)
146+
if exists {
147+
Expect(err).NotTo(HaveOccurred())
148+
Expect(len(elbsOutput.LoadBalancerDescriptions)).To(Equal(1))
149+
Expect(len(elbsOutput.LoadBalancerDescriptions[0].Instances)).Should(BeNumerically(">=", 1))
150+
Byf("ELB with name %s exists", elbName)
151+
} else {
152+
aerr, ok := err.(awserr.Error)
153+
Expect(ok).To(BeTrue())
154+
Expect(aerr.Code()).To(Equal(elb.ErrCodeAccessPointNotFoundException))
155+
Byf("ELB with name %s doesn't exists", elbName)
156+
}
157+
}
158+
159+
func defaultNginxDeployment(deploymentName, deploymentNamespace string) v1.Deployment {
160+
selector, err := metav1.ParseToLabelSelector("app=nginx")
161+
Expect(err).To(BeNil())
162+
deploymentSpec := v1.DeploymentSpec{
163+
Selector: selector,
164+
Replicas: pointer.Int32(1),
165+
Template: corev1.PodTemplateSpec{
166+
ObjectMeta: metav1.ObjectMeta{
167+
Name: "nginx",
168+
Labels: map[string]string{
169+
"app": "nginx",
170+
},
171+
},
172+
Spec: corev1.PodSpec{
173+
Containers: []corev1.Container{
174+
{
175+
Name: "nginx",
176+
Image: "k8s.gcr.io/nginx-slim:0.8",
177+
Ports: []corev1.ContainerPort{{
178+
Name: "nginx-port", ContainerPort: int32(80),
179+
}},
180+
},
181+
},
182+
},
183+
},
184+
}
185+
return v1.Deployment{
186+
ObjectMeta: metav1.ObjectMeta{
187+
Namespace: deploymentNamespace,
188+
Name: deploymentName,
189+
Labels: map[string]string{
190+
"app": "nginx",
191+
},
192+
},
193+
Spec: deploymentSpec,
194+
}
195+
}

test/e2e/suites/managed/eks_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ var _ = ginkgo.Describe("[managed] [general] EKS cluster tests", func() {
110110
AWSSession: e2eCtx.BootstrapUserAWSSession,
111111
Namespace: namespace,
112112
ClusterName: clusterName,
113+
IncludeLBTest: true,
113114
Replicas: 1,
114115
Cleanup: true,
115116
}
@@ -124,6 +125,7 @@ var _ = ginkgo.Describe("[managed] [general] EKS cluster tests", func() {
124125
AWSSession: e2eCtx.BootstrapUserAWSSession,
125126
Namespace: namespace,
126127
ClusterName: clusterName,
128+
IncludeLBTest: true,
127129
IncludeScaling: true,
128130
Cleanup: true,
129131
}
@@ -136,7 +138,6 @@ var _ = ginkgo.Describe("[managed] [general] EKS cluster tests", func() {
136138
Name: clusterName,
137139
})
138140
Expect(cluster).NotTo(BeNil(), "couldn't find CAPI cluster")
139-
140141
framework.DeleteCluster(ctx, framework.DeleteClusterInput{
141142
Deleter: e2eCtx.Environment.BootstrapClusterProxy.GetClient(),
142143
Cluster: cluster,

test/e2e/suites/managed/machine_deployment.go

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,17 @@ import (
2323
"context"
2424

2525
"github.com/aws/aws-sdk-go/aws/client"
26+
"github.com/onsi/ginkgo"
2627
. "github.com/onsi/gomega"
2728
corev1 "k8s.io/api/core/v1"
29+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2830
"k8s.io/utils/pointer"
2931

3032
"sigs.k8s.io/cluster-api-provider-aws/test/e2e/shared"
3133
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
3234
"sigs.k8s.io/cluster-api/test/framework"
3335
"sigs.k8s.io/cluster-api/test/framework/clusterctl"
36+
"sigs.k8s.io/cluster-api/util"
3437
)
3538

3639
// MachineDeploymentSpecInput is the input for MachineDeploymentSpec.
@@ -42,6 +45,7 @@ type MachineDeploymentSpecInput struct {
4245
Namespace *corev1.Namespace
4346
Replicas int64
4447
ClusterName string
48+
IncludeLBTest bool
4549
Cleanup bool
4650
}
4751

@@ -92,17 +96,26 @@ func MachineDeploymentSpec(ctx context.Context, inputGetter func() MachineDeploy
9296
StatusChecks: statusChecks,
9397
}
9498
framework.WaitForMachineStatusCheck(ctx, machineStatusInput, input.E2EConfig.GetIntervals("", "wait-machine-status")...)
99+
if input.IncludeLBTest {
100+
clusterClient := e2eCtx.Environment.BootstrapClusterProxy.GetWorkloadCluster(ctx, input.Namespace.Name, input.ClusterName).GetClient()
101+
ginkgo.By("Creating the Nginx deployment")
102+
deploymentName := "test-deployment-" + util.RandomString(6)
103+
shared.CreateDefaultNginxDeployment(metav1.NamespaceDefault, deploymentName, clusterClient)
104+
ginkgo.By("Creating the LB service")
105+
lbServiceName := "test-svc-" + util.RandomString(6)
106+
elbName := shared.CreateLBService(e2eCtx, metav1.NamespaceDefault, lbServiceName, clusterClient)
107+
shared.VerifyElbExists(e2eCtx, elbName, true)
108+
ginkgo.By("Deleting the Nginx deployment")
109+
shared.DeleteDefaultNginxDeployment(metav1.NamespaceDefault, deploymentName, clusterClient)
110+
ginkgo.By("Deleting LB service")
111+
shared.DeleteLBService(metav1.NamespaceDefault, lbServiceName, clusterClient)
112+
}
95113

96114
if input.Cleanup {
97115
deleteMachineDeployment(ctx, deleteMachineDeploymentInput{
98116
Deleter: input.BootstrapClusterProxy.GetClient(),
99117
MachineDeployment: md[0],
100118
})
101-
// deleteMachine(ctx, deleteMachineInput{
102-
// Deleter: input.BootstrapClusterProxy.GetClient(),
103-
// Machine: &workerMachines[0],
104-
// })
105-
106119
waitForMachineDeploymentDeleted(ctx, waitForMachineDeploymentDeletedInput{
107120
Getter: input.BootstrapClusterProxy.GetClient(),
108121
MachineDeployment: md[0],

test/e2e/suites/managed/machine_pool.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,13 @@ import (
2626
"github.com/onsi/ginkgo"
2727
. "github.com/onsi/gomega"
2828
corev1 "k8s.io/api/core/v1"
29+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2930
"k8s.io/utils/pointer"
3031

3132
"sigs.k8s.io/cluster-api-provider-aws/test/e2e/shared"
3233
"sigs.k8s.io/cluster-api/test/framework"
3334
"sigs.k8s.io/cluster-api/test/framework/clusterctl"
35+
"sigs.k8s.io/cluster-api/util"
3436
)
3537

3638
// ManagedMachinePoolSpecInput is the input for ManagedMachinePoolSpec.
@@ -42,6 +44,7 @@ type ManagedMachinePoolSpecInput struct {
4244
Namespace *corev1.Namespace
4345
ClusterName string
4446
IncludeScaling bool
47+
IncludeLBTest bool
4548
Cleanup bool
4649
}
4750

@@ -103,6 +106,21 @@ func ManagedMachinePoolSpec(ctx context.Context, inputGetter func() ManagedMachi
103106
})
104107
}
105108

109+
if input.IncludeLBTest {
110+
clusterClient := e2eCtx.Environment.BootstrapClusterProxy.GetWorkloadCluster(ctx, input.Namespace.Name, input.ClusterName).GetClient()
111+
ginkgo.By("Creating the Nginx deployment")
112+
deploymentName := "test-deployment-" + util.RandomString(6)
113+
shared.CreateDefaultNginxDeployment(metav1.NamespaceDefault, deploymentName, clusterClient)
114+
ginkgo.By("Creating the LB service")
115+
lbServiceName := "test-svc-" + util.RandomString(6)
116+
elbName := shared.CreateLBService(e2eCtx, metav1.NamespaceDefault, lbServiceName, clusterClient)
117+
shared.VerifyElbExists(e2eCtx, elbName, true)
118+
ginkgo.By("Deleting the Nginx deployment")
119+
shared.DeleteDefaultNginxDeployment(metav1.NamespaceDefault, deploymentName, clusterClient)
120+
ginkgo.By("Deleting LB service")
121+
shared.DeleteLBService(metav1.NamespaceDefault, lbServiceName, clusterClient)
122+
}
123+
106124
if input.Cleanup {
107125
deleteMachinePool(ctx, deleteMachinePoolInput{
108126
Deleter: input.BootstrapClusterProxy.GetClient(),

0 commit comments

Comments
 (0)