Skip to content

Commit 4f5632a

Browse files
Merge pull request #437 from mtulio/e2e-ote-ccm-aws
SPLAT-2672: e2e/ote/ccm-aws: moving OTE binary from CCM-AWS
2 parents fa292f1 + aa217e2 commit 4f5632a

7,830 files changed

Lines changed: 2645670 additions & 2 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.dockerignore

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# IDE
2+
.idea
3+
4+
# Binaries for programs and plugins
5+
*.exe
6+
*.exe~
7+
*.dll
8+
*.so
9+
*.dylib
10+
11+
# Test binary, built with `go test -c`
12+
*.test
13+
14+
# Output of the go coverage tool
15+
*.out
16+
17+
# Directories with variable content
18+
bin/*
19+
config/*
20+
21+
# golangci-lint cache
22+
.cache/*
23+
24+
# Git
25+
.git
26+
.gitignore

Dockerfile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
FROM registry.ci.openshift.org/ocp/builder:rhel-9-golang-1.25-openshift-4.22 AS builder
22
WORKDIR /go/src/github.com/openshift/cluster-cloud-controller-manager-operator
33
COPY . .
4-
RUN make build
4+
RUN make build &&\
5+
gzip /go/src/github.com/openshift/cluster-cloud-controller-manager-operator/bin/cloud-controller-manager-aws-tests-ext
56

67
FROM registry.ci.openshift.org/ocp/4.22:base-rhel9
78
COPY --from=builder /go/src/github.com/openshift/cluster-cloud-controller-manager-operator/bin/cluster-controller-manager-operator .
89
COPY --from=builder /go/src/github.com/openshift/cluster-cloud-controller-manager-operator/bin/config-sync-controllers .
910
COPY --from=builder /go/src/github.com/openshift/cluster-cloud-controller-manager-operator/bin/azure-config-credentials-injector .
1011
COPY --from=builder /go/src/github.com/openshift/cluster-cloud-controller-manager-operator/manifests manifests
12+
COPY --from=builder /go/src/github.com/openshift/cluster-cloud-controller-manager-operator/bin/cloud-controller-manager-aws-tests-ext.gz /usr/bin/cloud-controller-manager-aws-tests-ext.gz
1113

1214
LABEL io.openshift.release.operator true

Makefile

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ unit:
3737
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path --bin-dir $(PROJECT_DIR)/bin --index https://raw.githubusercontent.com/openshift/api/master/envtest-releases.yaml)" ./hack/ci-test.sh
3838

3939
# Build operator binaries
40-
build: operator config-sync-controllers azure-config-credentials-injector
40+
build: operator config-sync-controllers azure-config-credentials-injector cloud-controller-manager-aws-tests-ext
4141

4242
operator:
4343
go build -o bin/cluster-controller-manager-operator cmd/cluster-cloud-controller-manager-operator/main.go
@@ -48,6 +48,14 @@ config-sync-controllers:
4848
azure-config-credentials-injector:
4949
go build -o bin/azure-config-credentials-injector cmd/azure-config-credentials-injector/main.go
5050

51+
cloud-controller-manager-aws-tests-ext:
52+
cd cmd/cloud-controller-manager-aws-tests-ext && \
53+
GO111MODULE=on CGO_ENABLED=0 GOOS=$(GOOS) GOARCH=$(GOARCH) GOPROXY=$(GOPROXY) go build \
54+
-trimpath \
55+
-ldflags="$(LDFLAGS)" \
56+
-o=../../bin/cloud-controller-manager-aws-tests-ext .
57+
58+
5159
# Run against the configured Kubernetes cluster in ~/.kube/config
5260
run: verify manifests
5361
go run cmd/cluster-cloud-controller-manager-operator/main.go
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
package e2e
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"strings"
7+
8+
"github.com/aws/aws-sdk-go-v2/aws"
9+
"github.com/aws/aws-sdk-go-v2/config"
10+
ec2 "github.com/aws/aws-sdk-go-v2/service/ec2"
11+
ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types"
12+
elbv2 "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2"
13+
elbv2types "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2/types"
14+
configv1client "github.com/openshift/client-go/config/clientset/versioned/typed/config/v1"
15+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
16+
"k8s.io/kubernetes/test/e2e/framework"
17+
)
18+
19+
// AWS helpers
20+
21+
// createAWSClientLoadBalancer creates an AWS ELBv2 client using default credentials configured in the environment.
22+
func createAWSClientLoadBalancer(ctx context.Context) (*elbv2.Client, error) {
23+
cfg, err := config.LoadDefaultConfig(ctx)
24+
if err != nil {
25+
return nil, fmt.Errorf("unable to load AWS config: %v", err)
26+
}
27+
return elbv2.NewFromConfig(cfg), nil
28+
}
29+
30+
// getAWSLoadBalancerFromDNSName finds a load balancer by DNS name using the AWS ELBv2 client.
31+
func getAWSLoadBalancerFromDNSName(ctx context.Context, elbClient *elbv2.Client, lbDNSName string) (*elbv2types.LoadBalancer, error) {
32+
var foundLB *elbv2types.LoadBalancer
33+
framework.Logf("describing load balancers with DNS %s", lbDNSName)
34+
35+
paginator := elbv2.NewDescribeLoadBalancersPaginator(elbClient, &elbv2.DescribeLoadBalancersInput{})
36+
for paginator.HasMorePages() {
37+
page, err := paginator.NextPage(ctx)
38+
if err != nil {
39+
return nil, fmt.Errorf("failed to describe load balancers: %v", err)
40+
}
41+
42+
framework.Logf("found %d load balancers in page", len(page.LoadBalancers))
43+
// Search for the load balancer with matching DNS name in this page
44+
for i := range page.LoadBalancers {
45+
if aws.ToString(page.LoadBalancers[i].DNSName) == lbDNSName {
46+
foundLB = &page.LoadBalancers[i]
47+
framework.Logf("found load balancer with DNS %s", aws.ToString(foundLB.DNSName))
48+
break
49+
}
50+
}
51+
if foundLB != nil {
52+
break
53+
}
54+
}
55+
56+
if foundLB == nil {
57+
return nil, fmt.Errorf("no load balancer found with DNS name: %s", lbDNSName)
58+
}
59+
60+
return foundLB, nil
61+
}
62+
63+
// isFeatureEnabled checks if an OpenShift feature gate is enabled by querying the
64+
// FeatureGate resource named "cluster" using the typed OpenShift config API.
65+
//
66+
// This function uses the official OpenShift config/v1 API types for type-safe
67+
// access to feature gate information, providing better performance and maintainability
68+
// compared to dynamic client approaches.
69+
//
70+
// Parameters:
71+
// - ctx: Context for the API call
72+
// - featureName: Name of the feature gate to check (e.g., "AWSServiceLBNetworkSecurityGroup")
73+
//
74+
// Returns:
75+
// - bool: true if the feature is enabled, false if disabled or not found
76+
// - error: error if the API call fails
77+
//
78+
// Note: For HyperShift clusters, this checks the management cluster's feature gates.
79+
// To check hosted cluster feature gates, use the hosted cluster's kubeconfig.
80+
func isFeatureEnabled(ctx context.Context, featureName string) (bool, error) {
81+
// Get the REST config
82+
restConfig, err := framework.LoadConfig()
83+
if err != nil {
84+
return false, fmt.Errorf("failed to load kubeconfig: %v", err)
85+
}
86+
87+
// Create typed config client (more efficient than dynamic client)
88+
configClient, err := configv1client.NewForConfig(restConfig)
89+
if err != nil {
90+
return false, fmt.Errorf("failed to create config client: %v", err)
91+
}
92+
93+
// Get the FeatureGate resource using typed API
94+
featureGate, err := configClient.FeatureGates().Get(ctx, "cluster", metav1.GetOptions{})
95+
if err != nil {
96+
return false, fmt.Errorf("failed to get FeatureGate 'cluster': %v", err)
97+
}
98+
99+
// Iterate through the feature gates status (typed structs)
100+
for _, fg := range featureGate.Status.FeatureGates {
101+
// Check enabled list
102+
for _, enabled := range fg.Enabled {
103+
if string(enabled.Name) == featureName {
104+
framework.Logf("Feature %s is enabled (version %s)", featureName, fg.Version)
105+
return true, nil
106+
}
107+
}
108+
109+
// Check disabled list
110+
for _, disabled := range fg.Disabled {
111+
if string(disabled.Name) == featureName {
112+
framework.Logf("Feature %s is disabled (version %s)", featureName, fg.Version)
113+
return false, nil
114+
}
115+
}
116+
}
117+
118+
// Feature not found in either list
119+
framework.Logf("Feature %s not found in FeatureGate status", featureName)
120+
return false, nil
121+
}
122+
123+
// getAWSClientEC2 creates an AWS EC2 client using default credentials configured in the environment.
124+
func createAWSClientEC2(ctx context.Context) (*ec2.Client, error) {
125+
cfg, err := config.LoadDefaultConfig(ctx)
126+
if err != nil {
127+
return nil, fmt.Errorf("unable to load AWS config: %v", err)
128+
}
129+
return ec2.NewFromConfig(cfg), nil
130+
}
131+
132+
// getAWSSecurityGroup retrieves a security group by ID using the AWS EC2 client.
133+
func getAWSSecurityGroup(ctx context.Context, ec2Client *ec2.Client, sgID string) (*ec2types.SecurityGroup, error) {
134+
framework.Logf("describing security group %s", sgID)
135+
input := &ec2.DescribeSecurityGroupsInput{
136+
GroupIds: []string{sgID},
137+
}
138+
139+
result, err := ec2Client.DescribeSecurityGroups(ctx, input)
140+
if err != nil {
141+
return nil, fmt.Errorf("failed to describe security group %s: %v", sgID, err)
142+
}
143+
144+
if len(result.SecurityGroups) == 0 {
145+
return nil, fmt.Errorf("security group %s not found", sgID)
146+
}
147+
148+
return &result.SecurityGroups[0], nil
149+
}
150+
151+
// getAWSSecurityGroupRules gets the security group rules for the given security group IDs.
152+
func getAWSSecurityGroupRules(ctx context.Context, ec2Client *ec2.Client, groups []string) ([]ec2types.IpPermission, error) {
153+
rules := []ec2types.IpPermission{}
154+
for _, group := range groups {
155+
sg, err := getAWSSecurityGroup(ctx, ec2Client, group)
156+
if err != nil {
157+
return nil, err
158+
}
159+
rules = append(rules, sg.IpPermissions...)
160+
}
161+
return rules, nil
162+
}
163+
164+
// securityGroupExists checks if a security group exists by ID.
165+
// Returns true if it exists, false if it doesn't exist or was deleted.
166+
func securityGroupExists(ctx context.Context, ec2Client *ec2.Client, sgID string) (bool, error) {
167+
framework.Logf("checking if security group %s exists", sgID)
168+
input := &ec2.DescribeSecurityGroupsInput{
169+
GroupIds: []string{sgID},
170+
}
171+
172+
_, err := ec2Client.DescribeSecurityGroups(ctx, input)
173+
if err != nil {
174+
// Check if it's a "not found" error
175+
if ec2IsNotFoundError(err) {
176+
framework.Logf("security group %s does not exist", sgID)
177+
return false, nil
178+
}
179+
return false, fmt.Errorf("failed to check security group %s: %v", sgID, err)
180+
}
181+
182+
framework.Logf("security group %s exists", sgID)
183+
return true, nil
184+
}
185+
186+
// ec2IsNotFoundError checks if an error is an EC2 "not found" error.
187+
func ec2IsNotFoundError(err error) bool {
188+
if err == nil {
189+
return false
190+
}
191+
// Check for common EC2 not found error messages
192+
errMsg := err.Error()
193+
return strings.Contains(errMsg, "InvalidGroup.NotFound") ||
194+
strings.Contains(errMsg, "InvalidGroupId.NotFound") ||
195+
strings.Contains(errMsg, "InvalidGroup.Malformed")
196+
}

0 commit comments

Comments
 (0)