From b4e2e9a28b2be149f08ee3a5a67e9e1d43d45fe6 Mon Sep 17 00:00:00 2001 From: Lukasz Zajaczkowski Date: Wed, 2 Oct 2024 14:15:25 +0200 Subject: [PATCH] test: add controllers unit tests (#284) * add controllers unit tests * change test name * add restore unit tests * use default scope --- internal/controller/backup_controller_test.go | 73 ++ .../controller/constraint_controller_test.go | 88 +++ internal/controller/crd_controller_test.go | 124 ++++ .../controller/customhealth_controller.go | 2 +- .../customhealth_controller_test.go | 7 - internal/controller/customhealth_scope.go | 49 -- internal/controller/job_scope.go | 41 -- .../controller/pipelinegate_controller.go | 4 +- internal/controller/pipelinegate_scope.go | 42 -- .../controller/restore_controller_test.go | 79 +++ internal/controller/suite_test.go | 20 +- ...intpodstatus-customresourcedefinition.yaml | 80 +++ ...tes.gatekeeper.sh_constrainttemplates.yaml | 406 +++++++++++ test/crd/velero.io_backups.yaml | 660 ++++++++++++++++++ test/crd/velero.io_restores.yaml | 556 +++++++++++++++ 15 files changed, 2087 insertions(+), 144 deletions(-) create mode 100644 internal/controller/backup_controller_test.go create mode 100644 internal/controller/constraint_controller_test.go create mode 100644 internal/controller/crd_controller_test.go delete mode 100644 internal/controller/customhealth_scope.go delete mode 100644 internal/controller/job_scope.go delete mode 100644 internal/controller/pipelinegate_scope.go create mode 100644 internal/controller/restore_controller_test.go create mode 100644 test/crd/constraintpodstatus-customresourcedefinition.yaml create mode 100644 test/crd/templates.gatekeeper.sh_constrainttemplates.yaml create mode 100644 test/crd/velero.io_backups.yaml create mode 100644 test/crd/velero.io_restores.yaml diff --git a/internal/controller/backup_controller_test.go b/internal/controller/backup_controller_test.go new file mode 100644 index 00000000..c2195a65 --- /dev/null +++ b/internal/controller/backup_controller_test.go @@ -0,0 +1,73 @@ +package controller + +import ( + "context" + + "github.com/pluralsh/deployment-operator/pkg/test/mocks" + "github.com/stretchr/testify/mock" + velerov1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/reconcile" +) + +var _ = Describe("Backup Controller", Ordered, func() { + Context("When reconciling a resource", func() { + const ( + resourceName = "default" + namespace = "default" + ) + + ctx := context.Background() + + typeNamespacedName := types.NamespacedName{ + Name: resourceName, + Namespace: "default", + } + + backup := &velerov1.Backup{} + + BeforeAll(func() { + By("creating the custom resource for the Kind Backup") + err := kClient.Get(ctx, typeNamespacedName, backup) + if err != nil && errors.IsNotFound(err) { + resource := &velerov1.Backup{ + ObjectMeta: metav1.ObjectMeta{ + Name: resourceName, + Namespace: namespace, + }, + Spec: velerov1.BackupSpec{}, + } + Expect(kClient.Create(ctx, resource)).To(Succeed()) + } + }) + + AfterAll(func() { + resource := &velerov1.Backup{} + err := kClient.Get(ctx, typeNamespacedName, resource) + Expect(err).NotTo(HaveOccurred()) + + By("Cleanup the specific resource instance Backup") + Expect(kClient.Delete(ctx, resource)).To(Succeed()) + }) + + It("should successfully reconcile resource", func() { + fakeConsoleClient := mocks.NewClientMock(mocks.TestingT) + fakeConsoleClient.On("SaveClusterBackup", mock.Anything, mock.Anything).Return(nil, nil) + reconciler := &BackupReconciler{ + Client: kClient, + Scheme: kClient.Scheme(), + ConsoleClient: fakeConsoleClient, + } + _, err := reconciler.Reconcile(ctx, reconcile.Request{ + NamespacedName: typeNamespacedName, + }) + Expect(err).NotTo(HaveOccurred()) + }) + }) + +}) diff --git a/internal/controller/constraint_controller_test.go b/internal/controller/constraint_controller_test.go new file mode 100644 index 00000000..d39f076c --- /dev/null +++ b/internal/controller/constraint_controller_test.go @@ -0,0 +1,88 @@ +package controller + +import ( + "context" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + templatesv1 "github.com/open-policy-agent/frameworks/constraint/pkg/apis/templates/v1" + "github.com/open-policy-agent/gatekeeper/v3/apis/status/v1beta1" + constraintstatusv1beta1 "github.com/open-policy-agent/gatekeeper/v3/apis/status/v1beta1" + "github.com/pluralsh/deployment-operator/pkg/test/mocks" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/reconcile" +) + +var _ = Describe("ConstraintPodStatus Controller", Ordered, func() { + Context("When reconciling a resource", func() { + const ( + resourceName = "default" + namespace = "default" + kind = "Test" + templateName = "test-template" + ) + + ctx := context.Background() + + typeNamespacedName := types.NamespacedName{ + Name: resourceName, + Namespace: "default", + } + + cps := new(constraintstatusv1beta1.ConstraintPodStatus) + + BeforeAll(func() { + By("creating the custom resource for the Kind ConstraintPodStatus") + err := kClient.Get(ctx, typeNamespacedName, cps) + if err != nil && errors.IsNotFound(err) { + resource := &constraintstatusv1beta1.ConstraintPodStatus{ + ObjectMeta: metav1.ObjectMeta{ + Name: resourceName, + Namespace: namespace, + Labels: map[string]string{v1beta1.ConstraintNameLabel: templateName, v1beta1.ConstraintKindLabel: kind, v1beta1.ConstraintTemplateNameLabel: templateName}, + }, + Status: constraintstatusv1beta1.ConstraintPodStatusStatus{}, + } + Expect(kClient.Create(ctx, resource)).To(Succeed()) + } + template := &templatesv1.ConstraintTemplate{ + ObjectMeta: metav1.ObjectMeta{ + Name: templateName, + Namespace: namespace, + }, + Spec: templatesv1.ConstraintTemplateSpec{}, + } + Expect(kClient.Create(ctx, template)).To(Succeed()) + }) + + AfterAll(func() { + resource := &constraintstatusv1beta1.ConstraintPodStatus{} + err := kClient.Get(ctx, typeNamespacedName, resource) + Expect(err).NotTo(HaveOccurred()) + + By("Cleanup the specific resource instance ConstraintPodStatus") + Expect(kClient.Delete(ctx, resource)).To(Succeed()) + + template := new(templatesv1.ConstraintTemplate) + Expect(kClient.Get(ctx, types.NamespacedName{Name: templateName}, template)).To(Succeed()) + Expect(kClient.Delete(ctx, template)).To(Succeed()) + }) + + It("should fail reconcile resource", func() { + fakeConsoleClient := mocks.NewClientMock(mocks.TestingT) + reconciler := &ConstraintReconciler{ + Client: kClient, + Scheme: kClient.Scheme(), + ConsoleClient: fakeConsoleClient, + Reader: kClient, + } + _, err := reconciler.Reconcile(ctx, reconcile.Request{ + NamespacedName: typeNamespacedName, + }) + Expect(err).To(HaveOccurred()) + }) + }) + +}) diff --git a/internal/controller/crd_controller_test.go b/internal/controller/crd_controller_test.go new file mode 100644 index 00000000..0914b1b7 --- /dev/null +++ b/internal/controller/crd_controller_test.go @@ -0,0 +1,124 @@ +package controller + +import ( + "context" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/reconcile" +) + +type TestReconciler struct{} + +func (r *TestReconciler) SetupWithManager(_ ctrl.Manager) error { + return nil +} + +var _ = Describe("CRD Controller", Ordered, func() { + Context("When reconciling a resource", func() { + const ( + resourceName = "testresources.test.group" + ) + + ctx := context.Background() + + typeNamespacedName := types.NamespacedName{ + Name: resourceName, + Namespace: "default", + } + + testReconciler := TestReconciler{} + reconcileGroups := map[schema.GroupVersionKind]SetupWithManager{ + { + Group: "test.group", + Version: "v1", + Kind: "TestResource", + }: testReconciler.SetupWithManager, + } + + crd := &apiextensionsv1.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: "testresources.test.group", + }, + Spec: apiextensionsv1.CustomResourceDefinitionSpec{ + Group: "test.group", + Names: apiextensionsv1.CustomResourceDefinitionNames{ + Plural: "testresources", + Singular: "testresource", + Kind: "TestResource", + ListKind: "TestResourceList", + ShortNames: []string{"tr"}, + }, + Scope: apiextensionsv1.NamespaceScoped, + Versions: []apiextensionsv1.CustomResourceDefinitionVersion{ + { + Name: "v1", + Served: true, + Storage: true, + Schema: &apiextensionsv1.CustomResourceValidation{ + OpenAPIV3Schema: &apiextensionsv1.JSONSchemaProps{ + Type: "object", + Properties: map[string]apiextensionsv1.JSONSchemaProps{ + "spec": { + Type: "object", + Properties: map[string]apiextensionsv1.JSONSchemaProps{ + "name": { + Type: "string", + }, + "value": { + Type: "string", + }, + }, + }, + "status": { + Type: "object", + Properties: map[string]apiextensionsv1.JSONSchemaProps{}, + }, + }, + }, + }, + }, + }, + }, + } + + BeforeAll(func() { + By("creating the custom resource") + err := kClient.Get(ctx, typeNamespacedName, &apiextensionsv1.CustomResourceDefinition{}) + if err != nil && errors.IsNotFound(err) { + Expect(kClient.Create(ctx, crd)).To(Succeed()) + } + }) + + AfterAll(func() { + resource := &apiextensionsv1.CustomResourceDefinition{} + err := kClient.Get(ctx, typeNamespacedName, resource) + Expect(err).NotTo(HaveOccurred()) + + By("Cleanup the specific CRD") + Expect(kClient.Delete(ctx, resource)).To(Succeed()) + }) + + It("should successfully reconcile resource", func() { + + reconciler := &CrdRegisterControllerReconciler{ + Client: kClient, + Scheme: kClient.Scheme(), + ReconcilerGroups: reconcileGroups, + } + _, err := reconciler.Reconcile(ctx, reconcile.Request{ + NamespacedName: typeNamespacedName, + }) + Expect(err).NotTo(HaveOccurred()) + Expect(reconciler.registeredControllers).ToNot(BeNil()) + Expect(reconciler.registeredControllers).To(HaveLen(1)) + }) + }) + +}) diff --git a/internal/controller/customhealth_controller.go b/internal/controller/customhealth_controller.go index 111cf5a1..64449d7d 100644 --- a/internal/controller/customhealth_controller.go +++ b/internal/controller/customhealth_controller.go @@ -61,7 +61,7 @@ func (r *CustomHealthReconciler) Reconcile(ctx context.Context, req ctrl.Request utils.MarkCondition(script.SetCondition, v1alpha1.ReadyConditionType, v1.ConditionFalse, v1alpha1.ReadyConditionReason, "") // Ensure that status updates will always be persisted when exiting this function. - scope, err := NewClusterScope(ctx, r.Client, script) + scope, err := NewDefaultScope(ctx, r.Client, script) if err != nil { logger.Error(err, "Failed to create cluster scope") utils.MarkCondition(script.SetCondition, v1alpha1.ReadyConditionType, v1.ConditionFalse, v1alpha1.ReadyConditionReason, err.Error()) diff --git a/internal/controller/customhealth_controller_test.go b/internal/controller/customhealth_controller_test.go index 3936b49a..a422d910 100644 --- a/internal/controller/customhealth_controller_test.go +++ b/internal/controller/customhealth_controller_test.go @@ -59,13 +59,6 @@ var _ = Describe("Customhealt Controller", Ordered, func() { It("should successfully reconcile resource", func() { By("Reconciling the import resource") - _ = struct { - expectedStatus v1alpha1.CustomHealthStatus - }{ - expectedStatus: v1alpha1.CustomHealthStatus{ - Conditions: []metav1.Condition{}, - }, - } reconciler := &CustomHealthReconciler{ Client: kClient, Scheme: kClient.Scheme(), diff --git a/internal/controller/customhealth_scope.go b/internal/controller/customhealth_scope.go deleted file mode 100644 index 4b4070d5..00000000 --- a/internal/controller/customhealth_scope.go +++ /dev/null @@ -1,49 +0,0 @@ -package controller - -import ( - "context" - "errors" - "fmt" - "reflect" - - "k8s.io/client-go/util/retry" - "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/pluralsh/deployment-operator/api/v1alpha1" -) - -type LuaScriptScope struct { - Client client.Client - HealthConvert *v1alpha1.CustomHealth - ctx context.Context -} - -func (p *LuaScriptScope) PatchObject() error { - - key := client.ObjectKeyFromObject(p.HealthConvert) - - return retry.RetryOnConflict(retry.DefaultRetry, func() error { - oldScript := &v1alpha1.CustomHealth{} - if err := p.Client.Get(p.ctx, key, oldScript); err != nil { - return fmt.Errorf("could not fetch current %s/%s state, got error: %w", oldScript.GetName(), oldScript.GetNamespace(), err) - } - - if reflect.DeepEqual(oldScript.Status, p.HealthConvert.Status) { - return nil - } - - return p.Client.Status().Patch(p.ctx, p.HealthConvert, client.MergeFrom(oldScript)) - }) - -} - -func NewClusterScope(ctx context.Context, client client.Client, luaScript *v1alpha1.CustomHealth) (*LuaScriptScope, error) { - if luaScript == nil { - return nil, errors.New("failed to create new cluster scope, got nil cluster") - } - return &LuaScriptScope{ - Client: client, - HealthConvert: luaScript, - ctx: ctx, - }, nil -} diff --git a/internal/controller/job_scope.go b/internal/controller/job_scope.go deleted file mode 100644 index 6902cec6..00000000 --- a/internal/controller/job_scope.go +++ /dev/null @@ -1,41 +0,0 @@ -package controller - -import ( - "context" - "errors" - "fmt" - - "github.com/pluralsh/controller-reconcile-helper/pkg/patch" - batchv1 "k8s.io/api/batch/v1" - "sigs.k8s.io/controller-runtime/pkg/client" -) - -type JobScope struct { - Client client.Client - Job *batchv1.Job - - ctx context.Context - patchHelper *patch.Helper -} - -func (p *JobScope) PatchObject() error { - return p.patchHelper.Patch(p.ctx, p.Job) -} - -func NewJobScope(ctx context.Context, client client.Client, job *batchv1.Job) (*JobScope, error) { - if job == nil { - return nil, errors.New("failed to create new job scope, got nil job") - } - - helper, err := patch.NewHelper(job, client) - if err != nil { - return nil, fmt.Errorf("failed to create new pipeline scope, go error: %w", err) - } - - return &JobScope{ - Client: client, - Job: job, - ctx: ctx, - patchHelper: helper, - }, nil -} diff --git a/internal/controller/pipelinegate_controller.go b/internal/controller/pipelinegate_controller.go index 859de23e..08ab62b5 100644 --- a/internal/controller/pipelinegate_controller.go +++ b/internal/controller/pipelinegate_controller.go @@ -77,7 +77,7 @@ func (r *PipelineGateReconciler) Reconcile(ctx context.Context, req ctrl.Request return ctrl.Result{}, nil } - scope, err := NewPipelineGateScope(ctx, r.Client, crGate) + scope, err := NewDefaultScope(ctx, r.Client, crGate) if err != nil { return ctrl.Result{}, err } @@ -223,7 +223,7 @@ func (r *PipelineGateReconciler) updateJob(ctx context.Context, reconciledJob *b reconciledJob.Spec.Template.Annotations[k] = v } - jobScope, err := NewJobScope(ctx, r.Client, reconciledJob) + jobScope, err := NewDefaultScope(ctx, r.Client, reconciledJob) if err != nil { return err } diff --git a/internal/controller/pipelinegate_scope.go b/internal/controller/pipelinegate_scope.go deleted file mode 100644 index 75ba8d67..00000000 --- a/internal/controller/pipelinegate_scope.go +++ /dev/null @@ -1,42 +0,0 @@ -package controller - -import ( - "context" - "errors" - "fmt" - - "github.com/pluralsh/controller-reconcile-helper/pkg/patch" - v1alpha1 "github.com/pluralsh/deployment-operator/api/v1alpha1" - - "sigs.k8s.io/controller-runtime/pkg/client" -) - -type PipelineGateScope struct { - Client client.Client - PipelineGate *v1alpha1.PipelineGate - - ctx context.Context - patchHelper *patch.Helper -} - -func (p *PipelineGateScope) PatchObject() error { - return p.patchHelper.Patch(p.ctx, p.PipelineGate) -} - -func NewPipelineGateScope(ctx context.Context, client client.Client, gate *v1alpha1.PipelineGate) (*PipelineGateScope, error) { - if gate == nil { - return nil, errors.New("failed to create new pipeline scope, got nil pipeline") - } - - helper, err := patch.NewHelper(gate, client) - if err != nil { - return nil, fmt.Errorf("failed to create new pipeline scope, go error: %w", err) - } - - return &PipelineGateScope{ - Client: client, - PipelineGate: gate, - ctx: ctx, - patchHelper: helper, - }, nil -} diff --git a/internal/controller/restore_controller_test.go b/internal/controller/restore_controller_test.go new file mode 100644 index 00000000..867f7ca2 --- /dev/null +++ b/internal/controller/restore_controller_test.go @@ -0,0 +1,79 @@ +package controller + +import ( + "context" + "time" + + "github.com/pluralsh/deployment-operator/pkg/controller/service" + corev1 "k8s.io/api/core/v1" + + velerov1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/reconcile" +) + +var _ = Describe("Restore Controller", Ordered, func() { + Context("When reconciling a resource", func() { + const ( + resourceName = "default" + namespace = "default" + ) + + ctx := context.Background() + + typeNamespacedName := types.NamespacedName{ + Name: resourceName, + Namespace: "default", + } + + restore := &velerov1.Restore{} + + BeforeAll(func() { + By("creating the custom resource for the Kind Restore") + err := kClient.Get(ctx, typeNamespacedName, restore) + if err != nil && errors.IsNotFound(err) { + resource := &velerov1.Restore{ + ObjectMeta: metav1.ObjectMeta{ + Name: resourceName, + Namespace: namespace, + }, + Spec: velerov1.RestoreSpec{}, + Status: velerov1.RestoreStatus{ + Phase: velerov1.RestorePhaseInProgress, + StartTimestamp: &metav1.Time{ + Time: time.Now(), + }, + }, + } + Expect(kClient.Create(ctx, resource)).To(Succeed()) + } + }) + + AfterAll(func() { + resource := &velerov1.Restore{} + err := kClient.Get(ctx, typeNamespacedName, resource) + Expect(err).NotTo(HaveOccurred()) + + By("Cleanup the specific resource instance Backup") + Expect(kClient.Delete(ctx, resource)).To(Succeed()) + }) + + It("should successfully reconcile resource and create config map", func() { + reconciler := &RestoreReconciler{ + Client: kClient, + Scheme: kClient.Scheme(), + } + _, err := reconciler.Reconcile(ctx, reconcile.Request{ + NamespacedName: typeNamespacedName, + }) + Expect(err).NotTo(HaveOccurred()) + Expect(kClient.Get(ctx, types.NamespacedName{Name: service.RestoreConfigMapName, Namespace: namespace}, &corev1.ConfigMap{})).To(Succeed()) + }) + }) + +}) diff --git a/internal/controller/suite_test.go b/internal/controller/suite_test.go index 0f0949d7..9a8ec5bd 100644 --- a/internal/controller/suite_test.go +++ b/internal/controller/suite_test.go @@ -24,7 +24,11 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + templatesv1 "github.com/open-policy-agent/frameworks/constraint/pkg/apis/templates/v1" + constraintstatusv1beta1 "github.com/open-policy-agent/gatekeeper/v3/apis/status/v1beta1" deploymentsv1alpha1 "github.com/pluralsh/deployment-operator/api/v1alpha1" + velerov1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/client-go/kubernetes/scheme" "k8s.io/metrics/pkg/apis/metrics/v1beta1" "sigs.k8s.io/controller-runtime/pkg/client" @@ -48,7 +52,7 @@ var _ = BeforeSuite(func() { By("bootstrapping test environment") testEnv = &envtest.Environment{ - CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")}, + CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases"), filepath.Join("..", "..", "test", "crd")}, ErrorIfCRDPathMissing: true, BinaryAssetsDirectory: filepath.Join("..", "..", "bin", "k8s", fmt.Sprintf("1.28.3-%s-%s", runtime.GOOS, runtime.GOARCH)), @@ -60,13 +64,25 @@ var _ = BeforeSuite(func() { err = v1beta1.AddToScheme(scheme.Scheme) Expect(err).NotTo(HaveOccurred()) + err = deploymentsv1alpha1.AddToScheme(scheme.Scheme) Expect(err).NotTo(HaveOccurred()) + err = velerov1.AddToScheme(scheme.Scheme) + Expect(err).NotTo(HaveOccurred()) + + err = apiextensionsv1.AddToScheme(scheme.Scheme) + Expect(err).NotTo(HaveOccurred()) + + err = constraintstatusv1beta1.AddToScheme(scheme.Scheme) + Expect(err).NotTo(HaveOccurred()) + + err = templatesv1.AddToScheme(scheme.Scheme) + Expect(err).NotTo(HaveOccurred()) + kClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) Expect(err).NotTo(HaveOccurred()) Expect(kClient).NotTo(BeNil()) - }) var _ = AfterSuite(func() { diff --git a/test/crd/constraintpodstatus-customresourcedefinition.yaml b/test/crd/constraintpodstatus-customresourcedefinition.yaml new file mode 100644 index 00000000..85942c0d --- /dev/null +++ b/test/crd/constraintpodstatus-customresourcedefinition.yaml @@ -0,0 +1,80 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + labels: + gatekeeper.sh/system: "yes" + name: constraintpodstatuses.status.gatekeeper.sh +spec: + group: status.gatekeeper.sh + names: + kind: ConstraintPodStatus + listKind: ConstraintPodStatusList + plural: constraintpodstatuses + singular: constraintpodstatus + preserveUnknownFields: false + scope: Namespaced + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + description: ConstraintPodStatus is the Schema for the constraintpodstatuses API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + status: + description: ConstraintPodStatusStatus defines the observed state of ConstraintPodStatus. + properties: + constraintUID: + description: |- + Storing the constraint UID allows us to detect drift, such as + when a constraint has been recreated after its CRD was deleted + out from under it, interrupting the watch + type: string + enforced: + type: boolean + errors: + items: + description: Error represents a single error caught while adding a constraint to engine. + properties: + code: + type: string + location: + type: string + message: + type: string + required: + - code + - message + type: object + type: array + id: + type: string + observedGeneration: + format: int64 + type: integer + operations: + items: + type: string + type: array + type: object + type: object + served: true + storage: true diff --git a/test/crd/templates.gatekeeper.sh_constrainttemplates.yaml b/test/crd/templates.gatekeeper.sh_constrainttemplates.yaml new file mode 100644 index 00000000..f54950ae --- /dev/null +++ b/test/crd/templates.gatekeeper.sh_constrainttemplates.yaml @@ -0,0 +1,406 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: constrainttemplates.templates.gatekeeper.sh +spec: + group: templates.gatekeeper.sh + names: + kind: ConstraintTemplate + listKind: ConstraintTemplateList + plural: constrainttemplates + singular: constrainttemplate + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + description: ConstraintTemplate is the Schema for the constrainttemplates + API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: ConstraintTemplateSpec defines the desired state of ConstraintTemplate. + properties: + crd: + properties: + spec: + properties: + names: + properties: + kind: + type: string + shortNames: + items: + type: string + type: array + type: object + validation: + default: + legacySchema: false + properties: + legacySchema: + default: false + type: boolean + openAPIV3Schema: + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + type: object + type: object + targets: + items: + properties: + code: + description: |- + The source code options for the constraint template. "Rego" can only + be specified in one place (either here or in the "rego" field) + items: + properties: + engine: + description: 'The engine used to evaluate the code. Example: + "Rego". Required.' + type: string + source: + description: The source code for the template. Required. + x-kubernetes-preserve-unknown-fields: true + required: + - engine + - source + type: object + type: array + x-kubernetes-list-map-keys: + - engine + x-kubernetes-list-type: map + libs: + items: + type: string + type: array + rego: + type: string + target: + type: string + type: object + type: array + type: object + status: + description: ConstraintTemplateStatus defines the observed state of ConstraintTemplate. + properties: + byPod: + items: + description: |- + ByPodStatus defines the observed state of ConstraintTemplate as seen by + an individual controller + properties: + errors: + items: + description: CreateCRDError represents a single error caught + during parsing, compiling, etc. + properties: + code: + type: string + location: + type: string + message: + type: string + required: + - code + - message + type: object + type: array + id: + description: a unique identifier for the pod that wrote the + status + type: string + observedGeneration: + format: int64 + type: integer + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + created: + type: boolean + type: object + type: object + served: true + storage: true + subresources: + status: {} + - name: v1alpha1 + schema: + openAPIV3Schema: + description: ConstraintTemplate is the Schema for the constrainttemplates + API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: ConstraintTemplateSpec defines the desired state of ConstraintTemplate. + properties: + crd: + properties: + spec: + properties: + names: + properties: + kind: + type: string + shortNames: + items: + type: string + type: array + type: object + validation: + default: + legacySchema: true + properties: + legacySchema: + default: true + type: boolean + openAPIV3Schema: + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + type: object + type: object + targets: + items: + properties: + code: + description: |- + The source code options for the constraint template. "Rego" can only + be specified in one place (either here or in the "rego" field) + items: + properties: + engine: + description: 'The engine used to evaluate the code. Example: + "Rego". Required.' + type: string + source: + description: The source code for the template. Required. + x-kubernetes-preserve-unknown-fields: true + required: + - engine + - source + type: object + type: array + x-kubernetes-list-map-keys: + - engine + x-kubernetes-list-type: map + libs: + items: + type: string + type: array + rego: + type: string + target: + type: string + type: object + type: array + type: object + status: + description: ConstraintTemplateStatus defines the observed state of ConstraintTemplate. + properties: + byPod: + items: + description: |- + ByPodStatus defines the observed state of ConstraintTemplate as seen by + an individual controller + properties: + errors: + items: + description: CreateCRDError represents a single error caught + during parsing, compiling, etc. + properties: + code: + type: string + location: + type: string + message: + type: string + required: + - code + - message + type: object + type: array + id: + description: a unique identifier for the pod that wrote the + status + type: string + observedGeneration: + format: int64 + type: integer + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + created: + type: boolean + type: object + type: object + served: true + storage: false + subresources: + status: {} + - name: v1beta1 + schema: + openAPIV3Schema: + description: ConstraintTemplate is the Schema for the constrainttemplates + API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: ConstraintTemplateSpec defines the desired state of ConstraintTemplate. + properties: + crd: + properties: + spec: + properties: + names: + properties: + kind: + type: string + shortNames: + items: + type: string + type: array + type: object + validation: + default: + legacySchema: true + properties: + legacySchema: + default: true + type: boolean + openAPIV3Schema: + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + type: object + type: object + targets: + items: + properties: + code: + description: |- + The source code options for the constraint template. "Rego" can only + be specified in one place (either here or in the "rego" field) + items: + properties: + engine: + description: 'The engine used to evaluate the code. Example: + "Rego". Required.' + type: string + source: + description: The source code for the template. Required. + x-kubernetes-preserve-unknown-fields: true + required: + - engine + - source + type: object + type: array + x-kubernetes-list-map-keys: + - engine + x-kubernetes-list-type: map + libs: + items: + type: string + type: array + rego: + type: string + target: + type: string + type: object + type: array + type: object + status: + description: ConstraintTemplateStatus defines the observed state of ConstraintTemplate. + properties: + byPod: + items: + description: |- + ByPodStatus defines the observed state of ConstraintTemplate as seen by + an individual controller + properties: + errors: + items: + description: CreateCRDError represents a single error caught + during parsing, compiling, etc. + properties: + code: + type: string + location: + type: string + message: + type: string + required: + - code + - message + type: object + type: array + id: + description: a unique identifier for the pod that wrote the + status + type: string + observedGeneration: + format: int64 + type: integer + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + created: + type: boolean + type: object + type: object + served: true + storage: false + subresources: + status: {} diff --git a/test/crd/velero.io_backups.yaml b/test/crd/velero.io_backups.yaml new file mode 100644 index 00000000..1e79dcde --- /dev/null +++ b/test/crd/velero.io_backups.yaml @@ -0,0 +1,660 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: backups.velero.io +spec: + group: velero.io + names: + kind: Backup + listKind: BackupList + plural: backups + singular: backup + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: |- + Backup is a Velero resource that represents the capture of Kubernetes + cluster state at a point in time (API objects and associated volume state). + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: BackupSpec defines the specification for a Velero backup. + properties: + csiSnapshotTimeout: + description: |- + CSISnapshotTimeout specifies the time used to wait for CSI VolumeSnapshot status turns to + ReadyToUse during creation, before returning error as timeout. + The default value is 10 minute. + type: string + datamover: + description: |- + DataMover specifies the data mover to be used by the backup. + If DataMover is "" or "velero", the built-in data mover will be used. + type: string + defaultVolumesToFsBackup: + description: |- + DefaultVolumesToFsBackup specifies whether pod volume file system backup should be used + for all volumes by default. + nullable: true + type: boolean + defaultVolumesToRestic: + description: |- + DefaultVolumesToRestic specifies whether restic should be used to take a + backup of all pod volumes by default. + + + Deprecated: this field is no longer used and will be removed entirely in future. Use DefaultVolumesToFsBackup instead. + nullable: true + type: boolean + excludedClusterScopedResources: + description: |- + ExcludedClusterScopedResources is a slice of cluster-scoped + resource type names to exclude from the backup. + If set to "*", all cluster-scoped resource types are excluded. + The default value is empty. + items: + type: string + nullable: true + type: array + excludedNamespaceScopedResources: + description: |- + ExcludedNamespaceScopedResources is a slice of namespace-scoped + resource type names to exclude from the backup. + If set to "*", all namespace-scoped resource types are excluded. + The default value is empty. + items: + type: string + nullable: true + type: array + excludedNamespaces: + description: |- + ExcludedNamespaces contains a list of namespaces that are not + included in the backup. + items: + type: string + nullable: true + type: array + excludedResources: + description: |- + ExcludedResources is a slice of resource names that are not + included in the backup. + items: + type: string + nullable: true + type: array + hooks: + description: Hooks represent custom behaviors that should be executed + at different phases of the backup. + properties: + resources: + description: Resources are hooks that should be executed when + backing up individual instances of a resource. + items: + description: |- + BackupResourceHookSpec defines one or more BackupResourceHooks that should be executed based on + the rules defined for namespaces, resources, and label selector. + properties: + excludedNamespaces: + description: ExcludedNamespaces specifies the namespaces + to which this hook spec does not apply. + items: + type: string + nullable: true + type: array + excludedResources: + description: ExcludedResources specifies the resources to + which this hook spec does not apply. + items: + type: string + nullable: true + type: array + includedNamespaces: + description: |- + IncludedNamespaces specifies the namespaces to which this hook spec applies. If empty, it applies + to all namespaces. + items: + type: string + nullable: true + type: array + includedResources: + description: |- + IncludedResources specifies the resources to which this hook spec applies. If empty, it applies + to all resources. + items: + type: string + nullable: true + type: array + labelSelector: + description: LabelSelector, if specified, filters the resources + to which this hook spec applies. + nullable: true + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + name: + description: Name is the name of this hook. + type: string + post: + description: |- + PostHooks is a list of BackupResourceHooks to execute after storing the item in the backup. + These are executed after all "additional items" from item actions are processed. + items: + description: BackupResourceHook defines a hook for a resource. + properties: + exec: + description: Exec defines an exec hook. + properties: + command: + description: Command is the command and arguments + to execute. + items: + type: string + minItems: 1 + type: array + container: + description: |- + Container is the container in the pod where the command should be executed. If not specified, + the pod's first container is used. + type: string + onError: + description: OnError specifies how Velero should + behave if it encounters an error executing this + hook. + enum: + - Continue + - Fail + type: string + timeout: + description: |- + Timeout defines the maximum amount of time Velero should wait for the hook to complete before + considering the execution a failure. + type: string + required: + - command + type: object + required: + - exec + type: object + type: array + pre: + description: |- + PreHooks is a list of BackupResourceHooks to execute prior to storing the item in the backup. + These are executed before any "additional items" from item actions are processed. + items: + description: BackupResourceHook defines a hook for a resource. + properties: + exec: + description: Exec defines an exec hook. + properties: + command: + description: Command is the command and arguments + to execute. + items: + type: string + minItems: 1 + type: array + container: + description: |- + Container is the container in the pod where the command should be executed. If not specified, + the pod's first container is used. + type: string + onError: + description: OnError specifies how Velero should + behave if it encounters an error executing this + hook. + enum: + - Continue + - Fail + type: string + timeout: + description: |- + Timeout defines the maximum amount of time Velero should wait for the hook to complete before + considering the execution a failure. + type: string + required: + - command + type: object + required: + - exec + type: object + type: array + required: + - name + type: object + nullable: true + type: array + type: object + includeClusterResources: + description: |- + IncludeClusterResources specifies whether cluster-scoped resources + should be included for consideration in the backup. + nullable: true + type: boolean + includedClusterScopedResources: + description: |- + IncludedClusterScopedResources is a slice of cluster-scoped + resource type names to include in the backup. + If set to "*", all cluster-scoped resource types are included. + The default value is empty, which means only related + cluster-scoped resources are included. + items: + type: string + nullable: true + type: array + includedNamespaceScopedResources: + description: |- + IncludedNamespaceScopedResources is a slice of namespace-scoped + resource type names to include in the backup. + The default value is "*". + items: + type: string + nullable: true + type: array + includedNamespaces: + description: |- + IncludedNamespaces is a slice of namespace names to include objects + from. If empty, all namespaces are included. + items: + type: string + nullable: true + type: array + includedResources: + description: |- + IncludedResources is a slice of resource names to include + in the backup. If empty, all resources are included. + items: + type: string + nullable: true + type: array + itemOperationTimeout: + description: |- + ItemOperationTimeout specifies the time used to wait for asynchronous BackupItemAction operations + The default value is 4 hour. + type: string + labelSelector: + description: |- + LabelSelector is a metav1.LabelSelector to filter with + when adding individual objects to the backup. If empty + or nil, all objects are included. Optional. + nullable: true + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + metadata: + properties: + labels: + additionalProperties: + type: string + type: object + type: object + orLabelSelectors: + description: |- + OrLabelSelectors is list of metav1.LabelSelector to filter with + when adding individual objects to the backup. If multiple provided + they will be joined by the OR operator. LabelSelector as well as + OrLabelSelectors cannot co-exist in backup request, only one of them + can be used. + items: + description: |- + A label selector is a label query over a set of resources. The result of matchLabels and + matchExpressions are ANDed. An empty label selector matches all objects. A null + label selector matches no objects. + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + nullable: true + type: array + orderedResources: + additionalProperties: + type: string + description: |- + OrderedResources specifies the backup order of resources of specific Kind. + The map key is the resource name and value is a list of object names separated by commas. + Each resource name has format "namespace/objectname". For cluster resources, simply use "objectname". + nullable: true + type: object + resourcePolicy: + description: ResourcePolicy specifies the referenced resource policies + that backup should follow + properties: + apiGroup: + description: |- + APIGroup is the group for the resource being referenced. + If APIGroup is not specified, the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + snapshotMoveData: + description: SnapshotMoveData specifies whether snapshot data should + be moved + nullable: true + type: boolean + snapshotVolumes: + description: |- + SnapshotVolumes specifies whether to take snapshots + of any PV's referenced in the set of objects included + in the Backup. + nullable: true + type: boolean + storageLocation: + description: StorageLocation is a string containing the name of a + BackupStorageLocation where the backup should be stored. + type: string + ttl: + description: |- + TTL is a time.Duration-parseable string describing how long + the Backup should be retained for. + type: string + uploaderConfig: + description: UploaderConfig specifies the configuration for the uploader. + nullable: true + properties: + parallelFilesUpload: + description: ParallelFilesUpload is the number of files parallel + uploads to perform when using the uploader. + type: integer + type: object + volumeSnapshotLocations: + description: VolumeSnapshotLocations is a list containing names of + VolumeSnapshotLocations associated with this backup. + items: + type: string + type: array + type: object + status: + description: BackupStatus captures the current status of a Velero backup. + properties: + backupItemOperationsAttempted: + description: |- + BackupItemOperationsAttempted is the total number of attempted + async BackupItemAction operations for this backup. + type: integer + backupItemOperationsCompleted: + description: |- + BackupItemOperationsCompleted is the total number of successfully completed + async BackupItemAction operations for this backup. + type: integer + backupItemOperationsFailed: + description: |- + BackupItemOperationsFailed is the total number of async + BackupItemAction operations for this backup which ended with an error. + type: integer + completionTimestamp: + description: |- + CompletionTimestamp records the time a backup was completed. + Completion time is recorded even on failed backups. + Completion time is recorded before uploading the backup object. + The server's time is used for CompletionTimestamps + format: date-time + nullable: true + type: string + csiVolumeSnapshotsAttempted: + description: |- + CSIVolumeSnapshotsAttempted is the total number of attempted + CSI VolumeSnapshots for this backup. + type: integer + csiVolumeSnapshotsCompleted: + description: |- + CSIVolumeSnapshotsCompleted is the total number of successfully + completed CSI VolumeSnapshots for this backup. + type: integer + errors: + description: |- + Errors is a count of all error messages that were generated during + execution of the backup. The actual errors are in the backup's log + file in object storage. + type: integer + expiration: + description: Expiration is when this Backup is eligible for garbage-collection. + format: date-time + nullable: true + type: string + failureReason: + description: FailureReason is an error that caused the entire backup + to fail. + type: string + formatVersion: + description: FormatVersion is the backup format version, including + major, minor, and patch version. + type: string + hookStatus: + description: HookStatus contains information about the status of the + hooks. + nullable: true + properties: + hooksAttempted: + description: |- + HooksAttempted is the total number of attempted hooks + Specifically, HooksAttempted represents the number of hooks that failed to execute + and the number of hooks that executed successfully. + type: integer + hooksFailed: + description: HooksFailed is the total number of hooks which ended + with an error + type: integer + type: object + phase: + description: Phase is the current state of the Backup. + enum: + - New + - FailedValidation + - InProgress + - WaitingForPluginOperations + - WaitingForPluginOperationsPartiallyFailed + - Finalizing + - FinalizingPartiallyFailed + - Completed + - PartiallyFailed + - Failed + - Deleting + type: string + progress: + description: |- + Progress contains information about the backup's execution progress. Note + that this information is best-effort only -- if Velero fails to update it + during a backup for any reason, it may be inaccurate/stale. + nullable: true + properties: + itemsBackedUp: + description: |- + ItemsBackedUp is the number of items that have actually been written to the + backup tarball so far. + type: integer + totalItems: + description: |- + TotalItems is the total number of items to be backed up. This number may change + throughout the execution of the backup due to plugins that return additional related + items to back up, the velero.io/exclude-from-backup label, and various other + filters that happen as items are processed. + type: integer + type: object + startTimestamp: + description: |- + StartTimestamp records the time a backup was started. + Separate from CreationTimestamp, since that value changes + on restores. + The server's time is used for StartTimestamps + format: date-time + nullable: true + type: string + validationErrors: + description: |- + ValidationErrors is a slice of all validation errors (if + applicable). + items: + type: string + nullable: true + type: array + version: + description: |- + Version is the backup format major version. + Deprecated: Please see FormatVersion + type: integer + volumeSnapshotsAttempted: + description: |- + VolumeSnapshotsAttempted is the total number of attempted + volume snapshots for this backup. + type: integer + volumeSnapshotsCompleted: + description: |- + VolumeSnapshotsCompleted is the total number of successfully + completed volume snapshots for this backup. + type: integer + warnings: + description: |- + Warnings is a count of all warning messages that were generated during + execution of the backup. The actual warnings are in the backup's log + file in object storage. + type: integer + type: object + type: object + served: true + storage: true diff --git a/test/crd/velero.io_restores.yaml b/test/crd/velero.io_restores.yaml new file mode 100644 index 00000000..e2761729 --- /dev/null +++ b/test/crd/velero.io_restores.yaml @@ -0,0 +1,556 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: restores.velero.io +spec: + group: velero.io + names: + kind: Restore + listKind: RestoreList + plural: restores + singular: restore + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: |- + Restore is a Velero resource that represents the application of + resources from a Velero backup to a target Kubernetes cluster. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: RestoreSpec defines the specification for a Velero restore. + properties: + backupName: + description: |- + BackupName is the unique name of the Velero backup to restore + from. + type: string + excludedNamespaces: + description: |- + ExcludedNamespaces contains a list of namespaces that are not + included in the restore. + items: + type: string + nullable: true + type: array + excludedResources: + description: |- + ExcludedResources is a slice of resource names that are not + included in the restore. + items: + type: string + nullable: true + type: array + existingResourcePolicy: + description: ExistingResourcePolicy specifies the restore behavior + for the Kubernetes resource to be restored + nullable: true + type: string + hooks: + description: Hooks represent custom behaviors that should be executed + during or post restore. + properties: + resources: + items: + description: |- + RestoreResourceHookSpec defines one or more RestoreResrouceHooks that should be executed based on + the rules defined for namespaces, resources, and label selector. + properties: + excludedNamespaces: + description: ExcludedNamespaces specifies the namespaces + to which this hook spec does not apply. + items: + type: string + nullable: true + type: array + excludedResources: + description: ExcludedResources specifies the resources to + which this hook spec does not apply. + items: + type: string + nullable: true + type: array + includedNamespaces: + description: |- + IncludedNamespaces specifies the namespaces to which this hook spec applies. If empty, it applies + to all namespaces. + items: + type: string + nullable: true + type: array + includedResources: + description: |- + IncludedResources specifies the resources to which this hook spec applies. If empty, it applies + to all resources. + items: + type: string + nullable: true + type: array + labelSelector: + description: LabelSelector, if specified, filters the resources + to which this hook spec applies. + nullable: true + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + name: + description: Name is the name of this hook. + type: string + postHooks: + description: PostHooks is a list of RestoreResourceHooks + to execute during and after restoring a resource. + items: + description: RestoreResourceHook defines a restore hook + for a resource. + properties: + exec: + description: Exec defines an exec restore hook. + properties: + command: + description: Command is the command and arguments + to execute from within a container after a pod + has been restored. + items: + type: string + minItems: 1 + type: array + container: + description: |- + Container is the container in the pod where the command should be executed. If not specified, + the pod's first container is used. + type: string + execTimeout: + description: |- + ExecTimeout defines the maximum amount of time Velero should wait for the hook to complete before + considering the execution a failure. + type: string + onError: + description: OnError specifies how Velero should + behave if it encounters an error executing this + hook. + enum: + - Continue + - Fail + type: string + waitForReady: + description: WaitForReady ensures command will + be launched when container is Ready instead + of Running. + nullable: true + type: boolean + waitTimeout: + description: |- + WaitTimeout defines the maximum amount of time Velero should wait for the container to be Ready + before attempting to run the command. + type: string + required: + - command + type: object + init: + description: Init defines an init restore hook. + properties: + initContainers: + description: InitContainers is list of init containers + to be added to a pod during its restore. + items: + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + x-kubernetes-preserve-unknown-fields: true + timeout: + description: Timeout defines the maximum amount + of time Velero should wait for the initContainers + to complete. + type: string + type: object + type: object + type: array + required: + - name + type: object + type: array + type: object + includeClusterResources: + description: |- + IncludeClusterResources specifies whether cluster-scoped resources + should be included for consideration in the restore. If null, defaults + to true. + nullable: true + type: boolean + includedNamespaces: + description: |- + IncludedNamespaces is a slice of namespace names to include objects + from. If empty, all namespaces are included. + items: + type: string + nullable: true + type: array + includedResources: + description: |- + IncludedResources is a slice of resource names to include + in the restore. If empty, all resources in the backup are included. + items: + type: string + nullable: true + type: array + itemOperationTimeout: + description: |- + ItemOperationTimeout specifies the time used to wait for RestoreItemAction operations + The default value is 4 hour. + type: string + labelSelector: + description: |- + LabelSelector is a metav1.LabelSelector to filter with + when restoring individual objects from the backup. If empty + or nil, all objects are included. Optional. + nullable: true + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceMapping: + additionalProperties: + type: string + description: |- + NamespaceMapping is a map of source namespace names + to target namespace names to restore into. Any source + namespaces not included in the map will be restored into + namespaces of the same name. + type: object + orLabelSelectors: + description: |- + OrLabelSelectors is list of metav1.LabelSelector to filter with + when restoring individual objects from the backup. If multiple provided + they will be joined by the OR operator. LabelSelector as well as + OrLabelSelectors cannot co-exist in restore request, only one of them + can be used + items: + description: |- + A label selector is a label query over a set of resources. The result of matchLabels and + matchExpressions are ANDed. An empty label selector matches all objects. A null + label selector matches no objects. + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + nullable: true + type: array + preserveNodePorts: + description: PreserveNodePorts specifies whether to restore old nodePorts + from backup. + nullable: true + type: boolean + resourceModifier: + description: ResourceModifier specifies the reference to JSON resource + patches that should be applied to resources before restoration. + nullable: true + properties: + apiGroup: + description: |- + APIGroup is the group for the resource being referenced. + If APIGroup is not specified, the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + restorePVs: + description: |- + RestorePVs specifies whether to restore all included + PVs from snapshot + nullable: true + type: boolean + restoreStatus: + description: |- + RestoreStatus specifies which resources we should restore the status + field. If nil, no objects are included. Optional. + nullable: true + properties: + excludedResources: + description: ExcludedResources specifies the resources to which + will not restore the status. + items: + type: string + nullable: true + type: array + includedResources: + description: |- + IncludedResources specifies the resources to which will restore the status. + If empty, it applies to all resources. + items: + type: string + nullable: true + type: array + type: object + scheduleName: + description: |- + ScheduleName is the unique name of the Velero schedule to restore + from. If specified, and BackupName is empty, Velero will restore + from the most recent successful backup created from this schedule. + type: string + uploaderConfig: + description: UploaderConfig specifies the configuration for the restore. + nullable: true + properties: + parallelFilesDownload: + description: ParallelFilesDownload is the concurrency number setting + for restore. + type: integer + writeSparseFiles: + description: WriteSparseFiles is a flag to indicate whether write + files sparsely or not. + nullable: true + type: boolean + type: object + type: object + status: + description: RestoreStatus captures the current status of a Velero restore + properties: + completionTimestamp: + description: |- + CompletionTimestamp records the time the restore operation was completed. + Completion time is recorded even on failed restore. + The server's time is used for StartTimestamps + format: date-time + nullable: true + type: string + errors: + description: |- + Errors is a count of all error messages that were generated during + execution of the restore. The actual errors are stored in object storage. + type: integer + failureReason: + description: FailureReason is an error that caused the entire restore + to fail. + type: string + hookStatus: + description: HookStatus contains information about the status of the + hooks. + nullable: true + properties: + hooksAttempted: + description: |- + HooksAttempted is the total number of attempted hooks + Specifically, HooksAttempted represents the number of hooks that failed to execute + and the number of hooks that executed successfully. + type: integer + hooksFailed: + description: HooksFailed is the total number of hooks which ended + with an error + type: integer + type: object + phase: + description: Phase is the current state of the Restore + enum: + - New + - FailedValidation + - InProgress + - WaitingForPluginOperations + - WaitingForPluginOperationsPartiallyFailed + - Completed + - PartiallyFailed + - Failed + - Finalizing + - FinalizingPartiallyFailed + type: string + progress: + description: |- + Progress contains information about the restore's execution progress. Note + that this information is best-effort only -- if Velero fails to update it + during a restore for any reason, it may be inaccurate/stale. + nullable: true + properties: + itemsRestored: + description: ItemsRestored is the number of items that have actually + been restored so far + type: integer + totalItems: + description: |- + TotalItems is the total number of items to be restored. This number may change + throughout the execution of the restore due to plugins that return additional related + items to restore + type: integer + type: object + restoreItemOperationsAttempted: + description: |- + RestoreItemOperationsAttempted is the total number of attempted + async RestoreItemAction operations for this restore. + type: integer + restoreItemOperationsCompleted: + description: |- + RestoreItemOperationsCompleted is the total number of successfully completed + async RestoreItemAction operations for this restore. + type: integer + restoreItemOperationsFailed: + description: |- + RestoreItemOperationsFailed is the total number of async + RestoreItemAction operations for this restore which ended with an error. + type: integer + startTimestamp: + description: |- + StartTimestamp records the time the restore operation was started. + The server's time is used for StartTimestamps + format: date-time + nullable: true + type: string + validationErrors: + description: |- + ValidationErrors is a slice of all validation errors (if + applicable) + items: + type: string + nullable: true + type: array + warnings: + description: |- + Warnings is a count of all warning messages that were generated during + execution of the restore. The actual warnings are stored in object storage. + type: integer + type: object + type: object + served: true + storage: true