-
Notifications
You must be signed in to change notification settings - Fork 25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: restrict the membercluster name length to 63 #946
base: main
Are you sure you want to change the base?
Changes from all commits
d87f701
a159847
6fd1b17
a974e49
caa0566
e15893d
edef393
d318431
fa71b42
df5611f
1ed2227
5755525
43b6b29
21472e3
b46b64f
1a8e07f
f36f2a4
f6d3545
885d9a1
5068e83
6c00ada
20e6fd4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,226 @@ | ||||||
/* | ||||||
Copyright (c) Microsoft Corporation. | ||||||
Licensed under the MIT license. | ||||||
*/ | ||||||
package e2e | ||||||
|
||||||
import ( | ||||||
"errors" | ||||||
"fmt" | ||||||
|
||||||
"k8s.io/apimachinery/pkg/types" | ||||||
|
||||||
. "github.com/onsi/ginkgo/v2" | ||||||
. "github.com/onsi/gomega" | ||||||
|
||||||
"reflect" | ||||||
|
||||||
clusterv1beta1 "go.goms.io/fleet/apis/cluster/v1beta1" | ||||||
rbacv1 "k8s.io/api/rbac/v1" | ||||||
k8serrors "k8s.io/apimachinery/pkg/api/errors" | ||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||||
Comment on lines
+8
to
+21
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. please group the imports correctly |
||||||
) | ||||||
|
||||||
var _ = Describe("Resource validation tests for Member Cluster", func() { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can you split the tests into two, one is to allow create and the other one is to deny to improve the readability. |
||||||
It("should deny creating API with invalid name size", func() { | ||||||
var name = "abcdef-123456789-123456789-123456789-123456789-123456789-123456789-123456789" | ||||||
// Create the API. | ||||||
memberClusterName := &clusterv1beta1.MemberCluster{ | ||||||
ObjectMeta: metav1.ObjectMeta{ | ||||||
Name: name, | ||||||
}, | ||||||
Spec: clusterv1beta1.MemberClusterSpec{ | ||||||
Identity: rbacv1.Subject{ | ||||||
Name: "fleet-member-agent-cluster-1", | ||||||
Kind: "ServiceAccount", | ||||||
Namespace: "fleet-system", | ||||||
APIGroup: "", | ||||||
}, | ||||||
}, | ||||||
} | ||||||
By(fmt.Sprintf("expecting denial of CREATE API %s", name)) | ||||||
err := hubClient.Create(ctx, memberClusterName) | ||||||
var statusErr *k8serrors.StatusError | ||||||
Expect(errors.As(err, &statusErr)).To(BeTrue(), fmt.Sprintf("Create API call produced error %s. Error type wanted is %s.", reflect.TypeOf(err), reflect.TypeOf(&k8serrors.StatusError{}))) | ||||||
Expect(statusErr.Status().Message).Should(ContainSubstring("metadata.name max length is 63")) | ||||||
}) | ||||||
|
||||||
It("should allow creating API with valid name size", func() { | ||||||
var name = "abc-123456789-123456789-123456789-123456789-123456789-123456789" | ||||||
// Create the API. | ||||||
memberClusterName := &clusterv1beta1.MemberCluster{ | ||||||
ObjectMeta: metav1.ObjectMeta{ | ||||||
Name: name, | ||||||
}, | ||||||
Spec: clusterv1beta1.MemberClusterSpec{ | ||||||
Identity: rbacv1.Subject{ | ||||||
Name: "fleet-member-agent-cluster-1", | ||||||
Kind: "ServiceAccount", | ||||||
Namespace: "fleet-system", | ||||||
APIGroup: "", | ||||||
}, | ||||||
}, | ||||||
} | ||||||
Expect(impersonateHubClient.Create(ctx, memberClusterName)).Should(Succeed()) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
plese use hubClient instead and the imerpsonateHubClient is used for other test purpose. |
||||||
Expect(impersonateHubClient.Get(ctx, types.NamespacedName{Name: memberClusterName.Name}, memberClusterName)).Should(Succeed()) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you don't need to validate the get, since the reject should fail the create request. |
||||||
Expect(impersonateHubClient.Delete(ctx, memberClusterName)).Should(Succeed()) | ||||||
ensureMemberClusterAndRelatedResourcesDeletion(name) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This func will delete mc. Please remove line 66. |
||||||
}) | ||||||
|
||||||
It("should deny creating API with invalid name starting with non-alphanumeric character", func() { | ||||||
var name = "-abcdef-123456789-123456789-123456789-123456789-123456789" | ||||||
// Create the API. | ||||||
memberClusterName := &clusterv1beta1.MemberCluster{ | ||||||
ObjectMeta: metav1.ObjectMeta{ | ||||||
Name: name, | ||||||
}, | ||||||
Spec: clusterv1beta1.MemberClusterSpec{ | ||||||
Identity: rbacv1.Subject{ | ||||||
Name: "fleet-member-agent-cluster-1", | ||||||
Kind: "ServiceAccount", | ||||||
Namespace: "fleet-system", | ||||||
APIGroup: "", | ||||||
}, | ||||||
}, | ||||||
} | ||||||
By(fmt.Sprintf("expecting denial of CREATE API %s", name)) | ||||||
err := hubClient.Create(ctx, memberClusterName) | ||||||
var statusErr *k8serrors.StatusError | ||||||
Expect(errors.As(err, &statusErr)).To(BeTrue(), fmt.Sprintf("Create API call produced error %s. Error type wanted is %s.", reflect.TypeOf(err), reflect.TypeOf(&k8serrors.StatusError{}))) | ||||||
Expect(statusErr.Status().Message).Should(ContainSubstring("a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')")) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no need to compare the full error strings and it's not reliable cause the package may change the error message. Checking if have "a lowercase RFC 1123 subdomain" should be fine. |
||||||
}) | ||||||
|
||||||
It("should allow creating API with valid name starting with alphabet character", func() { | ||||||
var name = "abc-123456789" | ||||||
// Create the API. | ||||||
memberClusterName := &clusterv1beta1.MemberCluster{ | ||||||
ObjectMeta: metav1.ObjectMeta{ | ||||||
Name: name, | ||||||
}, | ||||||
Spec: clusterv1beta1.MemberClusterSpec{ | ||||||
Identity: rbacv1.Subject{ | ||||||
Name: "fleet-member-agent-cluster-1", | ||||||
Kind: "ServiceAccount", | ||||||
Namespace: "fleet-system", | ||||||
APIGroup: "", | ||||||
}, | ||||||
}, | ||||||
} | ||||||
Expect(impersonateHubClient.Create(ctx, memberClusterName)).Should(Succeed()) | ||||||
Expect(impersonateHubClient.Get(ctx, types.NamespacedName{Name: memberClusterName.Name}, memberClusterName)).Should(Succeed()) | ||||||
Expect(impersonateHubClient.Delete(ctx, memberClusterName)).Should(Succeed()) | ||||||
ensureMemberClusterAndRelatedResourcesDeletion(name) | ||||||
}) | ||||||
|
||||||
It("should allow creating API with valid name starting with numeric character", func() { | ||||||
var name = "123-123456789" | ||||||
// Create the API. | ||||||
memberClusterName := &clusterv1beta1.MemberCluster{ | ||||||
ObjectMeta: metav1.ObjectMeta{ | ||||||
Name: name, | ||||||
}, | ||||||
Spec: clusterv1beta1.MemberClusterSpec{ | ||||||
Identity: rbacv1.Subject{ | ||||||
Name: "fleet-member-agent-cluster-1", | ||||||
Kind: "ServiceAccount", | ||||||
Namespace: "fleet-system", | ||||||
APIGroup: "", | ||||||
}, | ||||||
}, | ||||||
} | ||||||
Expect(impersonateHubClient.Create(ctx, memberClusterName)).Should(Succeed()) | ||||||
Expect(impersonateHubClient.Get(ctx, types.NamespacedName{Name: memberClusterName.Name}, memberClusterName)).Should(Succeed()) | ||||||
Expect(impersonateHubClient.Delete(ctx, memberClusterName)).Should(Succeed()) | ||||||
ensureMemberClusterAndRelatedResourcesDeletion(name) | ||||||
}) | ||||||
|
||||||
It("should deny creating API with invalid name ending with non-alphanumeric character", func() { | ||||||
var name = "abcdef-123456789-123456789-123456789-123456789-123456789-" | ||||||
// Create the API. | ||||||
memberClusterName := &clusterv1beta1.MemberCluster{ | ||||||
ObjectMeta: metav1.ObjectMeta{ | ||||||
Name: name, | ||||||
}, | ||||||
Spec: clusterv1beta1.MemberClusterSpec{ | ||||||
Identity: rbacv1.Subject{ | ||||||
Name: "fleet-member-agent-cluster-1", | ||||||
Kind: "ServiceAccount", | ||||||
Namespace: "fleet-system", | ||||||
APIGroup: "", | ||||||
}, | ||||||
}, | ||||||
} | ||||||
By(fmt.Sprintf("expecting denial of CREATE API %s", name)) | ||||||
err := hubClient.Create(ctx, memberClusterName) | ||||||
var statusErr *k8serrors.StatusError | ||||||
Expect(errors.As(err, &statusErr)).To(BeTrue(), fmt.Sprintf("Create API call produced error %s. Error type wanted is %s.", reflect.TypeOf(err), reflect.TypeOf(&k8serrors.StatusError{}))) | ||||||
Expect(statusErr.Status().Message).Should(ContainSubstring("a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')")) | ||||||
}) | ||||||
|
||||||
It("should allow creating API with valid name ending with alphabet character", func() { | ||||||
var name = "123456789-abc" | ||||||
// Create the API. | ||||||
memberClusterName := &clusterv1beta1.MemberCluster{ | ||||||
ObjectMeta: metav1.ObjectMeta{ | ||||||
Name: name, | ||||||
}, | ||||||
Spec: clusterv1beta1.MemberClusterSpec{ | ||||||
Identity: rbacv1.Subject{ | ||||||
Name: "fleet-member-agent-cluster-1", | ||||||
Kind: "ServiceAccount", | ||||||
Namespace: "fleet-system", | ||||||
APIGroup: "", | ||||||
}, | ||||||
}, | ||||||
} | ||||||
Expect(impersonateHubClient.Create(ctx, memberClusterName)).Should(Succeed()) | ||||||
Expect(impersonateHubClient.Get(ctx, types.NamespacedName{Name: memberClusterName.Name}, memberClusterName)).Should(Succeed()) | ||||||
Expect(impersonateHubClient.Delete(ctx, memberClusterName)).Should(Succeed()) | ||||||
ensureMemberClusterAndRelatedResourcesDeletion(name) | ||||||
}) | ||||||
|
||||||
It("should allow creating API with valid name ending with numeric character", func() { | ||||||
var name = "123456789-123" | ||||||
// Create the API. | ||||||
memberClusterName := &clusterv1beta1.MemberCluster{ | ||||||
ObjectMeta: metav1.ObjectMeta{ | ||||||
Name: name, | ||||||
}, | ||||||
Spec: clusterv1beta1.MemberClusterSpec{ | ||||||
Identity: rbacv1.Subject{ | ||||||
Name: "fleet-member-agent-cluster-1", | ||||||
Kind: "ServiceAccount", | ||||||
Namespace: "fleet-system", | ||||||
APIGroup: "", | ||||||
}, | ||||||
}, | ||||||
} | ||||||
Expect(impersonateHubClient.Create(ctx, memberClusterName)).Should(Succeed()) | ||||||
Expect(impersonateHubClient.Get(ctx, types.NamespacedName{Name: memberClusterName.Name}, memberClusterName)).Should(Succeed()) | ||||||
Expect(impersonateHubClient.Delete(ctx, memberClusterName)).Should(Succeed()) | ||||||
ensureMemberClusterAndRelatedResourcesDeletion(name) | ||||||
}) | ||||||
|
||||||
It("should deny creating API with invalid name containing character that is not alphanumeric and not -", func() { | ||||||
var name = "a_bcdef-123456789-123456789-123456789-123456789-123456789-123456789-123456789" | ||||||
// Create the API. | ||||||
memberClusterName := &clusterv1beta1.MemberCluster{ | ||||||
ObjectMeta: metav1.ObjectMeta{ | ||||||
Name: name, | ||||||
}, | ||||||
Spec: clusterv1beta1.MemberClusterSpec{ | ||||||
Identity: rbacv1.Subject{ | ||||||
Name: "fleet-member-agent-cluster-1", | ||||||
Kind: "ServiceAccount", | ||||||
Namespace: "fleet-system", | ||||||
APIGroup: "", | ||||||
}, | ||||||
}, | ||||||
} | ||||||
By(fmt.Sprintf("expecting denial of CREATE API %s", name)) | ||||||
err := hubClient.Create(ctx, memberClusterName) | ||||||
var statusErr *k8serrors.StatusError | ||||||
Expect(errors.As(err, &statusErr)).To(BeTrue(), fmt.Sprintf("Create API call produced error %s. Error type wanted is %s.", reflect.TypeOf(err), reflect.TypeOf(&k8serrors.StatusError{}))) | ||||||
Expect(statusErr.Status().Message).Should(ContainSubstring("a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')")) | ||||||
}) | ||||||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please move this to integration test
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hi ryan, will the e2e tests be better here? The invalid MC is rejected by the CRD definition, while "The controller-runtime/pkg/envtest Go library helps write integration tests for your controllers by setting up and starting an instance of etcd and the Kubernetes API server, without kubelet, controller-manager or other components."
The ITs is better to test the controller behavior itself.