Files
open-cluster-management/pkg/webhook/webhook_test.go
2020-07-30 19:31:27 +08:00

183 lines
5.8 KiB
Go

package webhook
import (
"encoding/json"
"net/http"
"reflect"
"testing"
"github.com/open-cluster-management/work/pkg/spoke/spoketesting"
admissionv1beta1 "k8s.io/api/admission/v1beta1"
authenticationv1 "k8s.io/api/authentication/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)
var manifestWorkSchema = metav1.GroupVersionResource{
Group: "work.open-cluster-management.io",
Version: "v1",
Resource: "manifestworks",
}
func TestManagedClusterValidate(t *testing.T) {
manifestLimit = 3
cases := []struct {
name string
request *admissionv1beta1.AdmissionRequest
manifests []*unstructured.Unstructured
expectedResponse *admissionv1beta1.AdmissionResponse
}{
{
name: "validate non-manifestwork request",
request: &admissionv1beta1.AdmissionRequest{
Resource: metav1.GroupVersionResource{
Group: "test.open-cluster-management.io",
Version: "v1",
Resource: "tests",
},
},
manifests: []*unstructured.Unstructured{},
expectedResponse: &admissionv1beta1.AdmissionResponse{
Allowed: true,
},
},
{
name: "validate deleting operation",
request: &admissionv1beta1.AdmissionRequest{
Resource: manifestWorkSchema,
Operation: admissionv1beta1.Delete,
},
manifests: []*unstructured.Unstructured{},
expectedResponse: &admissionv1beta1.AdmissionResponse{
Allowed: true,
},
},
{
name: "validate creating ManaifestWork",
request: &admissionv1beta1.AdmissionRequest{
Resource: manifestWorkSchema,
Operation: admissionv1beta1.Create,
},
manifests: []*unstructured.Unstructured{spoketesting.NewUnstructured("v1", "Kind", "testns", "test")},
expectedResponse: &admissionv1beta1.AdmissionResponse{
Allowed: true,
},
},
{
name: "validate creating ManaifestWork with no manifests",
request: &admissionv1beta1.AdmissionRequest{
Resource: manifestWorkSchema,
Operation: admissionv1beta1.Create,
},
manifests: []*unstructured.Unstructured{},
expectedResponse: &admissionv1beta1.AdmissionResponse{
Allowed: false,
Result: &metav1.Status{
Status: metav1.StatusFailure, Code: http.StatusBadRequest, Reason: metav1.StatusReasonBadRequest,
Message: "manifests should not be empty",
},
},
},
{
name: "validate creating ManaifestWork with no name",
request: &admissionv1beta1.AdmissionRequest{
Resource: manifestWorkSchema,
Operation: admissionv1beta1.Create,
UserInfo: authenticationv1.UserInfo{Username: "tester"},
},
manifests: []*unstructured.Unstructured{
spoketesting.NewUnstructured("v1", "Kind", "testns", "test"),
spoketesting.NewUnstructured("v1", "Kind", "testns", ""),
},
expectedResponse: &admissionv1beta1.AdmissionResponse{
Allowed: false,
Result: &metav1.Status{
Status: metav1.StatusFailure, Code: http.StatusBadRequest, Reason: metav1.StatusReasonBadRequest,
Message: "name must be set in manifest",
},
},
},
{
name: "validate creating ManaifestWork with generate name",
request: &admissionv1beta1.AdmissionRequest{
Resource: manifestWorkSchema,
Operation: admissionv1beta1.Create,
UserInfo: authenticationv1.UserInfo{Username: "tester"},
},
manifests: []*unstructured.Unstructured{
{
Object: map[string]interface{}{
"apiVersion": "v1",
"kind": "kind",
"metadata": map[string]interface{}{
"namespace": "ns1",
"name": "test",
"generateName": "test",
},
},
},
},
expectedResponse: &admissionv1beta1.AdmissionResponse{
Allowed: false,
Result: &metav1.Status{
Status: metav1.StatusFailure, Code: http.StatusBadRequest, Reason: metav1.StatusReasonBadRequest,
Message: "generateName must not be set in manifest",
},
},
},
{
name: "validate updating ManaifestWork with no name",
request: &admissionv1beta1.AdmissionRequest{
Resource: manifestWorkSchema,
Operation: admissionv1beta1.Update,
UserInfo: authenticationv1.UserInfo{Username: "tester"},
},
manifests: []*unstructured.Unstructured{
spoketesting.NewUnstructured("v1", "Kind", "testns", "test"),
spoketesting.NewUnstructured("v1", "Kind", "testns", ""),
},
expectedResponse: &admissionv1beta1.AdmissionResponse{
Allowed: false,
Result: &metav1.Status{
Status: metav1.StatusFailure, Code: http.StatusBadRequest, Reason: metav1.StatusReasonBadRequest,
Message: "name must be set in manifest",
},
},
},
{
name: "validate creating ManaifestWork with manifests more than limit",
request: &admissionv1beta1.AdmissionRequest{
Resource: manifestWorkSchema,
Operation: admissionv1beta1.Create,
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"),
},
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",
},
},
},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
work, _ := spoketesting.NewManifestWork(0, c.manifests...)
c.request.Object.Raw, _ = json.Marshal(work)
admissionHook := &ManifestWorkAdmissionHook{}
actualResponse := admissionHook.Validate(c.request)
if !reflect.DeepEqual(actualResponse, c.expectedResponse) {
t.Errorf("expected %#v but got: %#v", c.expectedResponse.Result, actualResponse.Result)
}
})
}
}