From d99994bec1fa430069c7a4557a4fcd4fe35fd5e5 Mon Sep 17 00:00:00 2001 From: Erik Godding Boye Date: Fri, 7 Jun 2024 07:42:58 +0200 Subject: [PATCH] feat: start serving v2 API --- api/accurate/v2/conversion_test.go | 29 ++++ api/accurate/v2/doc.go | 1 + api/accurate/v2/groupversion_info.go | 2 + api/accurate/v2/subnamespace_conversion.go | 43 +++++ api/accurate/v2/subnamespace_types.go | 1 - api/accurate/v2/zz_generated.conversion.go | 163 ++++++++++++++++++ charts/accurate/templates/generated/crds.yaml | 2 +- cmd/accurate-controller/sub/run.go | 4 + cmd/kubectl-accurate/sub/util.go | 4 + .../accurate.cybozu.com_subnamespaces.yaml | 2 +- controllers/suite_test.go | 3 + e2e/e2e_test.go | 2 +- hooks/subnamespace.go | 3 +- hooks/subnamespace_v2_test.go | 101 +++++++---- hooks/suite_test.go | 3 + 15 files changed, 328 insertions(+), 35 deletions(-) create mode 100644 api/accurate/v2/conversion_test.go create mode 100644 api/accurate/v2/subnamespace_conversion.go create mode 100644 api/accurate/v2/zz_generated.conversion.go diff --git a/api/accurate/v2/conversion_test.go b/api/accurate/v2/conversion_test.go new file mode 100644 index 0000000..3b17501 --- /dev/null +++ b/api/accurate/v2/conversion_test.go @@ -0,0 +1,29 @@ +package v2 + +import ( + "testing" + + accuratev2alpha1 "github.com/cybozu-go/accurate/api/accurate/v2alpha1" + utilconversion "github.com/cybozu-go/accurate/internal/util/conversion" + fuzz "github.com/google/gofuzz" + "k8s.io/apimachinery/pkg/api/apitesting/fuzzer" + runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer" +) + +func TestFuzzyConversion(t *testing.T) { + t.Run("for SubNamespace", utilconversion.FuzzTestFunc(utilconversion.FuzzTestFuncInput{ + Hub: &accuratev2alpha1.SubNamespace{}, + Spoke: &SubNamespace{}, + FuzzerFuncs: []fuzzer.FuzzerFuncs{SubNamespaceStatusFuzzFunc}, + })) +} + +func SubNamespaceStatusFuzzFunc(_ runtimeserializer.CodecFactory) []interface{} { + return []interface{}{ + SubNamespaceStatusFuzzer, + } +} + +func SubNamespaceStatusFuzzer(in *SubNamespace, c fuzz.Continue) { + c.FuzzNoCustom(in) +} diff --git a/api/accurate/v2/doc.go b/api/accurate/v2/doc.go index 9d677ac..6ec0003 100644 --- a/api/accurate/v2/doc.go +++ b/api/accurate/v2/doc.go @@ -1,3 +1,4 @@ // +kubebuilder:object:generate=true // +groupName=accurate.cybozu.com +// +k8s:conversion-gen=github.com/cybozu-go/accurate/api/accurate/v2alpha1 package v2 diff --git a/api/accurate/v2/groupversion_info.go b/api/accurate/v2/groupversion_info.go index 2214c30..db1ad72 100644 --- a/api/accurate/v2/groupversion_info.go +++ b/api/accurate/v2/groupversion_info.go @@ -15,4 +15,6 @@ var ( // AddToScheme adds the types in this group-version to the given scheme. AddToScheme = SchemeBuilder.AddToScheme + + localSchemeBuilder = SchemeBuilder.SchemeBuilder ) diff --git a/api/accurate/v2/subnamespace_conversion.go b/api/accurate/v2/subnamespace_conversion.go new file mode 100644 index 0000000..bb41bde --- /dev/null +++ b/api/accurate/v2/subnamespace_conversion.go @@ -0,0 +1,43 @@ +package v2 + +import ( + accuratev2alpha1 "github.com/cybozu-go/accurate/api/accurate/v2alpha1" + "github.com/go-logr/logr" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/conversion" +) + +// ConvertTo converts this SubNamespace to the Hub version (v2alpha1). +func (src *SubNamespace) ConvertTo(dstRaw conversion.Hub) error { + dst := dstRaw.(*accuratev2alpha1.SubNamespace) + + logger := getConversionLogger(src).WithValues( + "source", SchemeGroupVersion.Version, + "destination", accuratev2alpha1.SchemeGroupVersion.Version, + ) + logger.V(5).Info("converting") + + return Convert_v2_SubNamespace_To_v2alpha1_SubNamespace(src, dst, nil) +} + +// ConvertFrom converts from the Hub version (v2alpha1) to this version. +func (dst *SubNamespace) ConvertFrom(srcRaw conversion.Hub) error { + src := srcRaw.(*accuratev2alpha1.SubNamespace) + + logger := getConversionLogger(src).WithValues( + "source", accuratev2alpha1.SchemeGroupVersion.Version, + "destination", SchemeGroupVersion.Version, + ) + logger.V(5).Info("converting") + + return Convert_v2alpha1_SubNamespace_To_v2_SubNamespace(src, dst, nil) +} + +func getConversionLogger(obj client.Object) logr.Logger { + return ctrl.Log.WithName("conversion").WithValues( + "kind", "SubNamespace", + "namespace", obj.GetNamespace(), + "name", obj.GetName(), + ) +} diff --git a/api/accurate/v2/subnamespace_types.go b/api/accurate/v2/subnamespace_types.go index cc6390c..dcbc804 100644 --- a/api/accurate/v2/subnamespace_types.go +++ b/api/accurate/v2/subnamespace_types.go @@ -32,7 +32,6 @@ type SubNamespaceSpec struct { } //+kubebuilder:object:root=true -//+kubebuilder:unservedversion //+kubebuilder:subresource:status //+genclient diff --git a/api/accurate/v2/zz_generated.conversion.go b/api/accurate/v2/zz_generated.conversion.go new file mode 100644 index 0000000..a575e06 --- /dev/null +++ b/api/accurate/v2/zz_generated.conversion.go @@ -0,0 +1,163 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Code generated by conversion-gen. DO NOT EDIT. + +package v2 + +import ( + unsafe "unsafe" + + v2alpha1 "github.com/cybozu-go/accurate/api/accurate/v2alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + conversion "k8s.io/apimachinery/pkg/conversion" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +func init() { + localSchemeBuilder.Register(RegisterConversions) +} + +// RegisterConversions adds conversion functions to the given scheme. +// Public to allow building arbitrary schemes. +func RegisterConversions(s *runtime.Scheme) error { + if err := s.AddGeneratedConversionFunc((*SubNamespace)(nil), (*v2alpha1.SubNamespace)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v2_SubNamespace_To_v2alpha1_SubNamespace(a.(*SubNamespace), b.(*v2alpha1.SubNamespace), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v2alpha1.SubNamespace)(nil), (*SubNamespace)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v2alpha1_SubNamespace_To_v2_SubNamespace(a.(*v2alpha1.SubNamespace), b.(*SubNamespace), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*SubNamespaceList)(nil), (*v2alpha1.SubNamespaceList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v2_SubNamespaceList_To_v2alpha1_SubNamespaceList(a.(*SubNamespaceList), b.(*v2alpha1.SubNamespaceList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v2alpha1.SubNamespaceList)(nil), (*SubNamespaceList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v2alpha1_SubNamespaceList_To_v2_SubNamespaceList(a.(*v2alpha1.SubNamespaceList), b.(*SubNamespaceList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*SubNamespaceSpec)(nil), (*v2alpha1.SubNamespaceSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v2_SubNamespaceSpec_To_v2alpha1_SubNamespaceSpec(a.(*SubNamespaceSpec), b.(*v2alpha1.SubNamespaceSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v2alpha1.SubNamespaceSpec)(nil), (*SubNamespaceSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v2alpha1_SubNamespaceSpec_To_v2_SubNamespaceSpec(a.(*v2alpha1.SubNamespaceSpec), b.(*SubNamespaceSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*SubNamespaceStatus)(nil), (*v2alpha1.SubNamespaceStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v2_SubNamespaceStatus_To_v2alpha1_SubNamespaceStatus(a.(*SubNamespaceStatus), b.(*v2alpha1.SubNamespaceStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v2alpha1.SubNamespaceStatus)(nil), (*SubNamespaceStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v2alpha1_SubNamespaceStatus_To_v2_SubNamespaceStatus(a.(*v2alpha1.SubNamespaceStatus), b.(*SubNamespaceStatus), scope) + }); err != nil { + return err + } + return nil +} + +func autoConvert_v2_SubNamespace_To_v2alpha1_SubNamespace(in *SubNamespace, out *v2alpha1.SubNamespace, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v2_SubNamespaceSpec_To_v2alpha1_SubNamespaceSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v2_SubNamespaceStatus_To_v2alpha1_SubNamespaceStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v2_SubNamespace_To_v2alpha1_SubNamespace is an autogenerated conversion function. +func Convert_v2_SubNamespace_To_v2alpha1_SubNamespace(in *SubNamespace, out *v2alpha1.SubNamespace, s conversion.Scope) error { + return autoConvert_v2_SubNamespace_To_v2alpha1_SubNamespace(in, out, s) +} + +func autoConvert_v2alpha1_SubNamespace_To_v2_SubNamespace(in *v2alpha1.SubNamespace, out *SubNamespace, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v2alpha1_SubNamespaceSpec_To_v2_SubNamespaceSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v2alpha1_SubNamespaceStatus_To_v2_SubNamespaceStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v2alpha1_SubNamespace_To_v2_SubNamespace is an autogenerated conversion function. +func Convert_v2alpha1_SubNamespace_To_v2_SubNamespace(in *v2alpha1.SubNamespace, out *SubNamespace, s conversion.Scope) error { + return autoConvert_v2alpha1_SubNamespace_To_v2_SubNamespace(in, out, s) +} + +func autoConvert_v2_SubNamespaceList_To_v2alpha1_SubNamespaceList(in *SubNamespaceList, out *v2alpha1.SubNamespaceList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]v2alpha1.SubNamespace)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_v2_SubNamespaceList_To_v2alpha1_SubNamespaceList is an autogenerated conversion function. +func Convert_v2_SubNamespaceList_To_v2alpha1_SubNamespaceList(in *SubNamespaceList, out *v2alpha1.SubNamespaceList, s conversion.Scope) error { + return autoConvert_v2_SubNamespaceList_To_v2alpha1_SubNamespaceList(in, out, s) +} + +func autoConvert_v2alpha1_SubNamespaceList_To_v2_SubNamespaceList(in *v2alpha1.SubNamespaceList, out *SubNamespaceList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]SubNamespace)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_v2alpha1_SubNamespaceList_To_v2_SubNamespaceList is an autogenerated conversion function. +func Convert_v2alpha1_SubNamespaceList_To_v2_SubNamespaceList(in *v2alpha1.SubNamespaceList, out *SubNamespaceList, s conversion.Scope) error { + return autoConvert_v2alpha1_SubNamespaceList_To_v2_SubNamespaceList(in, out, s) +} + +func autoConvert_v2_SubNamespaceSpec_To_v2alpha1_SubNamespaceSpec(in *SubNamespaceSpec, out *v2alpha1.SubNamespaceSpec, s conversion.Scope) error { + out.Labels = *(*map[string]string)(unsafe.Pointer(&in.Labels)) + out.Annotations = *(*map[string]string)(unsafe.Pointer(&in.Annotations)) + return nil +} + +// Convert_v2_SubNamespaceSpec_To_v2alpha1_SubNamespaceSpec is an autogenerated conversion function. +func Convert_v2_SubNamespaceSpec_To_v2alpha1_SubNamespaceSpec(in *SubNamespaceSpec, out *v2alpha1.SubNamespaceSpec, s conversion.Scope) error { + return autoConvert_v2_SubNamespaceSpec_To_v2alpha1_SubNamespaceSpec(in, out, s) +} + +func autoConvert_v2alpha1_SubNamespaceSpec_To_v2_SubNamespaceSpec(in *v2alpha1.SubNamespaceSpec, out *SubNamespaceSpec, s conversion.Scope) error { + out.Labels = *(*map[string]string)(unsafe.Pointer(&in.Labels)) + out.Annotations = *(*map[string]string)(unsafe.Pointer(&in.Annotations)) + return nil +} + +// Convert_v2alpha1_SubNamespaceSpec_To_v2_SubNamespaceSpec is an autogenerated conversion function. +func Convert_v2alpha1_SubNamespaceSpec_To_v2_SubNamespaceSpec(in *v2alpha1.SubNamespaceSpec, out *SubNamespaceSpec, s conversion.Scope) error { + return autoConvert_v2alpha1_SubNamespaceSpec_To_v2_SubNamespaceSpec(in, out, s) +} + +func autoConvert_v2_SubNamespaceStatus_To_v2alpha1_SubNamespaceStatus(in *SubNamespaceStatus, out *v2alpha1.SubNamespaceStatus, s conversion.Scope) error { + out.ObservedGeneration = in.ObservedGeneration + out.Conditions = *(*[]v1.Condition)(unsafe.Pointer(&in.Conditions)) + return nil +} + +// Convert_v2_SubNamespaceStatus_To_v2alpha1_SubNamespaceStatus is an autogenerated conversion function. +func Convert_v2_SubNamespaceStatus_To_v2alpha1_SubNamespaceStatus(in *SubNamespaceStatus, out *v2alpha1.SubNamespaceStatus, s conversion.Scope) error { + return autoConvert_v2_SubNamespaceStatus_To_v2alpha1_SubNamespaceStatus(in, out, s) +} + +func autoConvert_v2alpha1_SubNamespaceStatus_To_v2_SubNamespaceStatus(in *v2alpha1.SubNamespaceStatus, out *SubNamespaceStatus, s conversion.Scope) error { + out.ObservedGeneration = in.ObservedGeneration + out.Conditions = *(*[]v1.Condition)(unsafe.Pointer(&in.Conditions)) + return nil +} + +// Convert_v2alpha1_SubNamespaceStatus_To_v2_SubNamespaceStatus is an autogenerated conversion function. +func Convert_v2alpha1_SubNamespaceStatus_To_v2_SubNamespaceStatus(in *v2alpha1.SubNamespaceStatus, out *SubNamespaceStatus, s conversion.Scope) error { + return autoConvert_v2alpha1_SubNamespaceStatus_To_v2_SubNamespaceStatus(in, out, s) +} diff --git a/charts/accurate/templates/generated/crds.yaml b/charts/accurate/templates/generated/crds.yaml index 72e379f..cda91fa 100644 --- a/charts/accurate/templates/generated/crds.yaml +++ b/charts/accurate/templates/generated/crds.yaml @@ -180,7 +180,7 @@ spec: type: integer type: object type: object - served: false + served: true storage: false subresources: status: {} diff --git a/cmd/accurate-controller/sub/run.go b/cmd/accurate-controller/sub/run.go index 417e9c8..7acccae 100644 --- a/cmd/accurate-controller/sub/run.go +++ b/cmd/accurate-controller/sub/run.go @@ -9,6 +9,7 @@ import ( _ "k8s.io/client-go/plugin/pkg/client/auth" accuratev1 "github.com/cybozu-go/accurate/api/accurate/v1" + accuratev2 "github.com/cybozu-go/accurate/api/accurate/v2" accuratev2alpha1 "github.com/cybozu-go/accurate/api/accurate/v2alpha1" "github.com/cybozu-go/accurate/controllers" "github.com/cybozu-go/accurate/hooks" @@ -44,6 +45,9 @@ func subMain(ns, addr string, port int) error { if err := accuratev2alpha1.AddToScheme(scheme); err != nil { return fmt.Errorf("unable to add Accurate v2alpha1 objects: %w", err) } + if err := accuratev2.AddToScheme(scheme); err != nil { + return fmt.Errorf("unable to add Accurate v2 objects: %w", err) + } cfgData, err := os.ReadFile(options.configFile) if err != nil { diff --git a/cmd/kubectl-accurate/sub/util.go b/cmd/kubectl-accurate/sub/util.go index dba79eb..04f97e9 100644 --- a/cmd/kubectl-accurate/sub/util.go +++ b/cmd/kubectl-accurate/sub/util.go @@ -2,6 +2,7 @@ package sub import ( accuratev1 "github.com/cybozu-go/accurate/api/accurate/v1" + accuratev2 "github.com/cybozu-go/accurate/api/accurate/v2" accuratev2alpha1 "github.com/cybozu-go/accurate/api/accurate/v2alpha1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/cli-runtime/pkg/genericclioptions" @@ -25,6 +26,9 @@ func makeClient(config *genericclioptions.ConfigFlags) (client.Client, error) { if err := accuratev2alpha1.AddToScheme(scheme); err != nil { return nil, err } + if err := accuratev2.AddToScheme(scheme); err != nil { + return nil, err + } return client.New(cfg, client.Options{Scheme: scheme}) } diff --git a/config/crd/bases/accurate.cybozu.com_subnamespaces.yaml b/config/crd/bases/accurate.cybozu.com_subnamespaces.yaml index 75a7fdf..6c44289 100644 --- a/config/crd/bases/accurate.cybozu.com_subnamespaces.yaml +++ b/config/crd/bases/accurate.cybozu.com_subnamespaces.yaml @@ -168,7 +168,7 @@ spec: type: integer type: object type: object - served: false + served: true storage: false subresources: status: {} diff --git a/controllers/suite_test.go b/controllers/suite_test.go index 7f1c45e..ad9df36 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -21,6 +21,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/log/zap" accuratev1 "github.com/cybozu-go/accurate/api/accurate/v1" + accuratev2 "github.com/cybozu-go/accurate/api/accurate/v2" accuratev2alpha1 "github.com/cybozu-go/accurate/api/accurate/v2alpha1" "github.com/cybozu-go/accurate/pkg/config" "github.com/cybozu-go/accurate/pkg/constants" @@ -75,6 +76,8 @@ var _ = BeforeSuite(func() { Expect(err).NotTo(HaveOccurred()) err = accuratev2alpha1.AddToScheme(scheme) Expect(err).NotTo(HaveOccurred()) + err = accuratev2.AddToScheme(scheme) + Expect(err).NotTo(HaveOccurred()) //+kubebuilder:scaffold:scheme diff --git a/e2e/e2e_test.go b/e2e/e2e_test.go index cc1d6a7..33b1ca9 100644 --- a/e2e/e2e_test.go +++ b/e2e/e2e_test.go @@ -246,7 +246,7 @@ var _ = Describe("kubectl accurate", func() { kubectlSafe(nil, "get", "subnamespaces", "-n", "subroot1", "sn1") Eventually(func() string { - out, err := kubectl(nil, "get", "-n", "subroot2", "subnamespaces", "sn1", "-o", "json") + out, err := kubectl(nil, "get", "-n", "subroot2", "subnamespaces.v1.accurate.cybozu.com", "sn1", "-o", "json") if err != nil { return "" } diff --git a/hooks/subnamespace.go b/hooks/subnamespace.go index b669f1e..3ff5e9b 100644 --- a/hooks/subnamespace.go +++ b/hooks/subnamespace.go @@ -8,6 +8,7 @@ import ( "regexp" accuratev1 "github.com/cybozu-go/accurate/api/accurate/v1" + accuratev2 "github.com/cybozu-go/accurate/api/accurate/v2" accuratev2alpha1 "github.com/cybozu-go/accurate/api/accurate/v2alpha1" "github.com/cybozu-go/accurate/pkg/config" "github.com/cybozu-go/accurate/pkg/constants" @@ -140,7 +141,7 @@ func (v *subNamespaceValidator) notMatchingNamingPolicy(ctx context.Context, ns, // SetupSubNamespaceWebhook registers the webhooks for SubNamespace func SetupSubNamespaceWebhook(mgr manager.Manager, dec admission.Decoder, namingPolicyRegexps []config.NamingPolicyRegexp) error { - for _, s := range []runtime.Object{&accuratev1.SubNamespace{}, &accuratev2alpha1.SubNamespace{}} { + for _, s := range []runtime.Object{&accuratev1.SubNamespace{}, &accuratev2alpha1.SubNamespace{}, &accuratev2.SubNamespace{}} { err := ctrl.NewWebhookManagedBy(mgr). For(s). Complete() diff --git a/hooks/subnamespace_v2_test.go b/hooks/subnamespace_v2_test.go index 3f69441..462ae7e 100644 --- a/hooks/subnamespace_v2_test.go +++ b/hooks/subnamespace_v2_test.go @@ -6,6 +6,7 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + accuratev2 "github.com/cybozu-go/accurate/api/accurate/v2" accuratev2alpha1 "github.com/cybozu-go/accurate/api/accurate/v2alpha1" "github.com/cybozu-go/accurate/pkg/constants" corev1 "k8s.io/api/core/v1" @@ -19,41 +20,81 @@ import ( var _ = Describe("SubNamespace webhook", func() { ctx := context.Background() - It("should deny creation of v2 SubNamespace in a namespace that is neither root nor subnamespace", func() { - ns := &corev1.Namespace{} - ns.Name = "v2alpha1-ns1" - Expect(k8sClient.Create(ctx, ns)).To(Succeed()) - - sn := &accuratev2alpha1.SubNamespace{} - sn.Namespace = "v2alpha1-ns1" - sn.Name = "v2alpha1-foo" - err := k8sClient.Create(ctx, sn) - Expect(err).To(HaveOccurred()) - Expect(errors.ReasonForError(err)).Should(Equal(metav1.StatusReasonForbidden)) - }) + Context("v2alpha1", func() { + It("should deny creation of SubNamespace in a namespace that is neither root nor subnamespace", func() { + ns := &corev1.Namespace{} + ns.Name = "v2alpha1-ns1" + Expect(k8sClient.Create(ctx, ns)).To(Succeed()) + + sn := &accuratev2alpha1.SubNamespace{} + sn.Namespace = ns.Name + sn.Name = "v2alpha1-foo" + err := k8sClient.Create(ctx, sn) + Expect(err).To(HaveOccurred()) + Expect(errors.ReasonForError(err)).Should(Equal(metav1.StatusReasonForbidden)) + }) - It("should allow creation of SubNamespace in a root namespace", func() { - ns := &corev1.Namespace{} - ns.Name = "v2alpha1-ns2" - ns.Labels = map[string]string{constants.LabelType: constants.NSTypeRoot} - Expect(k8sClient.Create(ctx, ns)).To(Succeed()) + It("should allow creation of SubNamespace in a root namespace", func() { + ns := &corev1.Namespace{} + ns.Name = "v2alpha1-ns2" + ns.Labels = map[string]string{constants.LabelType: constants.NSTypeRoot} + Expect(k8sClient.Create(ctx, ns)).To(Succeed()) - sn := &accuratev2alpha1.SubNamespace{} - sn.Namespace = "v2alpha1-ns2" - sn.Name = "v2alpha1-foo" - sn.Spec.Labels = map[string]string{"foo": "bar"} - sn.Spec.Annotations = map[string]string{"foo": "bar"} - Expect(k8sClient.Create(ctx, sn)).To(Succeed()) + sn := &accuratev2alpha1.SubNamespace{} + sn.Namespace = ns.Name + sn.Name = "v2alpha1-foo" + sn.Spec.Labels = map[string]string{"foo": "bar"} + sn.Spec.Annotations = map[string]string{"foo": "bar"} + Expect(k8sClient.Create(ctx, sn)).To(Succeed()) - Expect(controllerutil.ContainsFinalizer(sn, constants.Finalizer)).To(BeTrue()) + Expect(controllerutil.ContainsFinalizer(sn, constants.Finalizer)).To(BeTrue()) - // deleting finalizer should succeed - sn.Finalizers = nil - Expect(k8sClient.Update(ctx, sn)).To(Succeed()) + // deleting finalizer should succeed + sn.Finalizers = nil + Expect(k8sClient.Update(ctx, sn)).To(Succeed()) - sn = &accuratev2alpha1.SubNamespace{} - Expect(k8sClient.Get(ctx, client.ObjectKey{Namespace: "v2alpha1-ns2", Name: "v2alpha1-foo"}, sn)).To(Succeed()) - Expect(sn.Finalizers).To(BeEmpty()) + sn = &accuratev2alpha1.SubNamespace{} + Expect(k8sClient.Get(ctx, client.ObjectKey{Namespace: "v2alpha1-ns2", Name: "v2alpha1-foo"}, sn)).To(Succeed()) + Expect(sn.Finalizers).To(BeEmpty()) + }) }) + Context("v2", func() { + It("should deny creation of SubNamespace in a namespace that is neither root nor subnamespace", func() { + ns := &corev1.Namespace{} + ns.Name = "v2-ns1" + Expect(k8sClient.Create(ctx, ns)).To(Succeed()) + + sn := &accuratev2.SubNamespace{} + sn.Namespace = ns.Name + sn.Name = "v2-foo" + err := k8sClient.Create(ctx, sn) + Expect(err).To(HaveOccurred()) + Expect(errors.ReasonForError(err)).Should(Equal(metav1.StatusReasonForbidden)) + }) + + It("should allow creation of SubNamespace in a root namespace", func() { + ns := &corev1.Namespace{} + ns.Name = "v2-ns2" + ns.Labels = map[string]string{constants.LabelType: constants.NSTypeRoot} + Expect(k8sClient.Create(ctx, ns)).To(Succeed()) + + sn := &accuratev2.SubNamespace{} + sn.Namespace = ns.Name + sn.Name = "v2-foo" + sn.Spec.Labels = map[string]string{"foo": "bar"} + sn.Spec.Annotations = map[string]string{"foo": "bar"} + Expect(k8sClient.Create(ctx, sn)).To(Succeed()) + + Expect(controllerutil.ContainsFinalizer(sn, constants.Finalizer)).To(BeTrue()) + + // deleting finalizer should succeed + sn.Finalizers = nil + Expect(k8sClient.Update(ctx, sn)).To(Succeed()) + + sn = &accuratev2.SubNamespace{} + Expect(k8sClient.Get(ctx, client.ObjectKey{Namespace: "v2-ns2", Name: "v2-foo"}, sn)).To(Succeed()) + Expect(sn.Finalizers).To(BeEmpty()) + }) + }) }) diff --git a/hooks/suite_test.go b/hooks/suite_test.go index 9ad4f1c..69af450 100644 --- a/hooks/suite_test.go +++ b/hooks/suite_test.go @@ -16,6 +16,7 @@ import ( admissionv1beta1 "k8s.io/api/admission/v1beta1" //+kubebuilder:scaffold:imports accuratev1 "github.com/cybozu-go/accurate/api/accurate/v1" + accuratev2 "github.com/cybozu-go/accurate/api/accurate/v2" accuratev2alpha1 "github.com/cybozu-go/accurate/api/accurate/v2alpha1" "github.com/cybozu-go/accurate/pkg/config" "github.com/cybozu-go/accurate/pkg/indexing" @@ -58,6 +59,8 @@ var _ = BeforeSuite(func() { Expect(err).NotTo(HaveOccurred()) err = accuratev2alpha1.AddToScheme(scheme) Expect(err).NotTo(HaveOccurred()) + err = accuratev2.AddToScheme(scheme) + Expect(err).NotTo(HaveOccurred()) err = clientgoscheme.AddToScheme(scheme) Expect(err).NotTo(HaveOccurred()) err = admissionv1beta1.AddToScheme(scheme)