mirror of
https://github.com/open-cluster-management-io/ocm.git
synced 2026-05-15 21:59:16 +00:00
@@ -51,6 +51,25 @@ func NewSecret(name, namespace string, content string) *corev1.Secret {
|
||||
}
|
||||
}
|
||||
|
||||
func NewUnstructuredSecretBySize(namespace, name string, size int32) *unstructured.Unstructured {
|
||||
data := ""
|
||||
for i := int32(0); i < size; i++ {
|
||||
data += "a"
|
||||
}
|
||||
|
||||
return &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"apiVersion": "v1",
|
||||
"kind": "Secret",
|
||||
"metadata": map[string]interface{}{
|
||||
"namespace": namespace,
|
||||
"name": name,
|
||||
},
|
||||
"data": data,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func NewUnstructuredSecret(namespace, name string, terminated bool, uid string) *unstructured.Unstructured {
|
||||
u := NewUnstructured("v1", "Secret", namespace, name)
|
||||
if terminated {
|
||||
|
||||
@@ -16,7 +16,8 @@ import (
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
var manifestLimit = 10
|
||||
// ManifestLimit is the max size of manifests data which is 50k bytes.
|
||||
const ManifestLimit = 50 * 1024
|
||||
|
||||
// ManifestWorkAdmissionHook will validate the creating/updating manifestwork request.
|
||||
type ManifestWorkAdmissionHook struct{}
|
||||
@@ -90,8 +91,13 @@ func (a *ManifestWorkAdmissionHook) validateManifestWorkObj(requestObj runtime.R
|
||||
return fmt.Errorf("manifests should not be empty")
|
||||
}
|
||||
|
||||
if len(work.Spec.Workload.Manifests) > manifestLimit {
|
||||
return fmt.Errorf("number of manifests should not be larger than %d", manifestLimit)
|
||||
totalSize := 0
|
||||
for _, manifest := range work.Spec.Workload.Manifests {
|
||||
totalSize = totalSize + manifest.Size()
|
||||
}
|
||||
|
||||
if totalSize > ManifestLimit {
|
||||
return fmt.Errorf("the size of manifests is %v bytes which exceeds the 50k limit", totalSize)
|
||||
}
|
||||
|
||||
for _, manifest := range work.Spec.Workload.Manifests {
|
||||
|
||||
@@ -21,7 +21,6 @@ var manifestWorkSchema = metav1.GroupVersionResource{
|
||||
}
|
||||
|
||||
func TestManifestWorkValidate(t *testing.T) {
|
||||
manifestLimit = 3
|
||||
cases := []struct {
|
||||
name string
|
||||
request *admissionv1beta1.AdmissionRequest
|
||||
@@ -153,16 +152,17 @@ func TestManifestWorkValidate(t *testing.T) {
|
||||
UserInfo: authenticationv1.UserInfo{Username: "tester"},
|
||||
},
|
||||
manifests: []*unstructured.Unstructured{
|
||||
spoketesting.NewUnstructured("v1", "Kind", "testns", "test"),
|
||||
spoketesting.NewUnstructured("v1", "Kind", "testns", "test1"),
|
||||
spoketesting.NewUnstructured("v1", "Kind", "testns", "test2"),
|
||||
spoketesting.NewUnstructured("v1", "Kind", "testns", "test3"),
|
||||
spoketesting.NewUnstructuredSecretBySize("test1", "testns", 10*1024),
|
||||
spoketesting.NewUnstructuredSecretBySize("test2", "testns", 10*1024),
|
||||
spoketesting.NewUnstructuredSecretBySize("test3", "testns", 10*1024),
|
||||
spoketesting.NewUnstructuredSecretBySize("test4", "testns", 10*1024),
|
||||
spoketesting.NewUnstructuredSecretBySize("test5", "testns", 10*1024),
|
||||
},
|
||||
expectedResponse: &admissionv1beta1.AdmissionResponse{
|
||||
Allowed: false,
|
||||
Result: &metav1.Status{
|
||||
Status: metav1.StatusFailure, Code: http.StatusBadRequest, Reason: metav1.StatusReasonBadRequest,
|
||||
Message: "number of manifests should not be larger than 3",
|
||||
Message: "the size of manifests is 51685 bytes which exceeds the 50k limit",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -91,5 +91,49 @@ var _ = ginkgo.Describe("ManifestWork admission webhook", func() {
|
||||
admissionName,
|
||||
)))
|
||||
})
|
||||
|
||||
ginkgo.It("Should respond bad request when the size of manifests is more than the limit", func() {
|
||||
manifests := []workapiv1.Manifest{
|
||||
{
|
||||
RawExtension: runtime.RawExtension{
|
||||
Object: newSecretBySize("default", "test1", 10*1024),
|
||||
},
|
||||
},
|
||||
{
|
||||
RawExtension: runtime.RawExtension{
|
||||
Object: newSecretBySize("default", "test2", 10*1024),
|
||||
},
|
||||
},
|
||||
{
|
||||
RawExtension: runtime.RawExtension{
|
||||
Object: newSecretBySize("default", "test3", 10*1024),
|
||||
},
|
||||
},
|
||||
{
|
||||
RawExtension: runtime.RawExtension{
|
||||
Object: newSecretBySize("default", "test4", 10*1024),
|
||||
},
|
||||
},
|
||||
{
|
||||
RawExtension: runtime.RawExtension{
|
||||
Object: newSecretBySize("default", "test5", 10*1024),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
err := retry.RetryOnConflict(retry.DefaultRetry, func() error {
|
||||
work, err = hubWorkClient.WorkV1().ManifestWorks(clusterName).Get(context.Background(), work.Name, metav1.GetOptions{})
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
|
||||
work.Spec.Workload.Manifests = append(work.Spec.Workload.Manifests, manifests...)
|
||||
_, err = hubWorkClient.WorkV1().ManifestWorks(clusterName).Update(context.Background(), work, metav1.UpdateOptions{})
|
||||
return err
|
||||
})
|
||||
|
||||
gomega.Expect(err).To(gomega.HaveOccurred())
|
||||
gomega.Expect(errors.IsBadRequest(err)).Should(gomega.BeTrue())
|
||||
gomega.Expect(err.Error()).Should(gomega.HavePrefix(fmt.Sprintf(
|
||||
"admission webhook \"%s\" denied the request: the size of manifests is", admissionName)))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -541,6 +541,27 @@ func newConfigmap(namespace, name string, data map[string]string, finalizers []s
|
||||
return cm
|
||||
}
|
||||
|
||||
func newSecretBySize(namespace, name string, size int32) *corev1.Secret {
|
||||
data := ""
|
||||
for i := int32(0); i < size; i++ {
|
||||
data += "a"
|
||||
}
|
||||
|
||||
return &corev1.Secret{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "Secret",
|
||||
APIVersion: "v1",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
Namespace: namespace,
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"test": []byte(data),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func haveManifestCondition(conditions []workapiv1.ManifestCondition, expectedType string, expectedStatuses []metav1.ConditionStatus) bool {
|
||||
if len(conditions) != len(expectedStatuses) {
|
||||
return false
|
||||
|
||||
Reference in New Issue
Block a user