From cc4ca3700642e7ff85ad5d90633302e9d4131312 Mon Sep 17 00:00:00 2001 From: Michal Pryc Date: Sun, 7 Sep 2025 22:39:28 +0200 Subject: [PATCH 1/3] Initial Non-Admin onboard to oadp-1.4 Signed-off-by: Michal Pryc --- Makefile | 2 +- api/v1alpha1/oadp_types.go | 111 ++ api/v1alpha1/zz_generated.deepcopy.go | 133 ++ ...c.authorization.k8s.io_v1_clusterrole.yaml | 21 + ...c.authorization.k8s.io_v1_clusterrole.yaml | 27 + ...c.authorization.k8s.io_v1_clusterrole.yaml | 23 + .../oadp-operator.clusterserviceversion.yaml | 885 +---------- .../oadp.openshift.io_nonadminbackups.yaml | 1380 +++++++++++++++++ ...nonadminbackupstoragelocationrequests.yaml | 195 +++ ...ift.io_nonadminbackupstoragelocations.yaml | 287 ++++ ...openshift.io_nonadmindownloadrequests.yaml | 190 +++ .../oadp.openshift.io_nonadminrestores.yaml | 755 +++++++++ ...enshift.io_dataprotectionapplications.yaml | 925 +++++++++++ config/crd/kustomization.yaml | 3 + config/manager/manager.yaml | 2 + .../oadp-operator.clusterserviceversion.yaml | 5 + config/manifests/kustomization.yaml | 2 + .../kustomization.yaml | 26 + .../nonadmindownloadrequest_admin_role.yaml | 27 + .../nonadmindownloadrequest_editor_role.yaml | 33 + .../nonadmindownloadrequest_viewer_role.yaml | 29 + config/non-admin-controller_rbac/role.yaml | 110 ++ .../role_binding.yaml | 19 + .../service_account.yaml | 12 + .../samples/oadp_v1alpha1_nonadminbackup.yaml | 12 + ...1alpha1_nonadminbackupstoragelocation.yaml | 22 + ..._nonadminbackupstoragelocationrequest.yaml | 12 + ...oadp_v1alpha1_nonadmindownloadrequest.yaml | 12 + .../oadp_v1alpha1_nonadminrestore.yaml | 13 + controllers/dpa_controller.go | 13 +- controllers/nonadmin_controller.go | 268 ++++ controllers/nonadmin_controller_test.go | 556 +++++++ controllers/velero.go | 4 + controllers/velero_test.go | 2 + go.mod | 2 +- main.go | 18 +- pkg/common/common.go | 2 + pkg/common/common_test.go | 2 + 38 files changed, 5248 insertions(+), 892 deletions(-) create mode 100644 bundle/manifests/nonadmindownloadrequest-admin-role_rbac.authorization.k8s.io_v1_clusterrole.yaml create mode 100644 bundle/manifests/nonadmindownloadrequest-editor-role_rbac.authorization.k8s.io_v1_clusterrole.yaml create mode 100644 bundle/manifests/nonadmindownloadrequest-viewer-role_rbac.authorization.k8s.io_v1_clusterrole.yaml create mode 100644 bundle/manifests/oadp.openshift.io_nonadminbackups.yaml create mode 100644 bundle/manifests/oadp.openshift.io_nonadminbackupstoragelocationrequests.yaml create mode 100644 bundle/manifests/oadp.openshift.io_nonadminbackupstoragelocations.yaml create mode 100644 bundle/manifests/oadp.openshift.io_nonadmindownloadrequests.yaml create mode 100644 bundle/manifests/oadp.openshift.io_nonadminrestores.yaml create mode 100644 config/non-admin-controller_rbac/kustomization.yaml create mode 100644 config/non-admin-controller_rbac/nonadmindownloadrequest_admin_role.yaml create mode 100644 config/non-admin-controller_rbac/nonadmindownloadrequest_editor_role.yaml create mode 100644 config/non-admin-controller_rbac/nonadmindownloadrequest_viewer_role.yaml create mode 100644 config/non-admin-controller_rbac/role.yaml create mode 100644 config/non-admin-controller_rbac/role_binding.yaml create mode 100644 config/non-admin-controller_rbac/service_account.yaml create mode 100644 config/samples/oadp_v1alpha1_nonadminbackup.yaml create mode 100644 config/samples/oadp_v1alpha1_nonadminbackupstoragelocation.yaml create mode 100644 config/samples/oadp_v1alpha1_nonadminbackupstoragelocationrequest.yaml create mode 100644 config/samples/oadp_v1alpha1_nonadmindownloadrequest.yaml create mode 100644 config/samples/oadp_v1alpha1_nonadminrestore.yaml create mode 100644 controllers/nonadmin_controller.go create mode 100644 controllers/nonadmin_controller_test.go diff --git a/Makefile b/Makefile index 23bfebbea20..8581e345d23 100644 --- a/Makefile +++ b/Makefile @@ -441,7 +441,7 @@ endef bundle: manifests kustomize operator-sdk ## Generate bundle manifests and metadata, then validate generated files. GOFLAGS="-mod=mod" $(OPERATOR_SDK) generate kustomize manifests -q cd config/manager && GOFLAGS="-mod=mod" $(KUSTOMIZE) edit set image controller=$(IMG) - GOFLAGS="-mod=mod" $(KUSTOMIZE) build config/manifests | GOFLAGS="-mod=mod" $(OPERATOR_SDK) generate bundle -q --extra-service-accounts "velero" --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS) + GOFLAGS="-mod=mod" $(KUSTOMIZE) build config/manifests | GOFLAGS="-mod=mod" $(OPERATOR_SDK) generate bundle -q --extra-service-accounts "velero,non-admin-controller" --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS) @make nullables # Copy updated bundle.Dockerfile to CI's Dockerfile.bundle # TODO: update CI to use generated one diff --git a/api/v1alpha1/oadp_types.go b/api/v1alpha1/oadp_types.go index f4ea6078897..c3d6505219f 100644 --- a/api/v1alpha1/oadp_types.go +++ b/api/v1alpha1/oadp_types.go @@ -52,6 +52,12 @@ type CustomPlugin struct { Name string `json:"name"` Image string `json:"image"` } +type LogFormat string + +const ( + LogFormatText LogFormat = "text" + LogFormatJSON LogFormat = "json" +) // Field does not have enum validation for development flexibility type UnsupportedImageKey string @@ -65,6 +71,7 @@ const GCPPluginImageKey UnsupportedImageKey = "gcpPluginImageFqin" const ResticRestoreImageKey UnsupportedImageKey = "resticRestoreImageFqin" const KubeVirtPluginImageKey UnsupportedImageKey = "kubevirtPluginImageFqin" const HypershiftPluginImageKey UnsupportedImageKey = "hypershiftPluginImageFqin" +const NonAdminControllerImageKey UnsupportedImageKey = "nonAdminControllerImageFqin" const OperatorTypeKey UnsupportedImageKey = "operator-type" const OperatorTypeMTC = "mtc" @@ -243,6 +250,102 @@ type SnapshotLocation struct { Velero *velero.VolumeSnapshotLocationSpec `json:"velero"` } +// We need to create enforcement structures for the BSL spec fields, because the Velero BSL spec +// is requiring fields like bucket, provider which are allowed to be empty for the enforcement in the DPA. + +// ObjectStorageLocation defines the enforced values for the Velero ObjectStorageLocation +type ObjectStorageLocation struct { + // Bucket is the bucket to use for object storage. + // +optional + Bucket string `json:"bucket,omitempty"` + + // Prefix is the path inside a bucket to use for Velero storage. Optional. + // +optional + Prefix string `json:"prefix,omitempty"` + + // CACert defines a CA bundle to use when verifying TLS connections to the provider. + // +optional + CACert []byte `json:"caCert,omitempty"` +} + +// StorageType defines the enforced values for the Velero StorageType +type StorageType struct { + // +optional + // +nullable + ObjectStorage *ObjectStorageLocation `json:"objectStorage,omitempty"` +} + +// EnforceBackupStorageLocationSpec defines the enforced values for the Velero BackupStorageLocationSpec +type EnforceBackupStorageLocationSpec struct { + // Provider is the provider of the backup storage. + // +optional + Provider string `json:"provider,omitempty"` + + // Config is for provider-specific configuration fields. + // +optional + Config map[string]string `json:"config,omitempty"` + + // Credential contains the credential information intended to be used with this location + // +optional + Credential *corev1.SecretKeySelector `json:"credential,omitempty"` + + StorageType `json:",inline"` + + // AccessMode defines the permissions for the backup storage location. + // +optional + AccessMode velero.BackupStorageLocationAccessMode `json:"accessMode,omitempty"` + + // BackupSyncPeriod defines how frequently to sync backup API objects from object storage. A value of 0 disables sync. + // +optional + // +nullable + BackupSyncPeriod *metav1.Duration `json:"backupSyncPeriod,omitempty"` + + // ValidationFrequency defines how frequently to validate the corresponding object storage. A value of 0 disables validation. + // +optional + // +nullable + ValidationFrequency *metav1.Duration `json:"validationFrequency,omitempty"` +} + +type NonAdmin struct { + // Enables non admin feature, by default is disabled + // +optional + Enable *bool `json:"enable,omitempty"` + + // which bakup spec field values to enforce + // +optional + EnforceBackupSpec *velero.BackupSpec `json:"enforceBackupSpec,omitempty"` + + // which restore spec field values to enforce + // +optional + EnforceRestoreSpec *velero.RestoreSpec `json:"enforceRestoreSpec,omitempty"` + + // which backupstoragelocation spec field values to enforce + // +optional + EnforceBSLSpec *EnforceBackupStorageLocationSpec `json:"enforceBSLSpec,omitempty"` + + // RequireApprovalForBSL specifies whether cluster administrator approval is required + // for creating Velero BackupStorageLocation (BSL) resources. + // - If set to false, all NonAdminBackupStorageLocationApproval CRDs will be automatically approved, + // including those that were previously pending or rejected. + // - If set to true, any existing BackupStorageLocation CRDs that lack the necessary approvals may be deleted, + // leaving the associated NonAdminBackup objects non-restorable until approval is granted. + // Defaults to false + // +optional + RequireApprovalForBSL *bool `json:"requireApprovalForBSL,omitempty"` + + // GarbageCollectionPeriod defines how frequently to look for possible leftover non admin related objects in OADP namespace. + // A value of 0 disables garbage collection. + // By default 24h + // +optional + GarbageCollectionPeriod *metav1.Duration `json:"garbageCollectionPeriod,omitempty"` + + // BackupSyncPeriod specifies the interval at which backups from the OADP namespace are synchronized with non-admin namespaces. + // A value of 0 disables sync. + // By default 2m + // +optional + BackupSyncPeriod *metav1.Duration `json:"backupSyncPeriod,omitempty"` +} + // DataMover defines the various config for DPA data mover type DataMover struct { // enable flag is used to specify whether you want to deploy the volume snapshot mover controller @@ -384,6 +487,14 @@ type DataProtectionApplicationSpec struct { // +optional // +kubebuilder:validation:Enum=Always;IfNotPresent;Never ImagePullPolicy *corev1.PullPolicy `json:"imagePullPolicy,omitempty"` + // nonAdmin defines the configuration for the DPA to enable backup and restore operations for non-admin users + // +optional + NonAdmin *NonAdmin `json:"nonAdmin,omitempty"` + // The format for log output. Valid values are text, json. (default text) + // +kubebuilder:validation:Enum=text;json + // +kubebuilder:default=text + // +optional + LogFormat LogFormat `json:"logFormat,omitempty"` } // DataProtectionApplicationStatus defines the observed state of DataProtectionApplication diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 9725625d0c9..41119dbcbbc 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -405,6 +405,11 @@ func (in *DataProtectionApplicationSpec) DeepCopyInto(out *DataProtectionApplica *out = new(v1.PullPolicy) **out = **in } + if in.NonAdmin != nil { + in, out := &in.NonAdmin, &out.NonAdmin + *out = new(NonAdmin) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataProtectionApplicationSpec. @@ -439,6 +444,44 @@ func (in *DataProtectionApplicationStatus) DeepCopy() *DataProtectionApplication return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EnforceBackupStorageLocationSpec) DeepCopyInto(out *EnforceBackupStorageLocationSpec) { + *out = *in + if in.Config != nil { + in, out := &in.Config, &out.Config + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Credential != nil { + in, out := &in.Credential, &out.Credential + *out = new(v1.SecretKeySelector) + (*in).DeepCopyInto(*out) + } + in.StorageType.DeepCopyInto(&out.StorageType) + if in.BackupSyncPeriod != nil { + in, out := &in.BackupSyncPeriod, &out.BackupSyncPeriod + *out = new(metav1.Duration) + **out = **in + } + if in.ValidationFrequency != nil { + in, out := &in.ValidationFrequency, &out.ValidationFrequency + *out = new(metav1.Duration) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnforceBackupStorageLocationSpec. +func (in *EnforceBackupStorageLocationSpec) DeepCopy() *EnforceBackupStorageLocationSpec { + if in == nil { + return nil + } + out := new(EnforceBackupStorageLocationSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Features) DeepCopyInto(out *Features) { *out = *in @@ -505,6 +548,76 @@ func (in *NodeAgentConfig) DeepCopy() *NodeAgentConfig { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NonAdmin) DeepCopyInto(out *NonAdmin) { + *out = *in + if in.Enable != nil { + in, out := &in.Enable, &out.Enable + *out = new(bool) + **out = **in + } + if in.EnforceBackupSpec != nil { + in, out := &in.EnforceBackupSpec, &out.EnforceBackupSpec + *out = new(velerov1.BackupSpec) + (*in).DeepCopyInto(*out) + } + if in.EnforceRestoreSpec != nil { + in, out := &in.EnforceRestoreSpec, &out.EnforceRestoreSpec + *out = new(velerov1.RestoreSpec) + (*in).DeepCopyInto(*out) + } + if in.EnforceBSLSpec != nil { + in, out := &in.EnforceBSLSpec, &out.EnforceBSLSpec + *out = new(EnforceBackupStorageLocationSpec) + (*in).DeepCopyInto(*out) + } + if in.RequireApprovalForBSL != nil { + in, out := &in.RequireApprovalForBSL, &out.RequireApprovalForBSL + *out = new(bool) + **out = **in + } + if in.GarbageCollectionPeriod != nil { + in, out := &in.GarbageCollectionPeriod, &out.GarbageCollectionPeriod + *out = new(metav1.Duration) + **out = **in + } + if in.BackupSyncPeriod != nil { + in, out := &in.BackupSyncPeriod, &out.BackupSyncPeriod + *out = new(metav1.Duration) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdmin. +func (in *NonAdmin) DeepCopy() *NonAdmin { + if in == nil { + return nil + } + out := new(NonAdmin) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ObjectStorageLocation) DeepCopyInto(out *ObjectStorageLocation) { + *out = *in + if in.CACert != nil { + in, out := &in.CACert, &out.CACert + *out = make([]byte, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectStorageLocation. +func (in *ObjectStorageLocation) DeepCopy() *ObjectStorageLocation { + if in == nil { + return nil + } + out := new(ObjectStorageLocation) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PodConfig) DeepCopyInto(out *PodConfig) { *out = *in @@ -600,6 +713,26 @@ func (in *SnapshotLocation) DeepCopy() *SnapshotLocation { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageType) DeepCopyInto(out *StorageType) { + *out = *in + if in.ObjectStorage != nil { + in, out := &in.ObjectStorage, &out.ObjectStorage + *out = new(ObjectStorageLocation) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageType. +func (in *StorageType) DeepCopy() *StorageType { + if in == nil { + return nil + } + out := new(StorageType) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VeleroConfig) DeepCopyInto(out *VeleroConfig) { *out = *in diff --git a/bundle/manifests/nonadmindownloadrequest-admin-role_rbac.authorization.k8s.io_v1_clusterrole.yaml b/bundle/manifests/nonadmindownloadrequest-admin-role_rbac.authorization.k8s.io_v1_clusterrole.yaml new file mode 100644 index 00000000000..d12e8f9d118 --- /dev/null +++ b/bundle/manifests/nonadmindownloadrequest-admin-role_rbac.authorization.k8s.io_v1_clusterrole.yaml @@ -0,0 +1,21 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + creationTimestamp: null + labels: + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/name: oadp-nac + name: nonadmindownloadrequest-admin-role +rules: +- apiGroups: + - oadp.openshift.io + resources: + - nonadmindownloadrequests + verbs: + - '*' +- apiGroups: + - oadp.openshift.io + resources: + - nonadmindownloadrequests/status + verbs: + - get diff --git a/bundle/manifests/nonadmindownloadrequest-editor-role_rbac.authorization.k8s.io_v1_clusterrole.yaml b/bundle/manifests/nonadmindownloadrequest-editor-role_rbac.authorization.k8s.io_v1_clusterrole.yaml new file mode 100644 index 00000000000..69660074eb1 --- /dev/null +++ b/bundle/manifests/nonadmindownloadrequest-editor-role_rbac.authorization.k8s.io_v1_clusterrole.yaml @@ -0,0 +1,27 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + creationTimestamp: null + labels: + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/name: oadp-nac + name: nonadmindownloadrequest-editor-role +rules: +- apiGroups: + - oadp.openshift.io + resources: + - nonadmindownloadrequests + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - oadp.openshift.io + resources: + - nonadmindownloadrequests/status + verbs: + - get diff --git a/bundle/manifests/nonadmindownloadrequest-viewer-role_rbac.authorization.k8s.io_v1_clusterrole.yaml b/bundle/manifests/nonadmindownloadrequest-viewer-role_rbac.authorization.k8s.io_v1_clusterrole.yaml new file mode 100644 index 00000000000..fca6f6f1d07 --- /dev/null +++ b/bundle/manifests/nonadmindownloadrequest-viewer-role_rbac.authorization.k8s.io_v1_clusterrole.yaml @@ -0,0 +1,23 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + creationTimestamp: null + labels: + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/name: oadp-nac + name: nonadmindownloadrequest-viewer-role +rules: +- apiGroups: + - oadp.openshift.io + resources: + - nonadmindownloadrequests + verbs: + - get + - list + - watch +- apiGroups: + - oadp.openshift.io + resources: + - nonadmindownloadrequests/status + verbs: + - get diff --git a/bundle/manifests/oadp-operator.clusterserviceversion.yaml b/bundle/manifests/oadp-operator.clusterserviceversion.yaml index 79a1e344aa7..cd4f8cc8eab 100644 --- a/bundle/manifests/oadp-operator.clusterserviceversion.yaml +++ b/bundle/manifests/oadp-operator.clusterserviceversion.yaml @@ -2,152 +2,7 @@ apiVersion: operators.coreos.com/v1alpha1 kind: ClusterServiceVersion metadata: annotations: - alm-examples: |- - [ - { - "apiVersion": "oadp.openshift.io/v1alpha1", - "kind": "DataProtectionApplication", - "metadata": { - "name": "velero-sample" - }, - "spec": { - "backupLocations": [ - { - "velero": { - "config": { - "profile": "default", - "region": "us-east-1" - }, - "credential": { - "key": "cloud", - "name": "cloud-credentials" - }, - "default": true, - "objectStorage": { - "bucket": "my-bucket-name", - "prefix": "velero" - }, - "provider": "aws" - } - } - ], - "configuration": { - "nodeAgent": { - "enable": true, - "uploaderType": "restic" - }, - "velero": { - "defaultPlugins": [ - "openshift", - "aws", - "kubevirt" - ] - } - }, - "snapshotLocations": [ - { - "velero": { - "config": { - "profile": "default", - "region": "us-west-2" - }, - "provider": "aws" - } - } - ] - } - }, - { - "apiVersion": "velero.io/v1", - "kind": "Backup", - "metadata": { - "name": "backup", - "namespace": "openshift-adp" - }, - "spec": {} - }, - { - "apiVersion": "velero.io/v1", - "kind": "BackupStorageLocation", - "metadata": { - "name": "backupstoragelocation", - "namespace": "openshift-adp" - }, - "spec": {} - }, - { - "apiVersion": "velero.io/v1", - "kind": "DeleteBackupRequest", - "metadata": { - "name": "deletebackuprequest", - "namespace": "openshift-adp" - }, - "spec": {} - }, - { - "apiVersion": "velero.io/v1", - "kind": "DownloadRequest", - "metadata": { - "name": "downloadrequest", - "namespace": "openshift-adp" - }, - "spec": {} - }, - { - "apiVersion": "velero.io/v1", - "kind": "PodVolumeBackup", - "metadata": { - "name": "podvolumebackup", - "namespace": "openshift-adp" - }, - "spec": {} - }, - { - "apiVersion": "velero.io/v1", - "kind": "PodVolumeRestore", - "metadata": { - "name": "podvolumerestore", - "namespace": "openshift-adp" - }, - "spec": {} - }, - { - "apiVersion": "velero.io/v1", - "kind": "Restore", - "metadata": { - "name": "restore", - "namespace": "openshift-adp" - }, - "spec": {} - }, - { - "apiVersion": "velero.io/v1", - "kind": "Schedule", - "metadata": { - "name": "schedule", - "namespace": "openshift-adp" - }, - "spec": {} - }, - { - "apiVersion": "velero.io/v1", - "kind": "ServerStatusRequest", - "metadata": { - "name": "serverstatusrequest", - "namespace": "openshift-adp" - }, - "spec": {} - }, - { - "apiVersion": "velero.io/v1", - "kind": "VolumeSnapshotLocation", - "metadata": { - "name": "volumesnapshotlocation", - "namespace": "openshift-adp" - }, - "spec": {} - } - ] + alm-examples: '[]' capabilities: Seamless Upgrades categories: | Cloud Provider,Developer Tools,Modernization & Migration,OpenShift Optional,Storage @@ -184,371 +39,7 @@ metadata: namespace: openshift-adp spec: apiservicedefinitions: {} - customresourcedefinitions: - owned: - - description: A backup repository is an indicator of a connection from the restic/kopia - server to the backupstoragelocation. - displayName: BackupRepository - kind: BackupRepository - name: backuprepositories.velero.io - statusDescriptors: - - description: Phase is the current state of the BackupRepository. - displayName: Phase - path: phase - - description: Message is a message about the current status of the BackupRepository. - displayName: Message - path: message - - description: LastMaintenanceTime is the last time maintenance was run. - displayName: LastMaintenanceTime - path: lastMaintenanceTime - version: v1 - - 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). - displayName: Backup - kind: Backup - name: backups.velero.io - statusDescriptors: - - 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. - displayName: CompletionTimestamp - path: completionTimestamp - - description: Expiration is when this Backup is eligible for garbage collection. - displayName: Expiration - path: expiration - - description: Format Version is the backup format version, including major, - minor, and patch version. - displayName: FormatVersion - path: formatVersion - - description: Phase is the current state of the Backup - displayName: Phase - path: phase - - 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. - displayName: Progress - path: progress - - description: Start Timestamp records the time a backup was started. Separate - from CreationTimestamp, since that value changes on restores. The server's - time is used for StartTimestamps. - displayName: StartTimestamp - path: startTimestamp - - description: ValidationErrors are a slice of all validation errors (if applicable). - displayName: Validation Errors - path: validationErrors - - description: VolumeSnapshotsAttempted is the total number of attempted volume - snapshots for this backup. - displayName: VolumeSnapshotsAttempted - path: volumeSnapshotsAttempted - - description: VolumeSnapshotsCompleted is the total number of successfully - completed volume snapshots for this backup. - displayName: VolumeSnapshotsCompleted - path: volumeSnapshotsCompleted - - 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. - displayName: Warnings - path: warnings - - 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. - displayName: Errors - path: errors - version: v1 - - description: BackupStorageLocation represents an object storage location (such - as Amazon S3 Bucket) where Velero stores backup objects. - displayName: BackupStorageLocation - kind: BackupStorageLocation - name: backupstoragelocations.velero.io - statusDescriptors: - - description: Phase is the current state of the BackupStorageLocation - displayName: Phase - path: phase - - description: LastSyncedTime is the last time the contents of the location - were synced into - displayName: LastSyncedTime - path: lastSyncedTime - - description: LastValidationTime is the last time the backup store location - was validated - displayName: LastValidationTime - path: lastValidationTime - version: v1 - - description: The CloudStorage API automates the creation of a bucket for object - storage. - displayName: CloudStorage - kind: CloudStorage - name: cloudstorages.oadp.openshift.io - statusDescriptors: - - description: LastSyncTimestamp is the last time the contents of the CloudStorage - was synced - displayName: LastSyncTimestamp - path: lastSyncTimestamp - - description: Name is the name requested for the bucket (aws, gcp) or container - (azure) - displayName: Name - path: name - version: v1alpha1 - - description: DataDownload represents a data download of a volume snapshot. There - is one DataDownload created per volume to be restored. - displayName: DataDownload - kind: DataDownload - name: datadownloads.velero.io - statusDescriptors: - - description: Phase is the current state of the DataDownload. - displayName: Phase - path: phase - - description: CompletionTimestamp records the time a restore was completed. - Completion time is recorded even on failed restores. The server's time is - used for CompletionTimestamps - displayName: CompletionTimestamp - path: completionTimestamp - - description: Message is a message about the current status of the BackupRepository. - displayName: Message - path: message - - description: Node is the name of the node where the DataDownload is processed. - displayName: Node - path: node - - description: Progress holds the total number of bytes of the snapshot and - the current number of restored bytes. This can be used to display progress - information about the restore operation. - displayName: Progress - path: progress - - description: StartTimestamp records the time a restore was started. The server's - time is used for StartTimestamps - displayName: StartTimestamp - path: startTimestamp - version: v2alpha1 - - description: DataProtectionApplication represents configuration to install a - data protection application to safely backup and restore, perform disaster - recovery and migrate Kubernetes cluster resources and persistent volumes. - displayName: DataProtectionApplication - kind: DataProtectionApplication - name: dataprotectionapplications.oadp.openshift.io - statusDescriptors: - - description: Conditions defines the observed state of DataProtectionApplication - displayName: Conditions - path: conditions - version: v1alpha1 - - description: DataUpload acts as the protocol between data mover plugins and - data mover controller for the datamover backup operation - displayName: DataUpload - kind: DataUpload - name: datauploads.velero.io - statusDescriptors: - - 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 - displayName: CompletionTimestamp - path: completionTimestamp - - description: DataMoverResult stores data-mover-specific information as a result - of the DataUpload. - displayName: DataMoverResult - path: dataMoverResult - - description: Message is a message about the DataUpload's status. - displayName: Message - path: message - - description: Node is the name of the node where the DataUpload is processed. - displayName: Node - path: node - - description: Path is the full path of the snapshot volume being backed up. - displayName: Path - path: path - - description: Phase is the current state of the DataUpload. - displayName: Phase - path: phase - - description: Progress holds the total number of bytes of the volume and the - current number of backed up bytes. This can be used to display progress - information about the backup operation. - displayName: Progress - path: progress - - description: SnapshotID is the identifier for the snapshot in the backup repository. - displayName: SnapshotID - path: snapshotID - - 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 - displayName: StartTimestamp - path: startTimestamp - version: v2alpha1 - - description: DeleteBackupRequest is a request to delete one or more backups. - displayName: DeleteBackupRequest - kind: DeleteBackupRequest - name: deletebackuprequests.velero.io - statusDescriptors: - - description: Phase is the current status of a DeleteBackupRequest - displayName: Phase - path: phase - - description: Errors contains any errors that were encountered during the deletion - process. - displayName: Errors - path: errors - version: v1 - - description: DownloadRequest is a request to download an artifact from object - storage such as a backup log file. - displayName: DownloadRequest - kind: DownloadRequest - name: downloadrequests.velero.io - statusDescriptors: - - description: Phase is the current state of the DownloadRequest. - displayName: Phase - path: phase - - description: DownloadURL contains the pre-signed URL for the target file. - displayName: DownloadURL - path: downloadURL - - description: Expiration is when this DownloadRequest expires and can be deleted - by the system. - displayName: Expiration - path: expiration - version: v1 - - description: A velero pod volume backup is a restic backup of persistent volumes - attached to a running pod. - displayName: PodVolumeBackup - kind: PodVolumeBackup - name: podvolumebackups.velero.io - statusDescriptors: - - description: Phase is the current state of the PodVolumeBackup. - displayName: Phase - path: phase - - description: Path is the full path within the controller pod being backed - up. - displayName: Path - path: path - - description: SnapshotID is the identifier for the snapshot of the pod volume. - displayName: SnapshotID - path: snapshotID - - description: Message is a message about the pod volume backup's status. - displayName: Message - path: message - - 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 - displayName: StartTimestamp - path: startTimestamp - - 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 - displayName: CompletionTimestamp - path: completionTimestamp - - description: Progress holds the total number of bytes of the volume and the - current number of backed up bytes. This can be used to display progress - information about the backup operation. - displayName: Progress - path: progress - version: v1 - - description: A velero pod volume restore is a restic restore of persistent volumes - attached to a running pod. - displayName: PodVolumeRestore - kind: PodVolumeRestore - name: podvolumerestores.velero.io - statusDescriptors: - - description: Phase is the current state of the PodVolumeRestore. - displayName: Phase - path: phase - - description: Message is a message about the pod volume restore's status. - displayName: Message - path: message - - description: StartTimestamp records the time a restore was started. The server's - time is used for StartTimestamps - displayName: StartTimestamp - path: startTimestamp - - description: CompletionTimestamp records the time a restore was completed. - Completion time is recorded even on failed restores. The server's time is - used for CompletionTimestamps - displayName: CompletionTimestamp - path: completionTimestamp - - description: Progress holds the total number of bytes of the snapshot and - the current number of restored bytes. This can be used to display progress - information about the restore operation. - displayName: Progress - path: progress - version: v1 - - description: Restore is a Velero resource that represents the application of - resources from a Velero backup to a target Kubernetes cluster. - displayName: Restore - kind: Restore - name: restores.velero.io - statusDescriptors: - - description: Phase is the current state of the Restore - displayName: Phase - path: phase - - description: ValidationErrors is a slice of all validation errors (if applicable) - displayName: ValidationErrors - path: validationErrors - - 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. - displayName: Warnings - path: warnings - - 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. - displayName: Errors - path: errors - - description: FailureReason is an error that caused the entire restore to fail. - displayName: FailureReason - path: failureReason - - description: StartTimestamp records the time the restore operation was started. - The server's time is used for StartTimestamps - displayName: StartTimestamp - path: startTimestamp - - 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 - displayName: CompletionTimestamp - path: completionTimestamp - - 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. - displayName: Progress - path: progress - version: v1 - - description: Schedule is a Velero resource that represents a pre-scheduled or - periodic Backup that should be run. - displayName: Schedule - kind: Schedule - name: schedules.velero.io - statusDescriptors: - - description: Phase is the current phase of the Schedule - displayName: Phase - path: phase - - description: LastBackup is the last time a Backup was run for this Schedule - schedule - displayName: LastBackup - path: lastBackup - - description: ValidationErrors is a slice of all validation errors (if applicable) - displayName: ValidationErrors - path: validationErrors - version: v1 - - description: ServerStatusRequest is a request to access current status information - about the Velero server. - displayName: ServerStatusRequest - kind: ServerStatusRequest - name: serverstatusrequests.velero.io - statusDescriptors: - - description: Phase is the current lifecycle phase of the ServerStatusRequest. - displayName: Phase - path: phase - - description: ProcessedTimestamp is when the ServerStatusRequest was processed - by the ServerStatusRequestController. - displayName: ProcessedTimestamp - path: processedTimestamp - - description: ServerVersion is the Velero server version. - displayName: ServerVersion - path: serverVersion - - description: Plugins list information about the plugins running on the Velero - server - displayName: Plugins - path: plugins - version: v1 - - description: VolumeSnapshotLocation is a location where Velero stores volume - snapshots. - displayName: VolumeSnapshotLocation - kind: VolumeSnapshotLocation - name: volumesnapshotlocations.velero.io - statusDescriptors: - - description: Phase is the current lifecycle phase of the VolumeSnapshotLocation - displayName: Phase - path: phase - version: v1 + customresourcedefinitions: {} description: | **OpenShift API for Data Protection (OADP)** operator sets up and installs Velero on the OpenShift platform, allowing users to backup and restore @@ -579,377 +70,7 @@ spec: mediatype: image/png install: spec: - clusterPermissions: - - rules: - - apiGroups: - - config.openshift.io - resources: - - infrastructures - verbs: - - get - - list - - watch - - apiGroups: - - cloudcredential.openshift.io - resources: - - credentialsrequests - verbs: - - create - - update - - get - - apiGroups: - - oadp.openshift.io - resources: - - '*' - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - apiGroups: - - coordination.k8s.io - - corev1 - resources: - - secrets - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - apiGroups: - - oadp.openshift.io - resources: - - buckets - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - apiGroups: - - oadp.openshift.io - resources: - - buckets/finalizers - verbs: - - update - - apiGroups: - - oadp.openshift.io - resources: - - buckets/status - verbs: - - get - - patch - - update - - apiGroups: - - oadp.openshift.io - resources: - - leases - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - apiGroups: - - velero.io - resources: - - '*' - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - apiGroups: - - security.openshift.io - resources: - - securitycontextconstraints - verbs: - - list - - get - - create - - delete - - patch - - update - - watch - - apiGroups: - - security.openshift.io - resourceNames: - - privileged - resources: - - securitycontextconstraints - verbs: - - use - - apiGroups: - - "" - resources: - - secrets - - configmaps - - pods - - services - - serviceaccounts - - endpoints - - persistentvolumeclaims - - events - verbs: - - list - - get - - create - - delete - - deletecollection - - patch - - update - - watch - - apiGroups: - - "" - resources: - - namespaces - verbs: - - list - - get - - create - - patch - - update - - watch - - apiGroups: - - apps - resources: - - deployments - - daemonsets - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - apiGroups: - - route.openshift.io - resources: - - routes - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - apiGroups: - - monitoring.coreos.com - resources: - - servicemonitors - verbs: - - get - - create - - list - - delete - - update - - patch - - watch - - apiGroups: - - authentication.k8s.io - resources: - - tokenreviews - verbs: - - create - - apiGroups: - - authorization.k8s.io - resources: - - subjectaccessreviews - verbs: - - create - serviceAccountName: openshift-adp-controller-manager - - rules: - - apiGroups: - - build.openshift.io - - migration.openshift.io - - rbac.authorization.k8s.io - - velero.io - resources: - - '*' - verbs: - - '*' - - apiGroups: - - "" - resources: - - serviceaccounts - verbs: - - '*' - - apiGroups: - - packages.operators.coreos.com - resources: - - packagemanifests - verbs: - - '*' - - apiGroups: - - '*' - resources: - - '*' - verbs: - - get - - watch - - list - - update - - patch - - create - - delete - - assign - - deletecollection - - nonResourceURLs: - - '*' - verbs: - - '*' - - apiGroups: - - security.openshift.io - resourceNames: - - privileged - resources: - - securitycontextconstraints - verbs: - - use - serviceAccountName: velero - deployments: - - label: - control-plane: controller-manager - name: openshift-adp-controller-manager - spec: - replicas: 1 - selector: - matchLabels: - control-plane: controller-manager - strategy: {} - template: - metadata: - labels: - control-plane: controller-manager - spec: - containers: - - args: - - --leader-elect - command: - - /manager - env: - - name: WATCH_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.annotations['olm.targetNamespaces'] - - name: RESTIC_PV_HOSTPATH - - name: FS_PV_HOSTPATH - - name: PLUGINS_HOSTPATH - - name: RELATED_IMAGE_VELERO - value: quay.io/konveyor/velero:oadp-1.4 - - name: RELATED_IMAGE_VELERO_RESTORE_HELPER - value: quay.io/konveyor/velero-restore-helper:oadp-1.4 - - name: RELATED_IMAGE_OPENSHIFT_VELERO_PLUGIN - value: quay.io/konveyor/openshift-velero-plugin:oadp-1.4 - - name: RELATED_IMAGE_VELERO_PLUGIN_FOR_AWS - value: quay.io/konveyor/velero-plugin-for-aws:oadp-1.4 - - name: RELATED_IMAGE_VELERO_PLUGIN_FOR_LEGACY_AWS - value: quay.io/konveyor/velero-plugin-for-legacy-aws:oadp-1.4 - - name: RELATED_IMAGE_VELERO_PLUGIN_FOR_MICROSOFT_AZURE - value: quay.io/konveyor/velero-plugin-for-microsoft-azure:oadp-1.4 - - name: RELATED_IMAGE_VELERO_PLUGIN_FOR_GCP - value: quay.io/konveyor/velero-plugin-for-gcp:oadp-1.4 - - name: RELATED_IMAGE_KUBEVIRT_VELERO_PLUGIN - value: quay.io/konveyor/kubevirt-velero-plugin:v0.7.0 - - name: RELATED_IMAGE_HYPERSHIFT_VELERO_PLUGIN - value: quay.io/redhat-user-workloads/ocp-art-tenant/oadp-hypershift-oadp-plugin-oadp-1-4 - - name: RELATED_IMAGE_MUSTGATHER - value: registry.redhat.io/oadp/oadp-mustgather-rhel8:v1.2 - image: quay.io/konveyor/oadp-operator:oadp-1.4 - imagePullPolicy: Always - livenessProbe: - httpGet: - path: /healthz - port: 8081 - initialDelaySeconds: 15 - periodSeconds: 20 - name: manager - readinessProbe: - httpGet: - path: /readyz - port: 8081 - initialDelaySeconds: 5 - periodSeconds: 10 - resources: - limits: - cpu: "1" - memory: 512Mi - requests: - cpu: 500m - memory: 128Mi - securityContext: - allowPrivilegeEscalation: false - startupProbe: - failureThreshold: 12 - httpGet: - path: /healthz - port: 8081 - periodSeconds: 10 - volumeMounts: - - mountPath: /var/run/secrets/openshift/serviceaccount - name: bound-sa-token - readOnly: true - securityContext: - runAsNonRoot: true - serviceAccountName: openshift-adp-controller-manager - terminationGracePeriodSeconds: 10 - volumes: - - name: bound-sa-token - projected: - sources: - - serviceAccountToken: - audience: openshift - expirationSeconds: 3600 - path: token - permissions: - - rules: - - apiGroups: - - "" - resources: - - configmaps - verbs: - - get - - list - - watch - - create - - update - - patch - - delete - - apiGroups: - - coordination.k8s.io - resources: - - leases - verbs: - - get - - list - - watch - - create - - update - - patch - - delete - - apiGroups: - - "" - resources: - - events - verbs: - - create - - patch - serviceAccountName: openshift-adp-controller-manager + deployments: [] strategy: deployment installModes: - supported: true diff --git a/bundle/manifests/oadp.openshift.io_nonadminbackups.yaml b/bundle/manifests/oadp.openshift.io_nonadminbackups.yaml new file mode 100644 index 00000000000..75df43810be --- /dev/null +++ b/bundle/manifests/oadp.openshift.io_nonadminbackups.yaml @@ -0,0 +1,1380 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + creationTimestamp: null + name: nonadminbackups.oadp.openshift.io +spec: + group: oadp.openshift.io + names: + kind: NonAdminBackup + listKind: NonAdminBackupList + plural: nonadminbackups + shortNames: + - nab + singular: nonadminbackup + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.phase + name: Request-Phase + type: string + - jsonPath: .status.veleroBackup.status.phase + name: Velero-Phase + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: NonAdminBackup is the Schema for the nonadminbackups 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: NonAdminBackupSpec defines the desired state of NonAdminBackup + properties: + backupSpec: + 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 + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + 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 + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + 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 + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + 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 + deleteBackup: + description: |- + DeleteBackup removes the NonAdminBackup and its associated NonAdminRestores and VeleroBackup from the cluster, + as well as the corresponding data in object storage + type: boolean + required: + - backupSpec + type: object + status: + description: NonAdminBackupStatus defines the observed state of NonAdminBackup + properties: + conditions: + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + dataMoverDataUploads: + description: DataMoverDataUploads contains information of the related + Velero DataUpload objects. + properties: + accepted: + description: number of DataUploads related to this NonAdminBackup's + Backup in phase Accepted + type: integer + canceled: + description: number of DataUploads related to this NonAdminBackup's + Backup in phase Canceled + type: integer + canceling: + description: number of DataUploads related to this NonAdminBackup's + Backup in phase Canceling + type: integer + completed: + description: number of DataUploads related to this NonAdminBackup's + Backup in phase Completed + type: integer + failed: + description: number of DataUploads related to this NonAdminBackup's + Backup in phase Failed + type: integer + inProgress: + description: number of DataUploads related to this NonAdminBackup's + Backup in phase InProgress + type: integer + new: + description: number of DataUploads related to this NonAdminBackup's + Backup in phase New + type: integer + prepared: + description: number of DataUploads related to this NonAdminBackup's + Backup in phase Prepared + type: integer + total: + description: number of DataUploads related to this NonAdminBackup's + Backup + type: integer + type: object + fileSystemPodVolumeBackups: + description: FileSystemPodVolumeBackups contains information of the + related Velero PodVolumeBackup objects. + properties: + completed: + description: number of PodVolumeBackups related to this NonAdminBackup's + Backup in phase Completed + type: integer + failed: + description: number of PodVolumeBackups related to this NonAdminBackup's + Backup in phase Failed + type: integer + inProgress: + description: number of PodVolumeBackups related to this NonAdminBackup's + Backup in phase InProgress + type: integer + new: + description: number of PodVolumeBackups related to this NonAdminBackup's + Backup in phase New + type: integer + total: + description: number of PodVolumeBackups related to this NonAdminBackup's + Backup + type: integer + type: object + phase: + description: phase is a simple one high-level summary of the lifecycle + of an NonAdminBackup. + enum: + - New + - BackingOff + - Created + - Deleting + type: string + queueInfo: + description: |- + queueInfo is used to estimate how many backups are scheduled before the given VeleroBackup in the OADP namespace. + This number is not guaranteed to be accurate, but it should be close. It's inaccurate for cases when + Velero pod is not running or being restarted after Backup object were created. + It counts only VeleroBackups that are still subject to be handled by OADP/Velero. + properties: + estimatedQueuePosition: + description: estimatedQueuePosition is the number of operations + ahead in the queue (0 if not queued) + type: integer + required: + - estimatedQueuePosition + type: object + veleroBackup: + description: VeleroBackup contains information of the related Velero + backup object. + properties: + nacuuid: + description: nacuuid references the Velero Backup object by it's + label containing same NACUUID. + type: string + name: + description: references the Velero Backup object by it's name. + type: string + namespace: + description: namespace references the Namespace in which Velero + backup exists. + type: string + spec: + description: spec captures the current spec of the 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 + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + 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 + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + 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 + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + 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: status captures the current status of the 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 + veleroDeleteBackupRequest: + description: VeleroDeleteBackupRequest contains information of the + related Velero delete backup request object. + properties: + nacuuid: + description: nacuuid references the Velero delete backup request + object by it's label containing same NACUUID. + type: string + name: + description: name references the Velero delete backup request + object by it's name. + type: string + namespace: + description: namespace references the Namespace in which Velero + delete backup request exists. + type: string + status: + description: status captures the current status of the Velero + delete backup request. + properties: + errors: + description: Errors contains any errors that were encountered + during the deletion process. + items: + type: string + nullable: true + type: array + phase: + description: Phase is the current state of the DeleteBackupRequest. + enum: + - New + - InProgress + - Processed + type: string + type: object + type: object + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null diff --git a/bundle/manifests/oadp.openshift.io_nonadminbackupstoragelocationrequests.yaml b/bundle/manifests/oadp.openshift.io_nonadminbackupstoragelocationrequests.yaml new file mode 100644 index 00000000000..0f1f473a48e --- /dev/null +++ b/bundle/manifests/oadp.openshift.io_nonadminbackupstoragelocationrequests.yaml @@ -0,0 +1,195 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + creationTimestamp: null + name: nonadminbackupstoragelocationrequests.oadp.openshift.io +spec: + group: oadp.openshift.io + names: + kind: NonAdminBackupStorageLocationRequest + listKind: NonAdminBackupStorageLocationRequestList + plural: nonadminbackupstoragelocationrequests + shortNames: + - nabslrequest + singular: nonadminbackupstoragelocationrequest + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.phase + name: Request-Phase + type: string + - jsonPath: .status.nonAdminBackupStorageLocation.namespace + name: Request-Namespace + type: string + - jsonPath: .status.nonAdminBackupStorageLocation.name + name: Request-Name + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: NonAdminBackupStorageLocationRequest is the Schema for the nonadminbackupstoragelocationrequests + 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: NonAdminBackupStorageLocationRequestSpec defines the desired + state of NonAdminBackupStorageLocationRequest + properties: + approvalDecision: + description: |- + approvalDecision is the decision of the cluster admin on the Requested NonAdminBackupStorageLocation creation. + The value may be set to either approve or reject. + enum: + - approve + - reject + - pending + type: string + type: object + status: + description: NonAdminBackupStorageLocationRequestStatus defines the observed + state of NonAdminBackupStorageLocationRequest + properties: + nonAdminBackupStorageLocation: + description: nonAdminBackupStorageLocation contains information of + the NonAdminBackupStorageLocation object that triggered NonAdminBSLRequest + properties: + nacuuid: + description: nacuuid references the NonAdminBackupStorageLocation + object by it's label containing same NACUUID. + type: string + name: + description: name references the NonAdminBackupStorageLocation + object by it's name. + type: string + namespace: + description: namespace references the Namespace in which NonAdminBackupStorageLocation + exists. + type: string + requestedSpec: + description: requestedSpec contains the requested Velero BackupStorageLocation + spec from the NonAdminBackupStorageLocation + properties: + accessMode: + description: AccessMode defines the permissions for the backup + storage location. + enum: + - ReadOnly + - ReadWrite + type: string + backupSyncPeriod: + description: BackupSyncPeriod defines how frequently to sync + backup API objects from object storage. A value of 0 disables + sync. + nullable: true + type: string + config: + additionalProperties: + type: string + description: Config is for provider-specific configuration + fields. + type: object + credential: + description: Credential contains the credential information + intended to be used with this location + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + default: + description: Default indicates this location is the default + backup storage location. + type: boolean + objectStorage: + description: ObjectStorageLocation specifies the settings + necessary to connect to a provider's object storage. + properties: + bucket: + description: Bucket is the bucket to use for object storage. + type: string + caCert: + description: CACert defines a CA bundle to use when verifying + TLS connections to the provider. + format: byte + type: string + prefix: + description: Prefix is the path inside a bucket to use + for Velero storage. Optional. + type: string + required: + - bucket + type: object + provider: + description: Provider is the provider of the backup storage. + type: string + validationFrequency: + description: ValidationFrequency defines how frequently to + validate the corresponding object storage. A value of 0 + disables validation. + nullable: true + type: string + required: + - objectStorage + - provider + type: object + required: + - requestedSpec + type: object + phase: + description: phase represents the current state of the NonAdminBSLRequest. + It can be either Pending, Approved or Rejected. + enum: + - Pending + - Approved + - Rejected + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null diff --git a/bundle/manifests/oadp.openshift.io_nonadminbackupstoragelocations.yaml b/bundle/manifests/oadp.openshift.io_nonadminbackupstoragelocations.yaml new file mode 100644 index 00000000000..ae737171d4d --- /dev/null +++ b/bundle/manifests/oadp.openshift.io_nonadminbackupstoragelocations.yaml @@ -0,0 +1,287 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + creationTimestamp: null + name: nonadminbackupstoragelocations.oadp.openshift.io +spec: + group: oadp.openshift.io + names: + kind: NonAdminBackupStorageLocation + listKind: NonAdminBackupStorageLocationList + plural: nonadminbackupstoragelocations + shortNames: + - nabsl + singular: nonadminbackupstoragelocation + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=='ClusterAdminApproved')].status + name: Request-Approved + type: string + - jsonPath: .status.phase + name: Request-Phase + type: string + - jsonPath: .status.veleroBackupStorageLocation.status.phase + name: Velero-Phase + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: NonAdminBackupStorageLocation is the Schema for the nonadminbackupstoragelocations + 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: NonAdminBackupStorageLocationSpec defines the desired state + of NonAdminBackupStorageLocation + properties: + backupStorageLocationSpec: + description: BackupStorageLocationSpec defines the desired state of + a Velero BackupStorageLocation + properties: + accessMode: + description: AccessMode defines the permissions for the backup + storage location. + enum: + - ReadOnly + - ReadWrite + type: string + backupSyncPeriod: + description: BackupSyncPeriod defines how frequently to sync backup + API objects from object storage. A value of 0 disables sync. + nullable: true + type: string + config: + additionalProperties: + type: string + description: Config is for provider-specific configuration fields. + type: object + credential: + description: Credential contains the credential information intended + to be used with this location + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key must be + defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + default: + description: Default indicates this location is the default backup + storage location. + type: boolean + objectStorage: + description: ObjectStorageLocation specifies the settings necessary + to connect to a provider's object storage. + properties: + bucket: + description: Bucket is the bucket to use for object storage. + type: string + caCert: + description: CACert defines a CA bundle to use when verifying + TLS connections to the provider. + format: byte + type: string + prefix: + description: Prefix is the path inside a bucket to use for + Velero storage. Optional. + type: string + required: + - bucket + type: object + provider: + description: Provider is the provider of the backup storage. + type: string + validationFrequency: + description: ValidationFrequency defines how frequently to validate + the corresponding object storage. A value of 0 disables validation. + nullable: true + type: string + required: + - objectStorage + - provider + type: object + required: + - backupStorageLocationSpec + type: object + status: + description: NonAdminBackupStorageLocationStatus defines the observed + state of NonAdminBackupStorageLocation + properties: + conditions: + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + phase: + description: phase is a simple one high-level summary of the lifecycle + of an NonAdminBackupStorageLocation. + enum: + - New + - BackingOff + - Created + - Deleting + type: string + veleroBackupStorageLocation: + description: VeleroBackupStorageLocation contains information of the + related Velero backup object. + properties: + nacuuid: + description: nacuuid references the Velero BackupStorageLocation + object by it's label containing same NACUUID. + type: string + name: + description: references the Velero BackupStorageLocation object + by it's name. + type: string + namespace: + description: namespace references the Namespace in which Velero + backup storage location exists. + type: string + status: + description: status captures the current status of the Velero + backup storage location. + properties: + accessMode: + description: |- + AccessMode is an unused field. + + Deprecated: there is now an AccessMode field on the Spec and this field + will be removed entirely as of v2.0. + enum: + - ReadOnly + - ReadWrite + type: string + lastSyncedRevision: + description: |- + LastSyncedRevision is the value of the `metadata/revision` file in the backup + storage location the last time the BSL's contents were synced into the cluster. + + Deprecated: this field is no longer updated or used for detecting changes to + the location's contents and will be removed entirely in v2.0. + type: string + lastSyncedTime: + description: |- + LastSyncedTime is the last time the contents of the location were synced into + the cluster. + format: date-time + nullable: true + type: string + lastValidationTime: + description: |- + LastValidationTime is the last time the backup store location was validated + the cluster. + format: date-time + nullable: true + type: string + message: + description: Message is a message about the backup storage + location's status. + type: string + phase: + description: Phase is the current state of the BackupStorageLocation. + enum: + - Available + - Unavailable + type: string + type: object + type: object + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null diff --git a/bundle/manifests/oadp.openshift.io_nonadmindownloadrequests.yaml b/bundle/manifests/oadp.openshift.io_nonadmindownloadrequests.yaml new file mode 100644 index 00000000000..08290cb3fe9 --- /dev/null +++ b/bundle/manifests/oadp.openshift.io_nonadmindownloadrequests.yaml @@ -0,0 +1,190 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + creationTimestamp: null + name: nonadmindownloadrequests.oadp.openshift.io +spec: + group: oadp.openshift.io + names: + kind: NonAdminDownloadRequest + listKind: NonAdminDownloadRequestList + plural: nonadmindownloadrequests + shortNames: + - nadr + singular: nonadmindownloadrequest + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.phase + name: Request-Phase + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: NonAdminDownloadRequest is the Schema for the nonadmindownloadrequests + 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: |- + NonAdminDownloadRequestSpec defines the desired state of NonAdminDownloadRequest. + Mirrors velero DownloadRequestSpec to allow non admins to download information for a non admin backup/restore + properties: + target: + description: Target is what to download (e.g. logs for a backup). + properties: + kind: + description: Kind is the type of file to download. + enum: + - BackupLog + - BackupContents + - BackupVolumeSnapshots + - BackupItemOperations + - BackupResourceList + - BackupResults + - RestoreLog + - RestoreResults + - RestoreResourceList + - RestoreItemOperations + - CSIBackupVolumeSnapshots + - CSIBackupVolumeSnapshotContents + - BackupVolumeInfos + - RestoreVolumeInfo + type: string + name: + description: Name is the name of the Kubernetes resource with + which the file is associated. + type: string + required: + - kind + - name + type: object + required: + - target + type: object + status: + description: NonAdminDownloadRequestStatus defines the observed state + of NonAdminDownloadRequest. + properties: + conditions: + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + phase: + description: phase is a simple one high-level summary of the lifecycle + of an NonAdminDownloadRequest + enum: + - New + - BackingOff + - Created + - Deleting + type: string + velero: + description: VeleroDownloadRequest represents VeleroDownloadRequest + properties: + status: + description: VeleroDownloadRequestStatus represents VeleroDownloadRequestStatus + properties: + downloadURL: + description: DownloadURL contains the pre-signed URL for the + target file. + type: string + expiration: + description: Expiration is when this DownloadRequest expires + and can be deleted by the system. + format: date-time + nullable: true + type: string + phase: + description: Phase is the current state of the DownloadRequest. + enum: + - New + - Processed + type: string + type: object + type: object + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null diff --git a/bundle/manifests/oadp.openshift.io_nonadminrestores.yaml b/bundle/manifests/oadp.openshift.io_nonadminrestores.yaml new file mode 100644 index 00000000000..42d4a9a0506 --- /dev/null +++ b/bundle/manifests/oadp.openshift.io_nonadminrestores.yaml @@ -0,0 +1,755 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + creationTimestamp: null + name: nonadminrestores.oadp.openshift.io +spec: + group: oadp.openshift.io + names: + kind: NonAdminRestore + listKind: NonAdminRestoreList + plural: nonadminrestores + shortNames: + - nar + singular: nonadminrestore + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.phase + name: Request-Phase + type: string + - jsonPath: .status.veleroRestore.status.phase + name: Velero-Phase + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: NonAdminRestore is the Schema for the nonadminrestores 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: NonAdminRestoreSpec defines the desired state of NonAdminRestore + properties: + restoreSpec: + 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 + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + 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 + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + 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 + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + 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 + required: + - restoreSpec + type: object + status: + description: NonAdminRestoreStatus defines the observed state of NonAdminRestore + properties: + conditions: + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + dataMoverDataDownloads: + description: DataMoverDataDownloads contains information of the related + Velero DataDownload objects. + properties: + accepted: + description: number of DataDownloads related to this NonAdminRestore's + Restore in phase Accepted + type: integer + canceled: + description: number of DataDownloads related to this NonAdminRestore's + Restore in phase Canceled + type: integer + canceling: + description: number of DataDownloads related to this NonAdminRestore's + Restore in phase Canceling + type: integer + completed: + description: number of DataDownloads related to this NonAdminRestore's + Restore in phase Completed + type: integer + failed: + description: number of DataDownloads related to this NonAdminRestore's + Restore in phase Failed + type: integer + inProgress: + description: number of DataDownloads related to this NonAdminRestore's + Restore in phase InProgress + type: integer + new: + description: number of DataDownloads related to this NonAdminRestore's + Restore in phase New + type: integer + prepared: + description: number of DataDownloads related to this NonAdminRestore's + Restore in phase Prepared + type: integer + total: + description: number of DataDownloads related to this NonAdminRestore's + Restore + type: integer + type: object + fileSystemPodVolumeRestores: + description: FileSystemPodVolumeRestores contains information of the + related Velero PodVolumeRestore objects. + properties: + completed: + description: number of PodVolumeRestores related to this NonAdminRestore's + Restore in phase Completed + type: integer + failed: + description: number of PodVolumeRestores related to this NonAdminRestore's + Restore in phase Failed + type: integer + inProgress: + description: number of PodVolumeRestores related to this NonAdminRestore's + Restore in phase InProgress + type: integer + new: + description: number of PodVolumeRestores related to this NonAdminRestore's + Restore in phase New + type: integer + total: + description: number of PodVolumeRestores related to this NonAdminRestore's + Restore + type: integer + type: object + phase: + description: phase is a simple one high-level summary of the lifecycle + of an NonAdminRestore. + enum: + - New + - BackingOff + - Created + - Deleting + type: string + queueInfo: + description: |- + queueInfo is used to estimate how many restores are scheduled before the given VeleroRestore in the OADP namespace. + This number is not guaranteed to be accurate, but it should be close. It's inaccurate for cases when + Velero pod is not running or being restarted after Restore object were created. + It counts only VeleroRestores that are still subject to be handled by OADP/Velero. + properties: + estimatedQueuePosition: + description: estimatedQueuePosition is the number of operations + ahead in the queue (0 if not queued) + type: integer + required: + - estimatedQueuePosition + type: object + veleroRestore: + description: VeleroRestore contains information of the related Velero + restore object. + properties: + nacuuid: + description: nacuuid references the Velero Restore object by it's + label containing same NACUUID. + type: string + name: + description: references the Velero Restore object by it's name. + type: string + namespace: + description: namespace references the Namespace in which Velero + Restore exists. + type: string + status: + description: status captures the current status of the 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 + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null diff --git a/config/crd/bases/oadp.openshift.io_dataprotectionapplications.yaml b/config/crd/bases/oadp.openshift.io_dataprotectionapplications.yaml index 71ff673d9d0..0bbe17b8e39 100644 --- a/config/crd/bases/oadp.openshift.io_dataprotectionapplications.yaml +++ b/config/crd/bases/oadp.openshift.io_dataprotectionapplications.yaml @@ -1204,6 +1204,931 @@ spec: - IfNotPresent - Never type: string + logFormat: + default: text + description: The format for log output. Valid values are text, json. (default text) + enum: + - text + - json + type: string + nonAdmin: + description: nonAdmin defines the configuration for the DPA to enable backup and restore operations for non-admin users + properties: + backupSyncPeriod: + description: |- + BackupSyncPeriod specifies the interval at which backups from the OADP namespace are synchronized with non-admin namespaces. + A value of 0 disables sync. + By default 2m + type: string + enable: + description: Enables non admin feature, by default is disabled + type: boolean + enforceBSLSpec: + description: which backupstoragelocation spec field values to enforce + properties: + accessMode: + description: AccessMode defines the permissions for the backup storage location. + enum: + - ReadOnly + - ReadWrite + type: string + backupSyncPeriod: + description: BackupSyncPeriod defines how frequently to sync backup API objects from object storage. A value of 0 disables sync. + nullable: true + type: string + config: + additionalProperties: + type: string + description: Config is for provider-specific configuration fields. + type: object + credential: + description: Credential contains the credential information intended to be used with this location + properties: + key: + description: The key of the secret to select from. Must be a valid secret key. + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + objectStorage: + description: ObjectStorageLocation defines the enforced values for the Velero ObjectStorageLocation + nullable: true + properties: + bucket: + description: Bucket is the bucket to use for object storage. + type: string + caCert: + description: CACert defines a CA bundle to use when verifying TLS connections to the provider. + format: byte + type: string + prefix: + description: Prefix is the path inside a bucket to use for Velero storage. Optional. + type: string + type: object + provider: + description: Provider is the provider of the backup storage. + type: string + validationFrequency: + description: ValidationFrequency defines how frequently to validate the corresponding object storage. A value of 0 disables validation. + nullable: true + type: string + type: object + enforceBackupSpec: + description: which bakup spec field values to enforce + 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 + enforceRestoreSpec: + description: which restore spec field values to enforce + 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 + garbageCollectionPeriod: + description: |- + GarbageCollectionPeriod defines how frequently to look for possible leftover non admin related objects in OADP namespace. + A value of 0 disables garbage collection. + By default 24h + type: string + requireApprovalForBSL: + description: |- + RequireApprovalForBSL specifies whether cluster administrator approval is required + for creating Velero BackupStorageLocation (BSL) resources. + - If set to false, all NonAdminBackupStorageLocationApproval CRDs will be automatically approved, + including those that were previously pending or rejected. + - If set to true, any existing BackupStorageLocation CRDs that lack the necessary approvals may be deleted, + leaving the associated NonAdminBackup objects non-restorable until approval is granted. + Defaults to false + type: boolean + type: object podAnnotations: additionalProperties: type: string diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index 4f18352b286..2971b10189d 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -17,6 +17,9 @@ resources: - bases/velero.io_schedules.yaml - bases/velero.io_serverstatusrequests.yaml - bases/velero.io_volumesnapshotlocations.yaml +- bases/oadp.openshift.io_nonadminbackups.yaml +- bases/oadp.openshift.io_nonadminrestores.yaml +- bases/oadp.openshift.io_nonadmindownloadrequests.yaml #+kubebuilder:scaffold:crdkustomizeresource patchesStrategicMerge: diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml index fbde35999a3..c4bf98b93ec 100644 --- a/config/manager/manager.yaml +++ b/config/manager/manager.yaml @@ -62,6 +62,8 @@ spec: value: quay.io/redhat-user-workloads/ocp-art-tenant/oadp-hypershift-oadp-plugin-oadp-1-4 - name: RELATED_IMAGE_MUSTGATHER value: registry.redhat.io/oadp/oadp-mustgather-rhel8:v1.2 + - name: RELATED_IMAGE_NON_ADMIN_CONTROLLER + value: quay.io/konveyor/oadp-non-admin:oadp-1.4 args: - --leader-elect image: controller:latest diff --git a/config/manifests/bases/oadp-operator.clusterserviceversion.yaml b/config/manifests/bases/oadp-operator.clusterserviceversion.yaml index c81c83ca2e3..3a163e08fec 100644 --- a/config/manifests/bases/oadp-operator.clusterserviceversion.yaml +++ b/config/manifests/bases/oadp-operator.clusterserviceversion.yaml @@ -401,6 +401,11 @@ spec: displayName: Name path: name version: v1alpha1 + - description: NonAdminBackup is the Schema for the nonadminbackups API + displayName: Non Admin Backup + kind: NonAdminBackup + name: nonadminbackups.nac.oadp.openshift.io + version: v1alpha1 description: | **OpenShift API for Data Protection (OADP)** operator sets up and installs Velero on the OpenShift platform, allowing users to backup and restore diff --git a/config/manifests/kustomization.yaml b/config/manifests/kustomization.yaml index 0a5c4052a13..cf9f275775a 100644 --- a/config/manifests/kustomization.yaml +++ b/config/manifests/kustomization.yaml @@ -6,6 +6,8 @@ resources: - ../samples - ../scorecard - ../velero +- ../non-admin-controller_rbac + # [WEBHOOK] To enable webhooks, uncomment all the sections with [WEBHOOK] prefix. # Do NOT uncomment sections with prefix [CERTMANAGER], as OLM does not support cert-manager. diff --git a/config/non-admin-controller_rbac/kustomization.yaml b/config/non-admin-controller_rbac/kustomization.yaml new file mode 100644 index 00000000000..758575ef776 --- /dev/null +++ b/config/non-admin-controller_rbac/kustomization.yaml @@ -0,0 +1,26 @@ +resources: +# All RBAC will be applied under this service account in +# the deployment namespace. You may comment out this resource +# if your manager will use a service account that exists at +# runtime. Be sure to update RoleBinding and ClusterRoleBinding +# subjects if changing service account names. +- service_account.yaml +- role.yaml +- role_binding.yaml +# - leader_election_role.yaml +# - leader_election_role_binding.yaml +# Comment the following 4 lines if you want to disable +# the auth proxy (https://github.com/brancz/kube-rbac-proxy) +# which protects your /metrics endpoint. +# - auth_proxy_service.yaml +# - auth_proxy_role.yaml +# - auth_proxy_role_binding.yaml +# - auth_proxy_client_clusterrole.yaml +# For each CRD, "Admin", "Editor" and "Viewer" roles are scaffolded by +# default, aiding admins in cluster management. Those roles are +# not used by the {{ .ProjectName }} itself. You can comment the following lines +# if you do not want those helpers be installed with your Project. +- nonadmindownloadrequest_admin_role.yaml +- nonadmindownloadrequest_editor_role.yaml +- nonadmindownloadrequest_viewer_role.yaml + diff --git a/config/non-admin-controller_rbac/nonadmindownloadrequest_admin_role.yaml b/config/non-admin-controller_rbac/nonadmindownloadrequest_admin_role.yaml new file mode 100644 index 00000000000..a1e5df37886 --- /dev/null +++ b/config/non-admin-controller_rbac/nonadmindownloadrequest_admin_role.yaml @@ -0,0 +1,27 @@ +# This rule is not used by the project oadp-nac itself. +# It is provided to allow the cluster admin to help manage permissions for users. +# +# Grants full permissions ('*') over oadp.openshift.io. +# This role is intended for users authorized to modify roles and bindings within the cluster, +# enabling them to delegate specific permissions to other users or groups as needed. + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: oadp-nac + app.kubernetes.io/managed-by: kustomize + name: nonadmindownloadrequest-admin-role +rules: +- apiGroups: + - oadp.openshift.io + resources: + - nonadmindownloadrequests + verbs: + - '*' +- apiGroups: + - oadp.openshift.io + resources: + - nonadmindownloadrequests/status + verbs: + - get diff --git a/config/non-admin-controller_rbac/nonadmindownloadrequest_editor_role.yaml b/config/non-admin-controller_rbac/nonadmindownloadrequest_editor_role.yaml new file mode 100644 index 00000000000..a71d1f36401 --- /dev/null +++ b/config/non-admin-controller_rbac/nonadmindownloadrequest_editor_role.yaml @@ -0,0 +1,33 @@ +# This rule is not used by the project oadp-nac itself. +# It is provided to allow the cluster admin to help manage permissions for users. +# +# Grants permissions to create, update, and delete resources within the oadp.openshift.io. +# This role is intended for users who need to manage these resources +# but should not control RBAC or manage permissions for others. + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: oadp-nac + app.kubernetes.io/managed-by: kustomize + name: nonadmindownloadrequest-editor-role +rules: +- apiGroups: + - oadp.openshift.io + resources: + - nonadmindownloadrequests + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - oadp.openshift.io + resources: + - nonadmindownloadrequests/status + verbs: + - get diff --git a/config/non-admin-controller_rbac/nonadmindownloadrequest_viewer_role.yaml b/config/non-admin-controller_rbac/nonadmindownloadrequest_viewer_role.yaml new file mode 100644 index 00000000000..6674dedb294 --- /dev/null +++ b/config/non-admin-controller_rbac/nonadmindownloadrequest_viewer_role.yaml @@ -0,0 +1,29 @@ +# This rule is not used by the project oadp-nac itself. +# It is provided to allow the cluster admin to help manage permissions for users. +# +# Grants read-only access to oadp.openshift.io resources. +# This role is intended for users who need visibility into these resources +# without permissions to modify them. It is ideal for monitoring purposes and limited-access viewing. + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: oadp-nac + app.kubernetes.io/managed-by: kustomize + name: nonadmindownloadrequest-viewer-role +rules: +- apiGroups: + - oadp.openshift.io + resources: + - nonadmindownloadrequests + verbs: + - get + - list + - watch +- apiGroups: + - oadp.openshift.io + resources: + - nonadmindownloadrequests/status + verbs: + - get diff --git a/config/non-admin-controller_rbac/role.yaml b/config/non-admin-controller_rbac/role.yaml new file mode 100644 index 00000000000..4da2508875e --- /dev/null +++ b/config/non-admin-controller_rbac/role.yaml @@ -0,0 +1,110 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: non-admin-controller-role +rules: +- apiGroups: + - "" + resources: + - namespaces + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - secrets + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - oadp.openshift.io + resources: + - dataprotectionapplications + verbs: + - list +- apiGroups: + - oadp.openshift.io + resources: + - nonadminbackups + - nonadminbackupstoragelocationrequests + - nonadminbackupstoragelocations + - nonadmindownloadrequests + - nonadminrestores + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - oadp.openshift.io + resources: + - nonadminbackups/finalizers + - nonadminbackupstoragelocations/finalizers + - nonadmindownloadrequests/finalizers + - nonadminrestores/finalizers + verbs: + - update +- apiGroups: + - oadp.openshift.io + resources: + - nonadminbackups/status + - nonadminbackupstoragelocationrequests/status + - nonadminbackupstoragelocations/status + - nonadmindownloadrequests/status + - nonadminrestores/status + verbs: + - get + - patch + - update +- apiGroups: + - velero.io + resources: + - backups + - backupstoragelocations + - deletebackuprequests + - downloadrequests + - restores + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - velero.io + resources: + - backupstoragelocations/status + verbs: + - get + - patch + - update +- apiGroups: + - velero.io + resources: + - datadownloads + - datauploads + - podvolumebackups + - podvolumerestores + verbs: + - get + - list + - watch +- apiGroups: + - velero.io + resources: + - downloadrequests/status + verbs: + - get diff --git a/config/non-admin-controller_rbac/role_binding.yaml b/config/non-admin-controller_rbac/role_binding.yaml new file mode 100644 index 00000000000..42f638ae73a --- /dev/null +++ b/config/non-admin-controller_rbac/role_binding.yaml @@ -0,0 +1,19 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/name: clusterrolebinding + app.kubernetes.io/instance: non-admin-controller-rolebinding + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: oadp-operator + app.kubernetes.io/part-of: oadp-operator + app.kubernetes.io/managed-by: kustomize + name: non-admin-controller-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: non-admin-controller-role +subjects: +- kind: ServiceAccount + name: non-admin-controller + namespace: system diff --git a/config/non-admin-controller_rbac/service_account.yaml b/config/non-admin-controller_rbac/service_account.yaml new file mode 100644 index 00000000000..09e0b660cb3 --- /dev/null +++ b/config/non-admin-controller_rbac/service_account.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/name: serviceaccount + app.kubernetes.io/instance: non-admin-controller-sa + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: oadp-operator + app.kubernetes.io/part-of: oadp-operator + app.kubernetes.io/managed-by: kustomize + name: non-admin-controller + namespace: system diff --git a/config/samples/oadp_v1alpha1_nonadminbackup.yaml b/config/samples/oadp_v1alpha1_nonadminbackup.yaml new file mode 100644 index 00000000000..1c49d64a66a --- /dev/null +++ b/config/samples/oadp_v1alpha1_nonadminbackup.yaml @@ -0,0 +1,12 @@ +apiVersion: oadp.openshift.io/v1alpha1 +kind: NonAdminBackup +metadata: + labels: + app.kubernetes.io/name: nonadminbackup + app.kubernetes.io/instance: nonadminbackup-sample + app.kubernetes.io/part-of: oadp-operator + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/created-by: oadp-operator + name: nonadminbackup-sample +spec: + backupSpec: {} diff --git a/config/samples/oadp_v1alpha1_nonadminbackupstoragelocation.yaml b/config/samples/oadp_v1alpha1_nonadminbackupstoragelocation.yaml new file mode 100644 index 00000000000..b6c329b9afd --- /dev/null +++ b/config/samples/oadp_v1alpha1_nonadminbackupstoragelocation.yaml @@ -0,0 +1,22 @@ +apiVersion: oadp.openshift.io/v1alpha1 +kind: NonAdminBackupStorageLocation +metadata: + labels: + app.kubernetes.io/name: nonadminbackupstoragelocation + app.kubernetes.io/instance: nonadminbackupstoragelocation-sample + app.kubernetes.io/part-of: oadp-nac + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/created-by: oadp-nac + name: nonadminbackupstoragelocation-sample +spec: + backupStorageLocationSpec: + config: + checksumAlgorithm: '' + region: eu-central-1 + credential: + key: default + name: cloud-credentials + objectStorage: + bucket: my-bucket + prefix: nac-test + provider: aws diff --git a/config/samples/oadp_v1alpha1_nonadminbackupstoragelocationrequest.yaml b/config/samples/oadp_v1alpha1_nonadminbackupstoragelocationrequest.yaml new file mode 100644 index 00000000000..28248a3a432 --- /dev/null +++ b/config/samples/oadp_v1alpha1_nonadminbackupstoragelocationrequest.yaml @@ -0,0 +1,12 @@ +apiVersion: oadp.openshift.io/v1alpha1 +kind: NonAdminBackupStorageLocationRequest +metadata: + labels: + app.kubernetes.io/name: nonadminbackupstoragelocationrequest + app.kubernetes.io/instance: nonadminbackupstoragelocationrequest-sample + app.kubernetes.io/part-of: oadp-nac + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/created-by: oadp-nac + name: nonadminbackupstoragelocationrequest-sample +spec: + approvalDecision: pending diff --git a/config/samples/oadp_v1alpha1_nonadmindownloadrequest.yaml b/config/samples/oadp_v1alpha1_nonadmindownloadrequest.yaml new file mode 100644 index 00000000000..9bd5a27610b --- /dev/null +++ b/config/samples/oadp_v1alpha1_nonadmindownloadrequest.yaml @@ -0,0 +1,12 @@ +apiVersion: oadp.openshift.io/v1alpha1 +kind: NonAdminDownloadRequest +metadata: + labels: + app.kubernetes.io/name: oadp-nac + app.kubernetes.io/managed-by: kustomize + name: nonadmindownloadrequest-sample +spec: + target: + kind: BackupLog + name: non-admin-backup-name + diff --git a/config/samples/oadp_v1alpha1_nonadminrestore.yaml b/config/samples/oadp_v1alpha1_nonadminrestore.yaml new file mode 100644 index 00000000000..f72499e9123 --- /dev/null +++ b/config/samples/oadp_v1alpha1_nonadminrestore.yaml @@ -0,0 +1,13 @@ +apiVersion: oadp.openshift.io/v1alpha1 +kind: NonAdminRestore +metadata: + labels: + app.kubernetes.io/name: nonadminrestore + app.kubernetes.io/instance: nonadminrestore-sample + app.kubernetes.io/part-of: oadp-nac + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/created-by: oadp-nac + name: nonadminrestore-sample +spec: + restoreSpec: + backupName: nonadminbackup-sample diff --git a/controllers/dpa_controller.go b/controllers/dpa_controller.go index 28a33520233..f0a088d1f1c 100644 --- a/controllers/dpa_controller.go +++ b/controllers/dpa_controller.go @@ -46,11 +46,13 @@ import ( // DPAReconciler reconciles a Velero object type DPAReconciler struct { client.Client - Scheme *runtime.Scheme - Log logr.Logger - Context context.Context - NamespacedName types.NamespacedName - EventRecorder record.EventRecorder + Scheme *runtime.Scheme + Log logr.Logger + Context context.Context + NamespacedName types.NamespacedName + EventRecorder record.EventRecorder + dpa *oadpv1alpha1.DataProtectionApplication + ClusterWideClient client.Client } var debugMode = os.Getenv("DEBUG") == "true" @@ -105,6 +107,7 @@ func (r *DPAReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R r.ReconcileNodeAgentDaemonset, r.ReconcileVeleroMetricsSVC, r.ReconcileDataMoverController, + r.ReconcileNonAdminController, ) if err != nil { diff --git a/controllers/nonadmin_controller.go b/controllers/nonadmin_controller.go new file mode 100644 index 00000000000..be9b2181105 --- /dev/null +++ b/controllers/nonadmin_controller.go @@ -0,0 +1,268 @@ +package controllers + +import ( + "fmt" + "os" + "reflect" + "strconv" + "time" + + "github.com/go-logr/logr" + "github.com/sirupsen/logrus" + "golang.org/x/exp/maps" + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + k8serror "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/utils/ptr" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + + oadpv1alpha1 "github.com/openshift/oadp-operator/api/v1alpha1" + "github.com/openshift/oadp-operator/pkg/common" +) + +const ( + nonAdminObjectName = "non-admin-controller" + controlPlaneKey = "control-plane" + + dpaResourceVersionAnnotation = oadpv1alpha1.OadpOperatorLabel + "-dpa-resource-version" +) + +var ( + controlPlaneLabel = map[string]string{ + controlPlaneKey: nonAdminObjectName, + } + deploymentLabels = map[string]string{ + "app.kubernetes.io/component": "manager", + "app.kubernetes.io/created-by": common.OADPOperator, + "app.kubernetes.io/instance": nonAdminObjectName, + "app.kubernetes.io/managed-by": "kustomize", + "app.kubernetes.io/name": "deployment", + "app.kubernetes.io/part-of": common.OADPOperator, + } + + dpaResourceVersion = "" + previousNonAdminConfiguration *oadpv1alpha1.NonAdmin = nil + previousDefaultBSLSyncPeriod *time.Duration = nil +) + +func (r *DPAReconciler) ReconcileNonAdminController(log logr.Logger) (bool, error) { + nonAdminDeployment := &appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: nonAdminObjectName, + Namespace: r.NamespacedName.Namespace, + }, + } + + // Delete (possible) previously deployment + if !r.checkNonAdminEnabled() { + if err := r.Get( + r.Context, + types.NamespacedName{ + Name: nonAdminDeployment.Name, + Namespace: nonAdminDeployment.Namespace, + }, + nonAdminDeployment, + ); err != nil { + if k8serror.IsNotFound(err) { + return true, nil + } + return false, err + } + + if err := r.Delete( + r.Context, + nonAdminDeployment, + &client.DeleteOptions{PropagationPolicy: ptr.To(metav1.DeletePropagationForeground)}, + ); err != nil { + r.EventRecorder.Event( + nonAdminDeployment, + corev1.EventTypeWarning, + "NonAdminDeploymentDeleteFailed", + fmt.Sprintf("Could not delete non admin controller deployment %s/%s: %s", nonAdminDeployment.Namespace, nonAdminDeployment.Name, err), + ) + return false, err + } + r.EventRecorder.Event( + nonAdminDeployment, + corev1.EventTypeNormal, + "NonAdminDeploymentDeleteSucceed", + fmt.Sprintf("Non admin controller deployment %s/%s deleted", nonAdminDeployment.Namespace, nonAdminDeployment.Name), + ) + return true, nil + } + + operation, err := controllerutil.CreateOrUpdate( + r.Context, + r.Client, + nonAdminDeployment, + func() error { + err := r.buildNonAdminDeployment(nonAdminDeployment) + if err != nil { + return err + } + + // Setting controller owner reference on the non admin controller deployment + return controllerutil.SetControllerReference(r.dpa, nonAdminDeployment, r.Scheme) + }, + ) + if err != nil { + return false, err + } + + if operation != controllerutil.OperationResultNone { + r.EventRecorder.Event( + nonAdminDeployment, + corev1.EventTypeNormal, + "NonAdminDeploymentReconciled", + fmt.Sprintf("Non admin controller deployment %s/%s %s", nonAdminDeployment.Namespace, nonAdminDeployment.Name, operation), + ) + } + return true, nil +} + +func (r *DPAReconciler) buildNonAdminDeployment(deploymentObject *appsv1.Deployment) error { + nonAdminImage := r.getNonAdminImage() + imagePullPolicy, err := common.GetImagePullPolicy(r.dpa.Spec.ImagePullPolicy, nonAdminImage) + if err != nil { + r.Log.Error(err, "imagePullPolicy regex failed") + } + ensureRequiredLabels(deploymentObject) + err = ensureRequiredSpecs(deploymentObject, r.dpa, nonAdminImage, imagePullPolicy) + if err != nil { + return err + } + return nil +} + +func ensureRequiredLabels(deploymentObject *appsv1.Deployment) { + maps.Copy(deploymentLabels, controlPlaneLabel) + deploymentObjectLabels := deploymentObject.GetLabels() + if deploymentObjectLabels == nil { + deploymentObject.SetLabels(deploymentLabels) + } else { + for key, value := range deploymentLabels { + deploymentObjectLabels[key] = value + } + deploymentObject.SetLabels(deploymentObjectLabels) + } +} + +func ensureRequiredSpecs(deploymentObject *appsv1.Deployment, dpa *oadpv1alpha1.DataProtectionApplication, image string, imagePullPolicy corev1.PullPolicy) error { + envVars := []corev1.EnvVar{ + { + Name: "WATCH_NAMESPACE", // TODO: fix, this is only used to indicate oadp ns, and is not actually used for watching ns. + Value: deploymentObject.Namespace, + }, + } + if dpa.Spec.Configuration != nil && dpa.Spec.Configuration.Velero != nil { + envVars = append(envVars, corev1.EnvVar{ + Name: common.LogLevelEnvVar, + Value: func() string { + // these levels are already validated in another controller. + level, err := logrus.ParseLevel(dpa.Spec.Configuration.Velero.LogLevel) + if err != nil { + return "" + } + return strconv.FormatUint(uint64(level), 10) + }(), + }) + } + + if len(dpa.Spec.LogFormat) > 0 { + envVars = append(envVars, corev1.EnvVar{ + Name: common.LogFormatEnvVar, + Value: string(dpa.Spec.LogFormat), + }) + } + + if len(dpaResourceVersion) == 0 || + !reflect.DeepEqual(dpa.Spec.NonAdmin, previousNonAdminConfiguration) || + (dpa.Spec.Configuration.Velero.Args != nil && + !reflect.DeepEqual(dpa.Spec.Configuration.Velero.Args.BackupSyncPeriod, previousDefaultBSLSyncPeriod)) { + dpaResourceVersion = dpa.GetResourceVersion() + previousNonAdminConfiguration = dpa.Spec.NonAdmin + if dpa.Spec.Configuration.Velero.Args != nil { + previousDefaultBSLSyncPeriod = dpa.Spec.Configuration.Velero.Args.BackupSyncPeriod + } + } + podAnnotations := map[string]string{ + dpaResourceVersionAnnotation: dpaResourceVersion, + } + + deploymentObject.Spec.Replicas = ptr.To(int32(1)) + deploymentObject.Spec.Selector = &metav1.LabelSelector{ + MatchLabels: controlPlaneLabel, + } + + templateObjectLabels := deploymentObject.Spec.Template.GetLabels() + if templateObjectLabels == nil { + deploymentObject.Spec.Template.SetLabels(controlPlaneLabel) + } else { + templateObjectLabels[controlPlaneKey] = controlPlaneLabel[controlPlaneKey] + deploymentObject.Spec.Template.SetLabels(templateObjectLabels) + } + + templateObjectAnnotations := deploymentObject.Spec.Template.GetAnnotations() + if templateObjectAnnotations == nil { + deploymentObject.Spec.Template.SetAnnotations(podAnnotations) + } else { + templateObjectAnnotations[dpaResourceVersionAnnotation] = podAnnotations[dpaResourceVersionAnnotation] + deploymentObject.Spec.Template.SetAnnotations(templateObjectAnnotations) + } + + nonAdminContainerFound := false + if len(deploymentObject.Spec.Template.Spec.Containers) == 0 { + deploymentObject.Spec.Template.Spec.Containers = []corev1.Container{{ + Name: nonAdminObjectName, + Image: image, + ImagePullPolicy: imagePullPolicy, + Env: envVars, + TerminationMessagePolicy: corev1.TerminationMessageFallbackToLogsOnError, + }} + nonAdminContainerFound = true + } else { + for index, container := range deploymentObject.Spec.Template.Spec.Containers { + if container.Name == nonAdminObjectName { + nonAdminContainer := &deploymentObject.Spec.Template.Spec.Containers[index] + nonAdminContainer.Image = image + nonAdminContainer.ImagePullPolicy = imagePullPolicy + nonAdminContainer.Env = envVars + nonAdminContainer.TerminationMessagePolicy = corev1.TerminationMessageFallbackToLogsOnError + nonAdminContainerFound = true + break + } + } + } + if !nonAdminContainerFound { + return fmt.Errorf("could not find Non admin container in Deployment") + } + deploymentObject.Spec.Template.Spec.RestartPolicy = corev1.RestartPolicyAlways + deploymentObject.Spec.Template.Spec.ServiceAccountName = nonAdminObjectName + return nil +} + +func (r *DPAReconciler) checkNonAdminEnabled() bool { + if r.dpa.Spec.NonAdmin != nil && r.dpa.Spec.NonAdmin.Enable != nil { + return *r.dpa.Spec.NonAdmin.Enable + } + return false +} + +func (r *DPAReconciler) getNonAdminImage() string { + dpa := r.dpa + unsupportedOverride := dpa.Spec.UnsupportedOverrides[oadpv1alpha1.NonAdminControllerImageKey] + if unsupportedOverride != "" { + return unsupportedOverride + } + + environmentVariable := os.Getenv("RELATED_IMAGE_NON_ADMIN_CONTROLLER") + if environmentVariable != "" { + return environmentVariable + } + + // TODO https://github.com/openshift/oadp-operator/issues/1379 + return "quay.io/konveyor/oadp-non-admin:latest" +} diff --git a/controllers/nonadmin_controller_test.go b/controllers/nonadmin_controller_test.go new file mode 100644 index 00000000000..3b6c1082d05 --- /dev/null +++ b/controllers/nonadmin_controller_test.go @@ -0,0 +1,556 @@ +package controllers + +import ( + "context" + "os" + "strconv" + "testing" + + "github.com/go-logr/logr" + "github.com/onsi/ginkgo/v2" + "github.com/onsi/gomega" + "github.com/sirupsen/logrus" + v1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/tools/record" + "k8s.io/utils/ptr" + + oadpv1alpha1 "github.com/openshift/oadp-operator/api/v1alpha1" + "github.com/openshift/oadp-operator/pkg/common" +) + +const defaultNonAdminImage = "quay.io/konveyor/oadp-non-admin:latest" + +type ReconcileNonAdminControllerScenario struct { + namespace string + dpa string + errMessage string + eventWords []string + nonAdminEnabled bool + deployment *appsv1.Deployment +} + +func createTestDeployment(namespace string) *appsv1.Deployment { + return &appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: nonAdminObjectName, + Namespace: namespace, + Labels: map[string]string{ + "test": "test", + "app.kubernetes.io/name": "wrong", + controlPlaneKey: "super-wrong", + }, + }, + Spec: appsv1.DeploymentSpec{ + Replicas: ptr.To(int32(2)), + Selector: &metav1.LabelSelector{ + MatchLabels: controlPlaneLabel, + }, + Template: corev1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: controlPlaneLabel, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: nonAdminObjectName, + Image: "wrong", + }, + }, + ServiceAccountName: "wrong-one", + }, + }, + }, + } +} + +func runReconcileNonAdminControllerTest( + scenario ReconcileNonAdminControllerScenario, + updateTestScenario func(scenario ReconcileNonAdminControllerScenario), + ctx context.Context, + envVarValue string, +) { + updateTestScenario(scenario) + + namespace := &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: scenario.namespace, + }, + } + gomega.Expect(k8sClient.Create(ctx, namespace)).To(gomega.Succeed()) + + dpa := &oadpv1alpha1.DataProtectionApplication{ + ObjectMeta: metav1.ObjectMeta{ + Name: scenario.dpa, + Namespace: scenario.namespace, + }, + Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{}, + }, + NonAdmin: &oadpv1alpha1.NonAdmin{ + Enable: ptr.To(scenario.nonAdminEnabled), + }, + }, + } + gomega.Expect(k8sClient.Create(ctx, dpa)).To(gomega.Succeed()) + + if scenario.deployment != nil { + gomega.Expect(k8sClient.Create(ctx, scenario.deployment)).To(gomega.Succeed()) + } + + os.Setenv("RELATED_IMAGE_NON_ADMIN_CONTROLLER", envVarValue) + event := record.NewFakeRecorder(5) + r := &DPAReconciler{ + Client: k8sClient, + Scheme: testEnv.Scheme, + Context: ctx, + NamespacedName: types.NamespacedName{ + Name: scenario.dpa, + Namespace: scenario.namespace, + }, + EventRecorder: event, + dpa: dpa, + } + result, err := r.ReconcileNonAdminController(logr.Discard()) + + if len(scenario.errMessage) == 0 { + gomega.Expect(result).To(gomega.BeTrue()) + gomega.Expect(err).To(gomega.Not(gomega.HaveOccurred())) + } else { + gomega.Expect(result).To(gomega.BeFalse()) + gomega.Expect(err).To(gomega.HaveOccurred()) + gomega.Expect(err.Error()).To(gomega.ContainSubstring(scenario.errMessage)) + } + + if scenario.eventWords != nil { + gomega.Expect(len(event.Events)).To(gomega.Equal(1)) + message := <-event.Events + for _, word := range scenario.eventWords { + gomega.Expect(message).To(gomega.ContainSubstring(word)) + } + } else { + gomega.Expect(len(event.Events)).To(gomega.Equal(0)) + } +} + +var _ = ginkgo.Describe("Test ReconcileNonAdminController function", func() { + var ( + ctx = context.Background() + currentTestScenario ReconcileNonAdminControllerScenario + updateTestScenario = func(scenario ReconcileNonAdminControllerScenario) { + currentTestScenario = scenario + } + ) + + ginkgo.AfterEach(func() { + os.Unsetenv("RELATED_IMAGE_NON_ADMIN_CONTROLLER") + + deployment := &appsv1.Deployment{} + if k8sClient.Get( + ctx, + types.NamespacedName{ + Name: nonAdminObjectName, + Namespace: currentTestScenario.namespace, + }, + deployment, + ) == nil { + gomega.Expect(k8sClient.Delete(ctx, deployment)).To(gomega.Succeed()) + } + + dpa := &oadpv1alpha1.DataProtectionApplication{ + ObjectMeta: metav1.ObjectMeta{ + Name: currentTestScenario.dpa, + Namespace: currentTestScenario.namespace, + }, + } + gomega.Expect(k8sClient.Delete(ctx, dpa)).To(gomega.Succeed()) + + namespace := &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: currentTestScenario.namespace, + }, + } + gomega.Expect(k8sClient.Delete(ctx, namespace)).To(gomega.Succeed()) + }) + + ginkgo.DescribeTable("Reconcile is true", + func(scenario ReconcileNonAdminControllerScenario) { + runReconcileNonAdminControllerTest(scenario, updateTestScenario, ctx, defaultNonAdminImage) + }, + ginkgo.Entry("Should create non admin deployment", ReconcileNonAdminControllerScenario{ + namespace: "test-1", + dpa: "test-1-dpa", + eventWords: []string{"Normal", "NonAdminDeploymentReconciled", "created"}, + nonAdminEnabled: true, + }), + ginkgo.Entry("Should update non admin deployment", ReconcileNonAdminControllerScenario{ + namespace: "test-2", + dpa: "test-2-dpa", + eventWords: []string{"Normal", "NonAdminDeploymentReconciled", "updated"}, + nonAdminEnabled: true, + deployment: createTestDeployment("test-2"), + }), + ginkgo.Entry("Should delete non admin deployment", ReconcileNonAdminControllerScenario{ + namespace: "test-3", + dpa: "test-3-dpa", + eventWords: []string{"Normal", "NonAdminDeploymentDeleteSucceed", "deleted"}, + nonAdminEnabled: false, + deployment: createTestDeployment("test-3"), + }), + ginkgo.Entry("Should do nothing", ReconcileNonAdminControllerScenario{ + namespace: "test-4", + dpa: "test-4-dpa", + nonAdminEnabled: false, + }), + ) + + ginkgo.DescribeTable("Reconcile is false", + func(scenario ReconcileNonAdminControllerScenario) { + runReconcileNonAdminControllerTest(scenario, updateTestScenario, ctx, defaultNonAdminImage) + }, + ginkgo.Entry("Should error because non admin container was not found in Deployment", ReconcileNonAdminControllerScenario{ + namespace: "test-error-1", + dpa: "test-error-1-dpa", + errMessage: "could not find Non admin container in Deployment", + nonAdminEnabled: true, + deployment: &appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: nonAdminObjectName, + Namespace: "test-error-1", + }, + Spec: appsv1.DeploymentSpec{ + Selector: &metav1.LabelSelector{ + MatchLabels: controlPlaneLabel, + }, + Template: corev1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: controlPlaneLabel, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{{ + Name: "wrong", + Image: defaultNonAdminImage, + }}, + }, + }, + }, + }, + }), + ) +}) + +func TestDPAReconcilerBuildNonAdminDeployment(t *testing.T) { + r := &DPAReconciler{dpa: &oadpv1alpha1.DataProtectionApplication{ + Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + NonAdmin: &oadpv1alpha1.NonAdmin{ + Enable: ptr.To(true), + }, + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{}, + }, + }, + }} + t.Setenv("RELATED_IMAGE_NON_ADMIN_CONTROLLER", defaultNonAdminImage) + deployment := createTestDeployment("test-build-deployment") + err := r.buildNonAdminDeployment(deployment) + if err != nil { + t.Errorf("buildNonAdminDeployment() errored out: %v", err) + } + labels := deployment.GetLabels() + if labels["test"] != "test" { + t.Errorf("Deployment label 'test' has wrong value: %v", labels["test"]) + } + if labels["app.kubernetes.io/name"] != "deployment" { + t.Errorf("Deployment label 'app.kubernetes.io/name' has wrong value: %v", labels["app.kubernetes.io/name"]) + } + if labels[controlPlaneKey] != nonAdminObjectName { + t.Errorf("Deployment label '%v' has wrong value: %v", controlPlaneKey, labels[controlPlaneKey]) + } + if *deployment.Spec.Replicas != 1 { + t.Errorf("Deployment has wrong number of replicas: %v", *deployment.Spec.Replicas) + } + if deployment.Spec.Template.Spec.ServiceAccountName != nonAdminObjectName { + t.Errorf("Deployment has wrong ServiceAccount: %v", deployment.Spec.Template.Spec.ServiceAccountName) + } +} + +func TestEnsureRequiredLabels(t *testing.T) { + deployment := createTestDeployment("test-ensure-label") + ensureRequiredLabels(deployment) + labels := deployment.GetLabels() + if labels["test"] != "test" { + t.Errorf("Deployment label 'test' has wrong value: %v", labels["test"]) + } + if labels["app.kubernetes.io/name"] != "deployment" { + t.Errorf("Deployment label 'app.kubernetes.io/name' has wrong value: %v", labels["app.kubernetes.io/name"]) + } + if labels[controlPlaneKey] != nonAdminObjectName { + t.Errorf("Deployment label '%v' has wrong value: %v", controlPlaneKey, labels[controlPlaneKey]) + } +} + +func TestEnsureRequiredSpecs(t *testing.T) { + deployment := createTestDeployment("test-ensure-spec") + dpa := &oadpv1alpha1.DataProtectionApplication{ + ObjectMeta: metav1.ObjectMeta{ + ResourceVersion: "123456789", + }, + Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{ + LogLevel: logrus.DebugLevel.String(), + }, + }, + NonAdmin: &oadpv1alpha1.NonAdmin{ + Enable: ptr.To(true), + }, + LogFormat: oadpv1alpha1.LogFormatJSON, + }, + } + err := ensureRequiredSpecs(deployment, dpa, defaultNonAdminImage, corev1.PullAlways) + if err != nil { + t.Errorf("ensureRequiredSpecs() errored out: %v", err) + } + if *deployment.Spec.Replicas != 1 { + t.Errorf("Deployment has wrong number of replicas: %v", *deployment.Spec.Replicas) + } + if deployment.Spec.Template.Spec.ServiceAccountName != nonAdminObjectName { + t.Errorf("Deployment has wrong ServiceAccount: %v", deployment.Spec.Template.Spec.ServiceAccountName) + } + if deployment.Spec.Template.Spec.Containers[0].Image != defaultNonAdminImage { + t.Errorf("Deployment has wrong Image: %v", deployment.Spec.Template.Spec.Containers[0].Image) + } + if len(deployment.Spec.Template.Annotations[dpaResourceVersionAnnotation]) == 0 { + t.Errorf("Deployment does not have Annotation") + } + for _, env := range deployment.Spec.Template.Spec.Containers[0].Env { + if env.Name == common.LogLevelEnvVar { + // check that we get expected int value string from the level set in config + if expectedLevel, err := logrus.ParseLevel(logrus.DebugLevel.String()); err != nil { + t.Errorf("Unable to parse loglevel expected") + } else { + if env.Value != strconv.FormatUint(uint64(expectedLevel), 10) { + t.Errorf("log level unexpected") + } + } + } + if env.Name == common.LogFormatEnvVar { + if env.Value != string(oadpv1alpha1.LogFormatJSON) && env.Value != string(oadpv1alpha1.LogFormatText) { + t.Errorf("log format unexpected") + } + } + } + + previousDPAAnnotationValue := deployment.DeepCopy().Spec.Template.Annotations[dpaResourceVersionAnnotation] + updatedDPA := &oadpv1alpha1.DataProtectionApplication{ + ObjectMeta: metav1.ObjectMeta{ + ResourceVersion: "147258369", + }, + Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + NonAdmin: &oadpv1alpha1.NonAdmin{ + Enable: ptr.To(true), + }, + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{}, + }, + }, + } + err = ensureRequiredSpecs(deployment, updatedDPA, defaultNonAdminImage, corev1.PullAlways) + if err != nil { + t.Errorf("ensureRequiredSpecs() errored out: %v", err) + } + if previousDPAAnnotationValue != deployment.Spec.Template.Annotations[dpaResourceVersionAnnotation] { + t.Errorf("Deployment have different Annotation") + } + updatedDPA = &oadpv1alpha1.DataProtectionApplication{ + ObjectMeta: metav1.ObjectMeta{ + ResourceVersion: "987654321", + }, + Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{}, + }, + NonAdmin: &oadpv1alpha1.NonAdmin{ + Enable: ptr.To(true), + EnforceBackupSpec: &v1.BackupSpec{ + SnapshotMoveData: ptr.To(false), + }, + }, + }, + } + err = ensureRequiredSpecs(deployment, updatedDPA, defaultNonAdminImage, corev1.PullAlways) + if err != nil { + t.Errorf("ensureRequiredSpecs() errored out: %v", err) + } + if previousDPAAnnotationValue == deployment.Spec.Template.Annotations[dpaResourceVersionAnnotation] { + t.Errorf("Deployment does not have different Annotation") + } + for _, env := range deployment.Spec.Template.Spec.Containers[0].Env { + if env.Name == common.LogLevelEnvVar { + // check that we get expected int value string from the level set in config + if expectedLevel, err := logrus.ParseLevel(""); err != nil { + // we expect logrus.ParseLevel("") to err here and returns 0 + if err == nil { + t.Error("Expected err when level is empty from logrus.ParseLevel") + } + // The returned expectedLevel of 0 is panic level + if expectedLevel != logrus.PanicLevel { + t.Errorf("unexpected logrus.ParseLevel('') return value") + } + // we ignore and return empty string instead, and nac deployment will handle defaulting + if env.Value != "" { + t.Errorf("log level unexpected") + } + } + } + } + previousDPAAnnotationValue = deployment.DeepCopy().Spec.Template.Annotations[dpaResourceVersionAnnotation] + updatedDPA = &oadpv1alpha1.DataProtectionApplication{ + ObjectMeta: metav1.ObjectMeta{ + ResourceVersion: "112233445", + }, + Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + NonAdmin: &oadpv1alpha1.NonAdmin{ + Enable: ptr.To(true), + EnforceBackupSpec: &v1.BackupSpec{ + SnapshotMoveData: ptr.To(false), + }, + EnforceRestoreSpec: &v1.RestoreSpec{ + RestorePVs: ptr.To(true), + }, + EnforceBSLSpec: &oadpv1alpha1.EnforceBackupStorageLocationSpec{ + Provider: "foo-provider", + }, + }, + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{}, + }, + }, + } + err = ensureRequiredSpecs(deployment, updatedDPA, defaultNonAdminImage, corev1.PullAlways) + if err != nil { + t.Errorf("ensureRequiredSpecs() errored out: %v", err) + } + if previousDPAAnnotationValue == deployment.Spec.Template.Annotations[dpaResourceVersionAnnotation] { + t.Errorf("Deployment does not have different Annotation") + } +} + +func TestDPAReconcilerCheckNonAdminEnabled(t *testing.T) { + tests := []struct { + name string + result bool + dpa *oadpv1alpha1.DataProtectionApplication + }{ + { + name: "DPA has non admin feature enable: true so return true", + result: true, + dpa: &oadpv1alpha1.DataProtectionApplication{ + Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + NonAdmin: &oadpv1alpha1.NonAdmin{ + Enable: ptr.To(true), + }, + }, + }, + }, + { + name: "DPA has non admin feature enable: false so return false", + result: false, + dpa: &oadpv1alpha1.DataProtectionApplication{ + Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + NonAdmin: &oadpv1alpha1.NonAdmin{ + Enable: ptr.To(false), + }, + }, + }, + }, + { + name: "DPA has empty non admin feature spec so return false", + result: false, + dpa: &oadpv1alpha1.DataProtectionApplication{ + Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + NonAdmin: &oadpv1alpha1.NonAdmin{}, + }, + }, + }, + { + name: "DPA has non admin feature enable: nil so return false", + result: false, + dpa: &oadpv1alpha1.DataProtectionApplication{ + Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + NonAdmin: &oadpv1alpha1.NonAdmin{ + Enable: nil, + }, + }, + }, + }, + { + name: "DPA has no non admin feature", + result: false, + dpa: &oadpv1alpha1.DataProtectionApplication{}, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + r := &DPAReconciler{dpa: test.dpa} + result := r.checkNonAdminEnabled() + if result != test.result { + t.Errorf("Results differ: got '%v' but expected '%v'", result, test.result) + } + }) + } +} + +func TestDPAReconcilerGetNonAdminImage(t *testing.T) { + tests := []struct { + name string + image string + env string + dpa *oadpv1alpha1.DataProtectionApplication + }{ + { + name: "Get non admin image from environment variable with default value", + image: defaultNonAdminImage, + env: defaultNonAdminImage, + dpa: &oadpv1alpha1.DataProtectionApplication{}, + }, + { + name: "Get non admin image from environment variable with custom value", + image: "quay.io/openshift/oadp-non-admin:latest", + env: "quay.io/openshift/oadp-non-admin:latest", + dpa: &oadpv1alpha1.DataProtectionApplication{}, + }, + { + name: "Get non admin image from unsupported overrides", + image: "quay.io/konveyor/another:latest", + dpa: &oadpv1alpha1.DataProtectionApplication{ + Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + UnsupportedOverrides: map[oadpv1alpha1.UnsupportedImageKey]string{ + "nonAdminControllerImageFqin": "quay.io/konveyor/another:latest", + }, + }, + }, + }, + { + name: "Get non admin image from fallback", + image: defaultNonAdminImage, + dpa: &oadpv1alpha1.DataProtectionApplication{}, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + r := &DPAReconciler{dpa: test.dpa} + if len(test.env) > 0 { + t.Setenv("RELATED_IMAGE_NON_ADMIN_CONTROLLER", test.env) + } + image := r.getNonAdminImage() + if image != test.image { + t.Errorf("Images differ: got '%v' but expected '%v'", image, test.image) + } + }) + } +} diff --git a/controllers/velero.go b/controllers/velero.go index 5fefdd5a296..110c98e1677 100644 --- a/controllers/velero.go +++ b/controllers/velero.go @@ -333,6 +333,10 @@ func (r *DPAReconciler) customizeVeleroDeployment(dpa *oadpv1alpha1.DataProtecti veleroContainer.Args = append(veleroContainer.Args, "--log-level", logLevel.String()) } + if dpa.Spec.LogFormat != "" { + veleroContainer.Args = append(veleroContainer.Args, fmt.Sprintf("--log-format=%s", dpa.Spec.LogFormat)) + } + // Setting async operations server parameter ItemOperationSyncFrequency if dpa.Spec.Configuration.Velero.ItemOperationSyncFrequency != "" { ItemOperationSyncFrequencyString := dpa.Spec.Configuration.Velero.ItemOperationSyncFrequency diff --git a/controllers/velero_test.go b/controllers/velero_test.go index 99689ef30e0..ba0f98ebec2 100644 --- a/controllers/velero_test.go +++ b/controllers/velero_test.go @@ -842,6 +842,7 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { dpa: createTestDpaWith( nil, oadpv1alpha1.DataProtectionApplicationSpec{ + LogFormat: oadpv1alpha1.LogFormatJSON, Configuration: &oadpv1alpha1.ApplicationConfig{ Velero: &oadpv1alpha1.VeleroConfig{ LogLevel: logrus.InfoLevel.String(), @@ -863,6 +864,7 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { defaultRestoreResourcePriorities, "--log-level", logrus.InfoLevel.String(), + "--log-format=json", "--item-operation-sync-frequency=5m", "--default-item-operation-timeout=2h", "--default-snapshot-move-data=false", diff --git a/go.mod b/go.mod index a55df062ed6..6dfe1a1ddd3 100644 --- a/go.mod +++ b/go.mod @@ -27,6 +27,7 @@ require ( github.com/google/go-cmp v0.7.0 github.com/openshift/hypershift/api v0.0.0-20240522104800-604a957be25e github.com/vmware-tanzu/velero v1.14.0 + golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 k8s.io/klog/v2 v2.120.1 ) @@ -151,7 +152,6 @@ require ( go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect golang.org/x/crypto v0.36.0 // indirect - golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect golang.org/x/net v0.36.0 // indirect golang.org/x/oauth2 v0.27.0 // indirect golang.org/x/sync v0.12.0 // indirect diff --git a/main.go b/main.go index 250148fb6cd..fc0cf69f5d6 100644 --- a/main.go +++ b/main.go @@ -220,10 +220,22 @@ func main() { os.Exit(1) } + dpaClientScheme := runtime.NewScheme() + utilruntime.Must(oadpv1alpha1.AddToScheme(dpaClientScheme)) + utilruntime.Must(appsv1.AddToScheme(dpaClientScheme)) + dpaClient, err := client.New(kubeconf, client.Options{ + Scheme: dpaClientScheme, + }) + if err != nil { + setupLog.Error(err, "unable to create Kubernetes client") + os.Exit(1) + } + if err = (&controllers.DPAReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - EventRecorder: mgr.GetEventRecorderFor("DPA-controller"), + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + EventRecorder: mgr.GetEventRecorderFor("DPA-controller"), + ClusterWideClient: dpaClient, }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "DataProtectionApplication") os.Exit(1) diff --git a/pkg/common/common.go b/pkg/common/common.go index 73c47dedf9d..5fe8a146903 100644 --- a/pkg/common/common.go +++ b/pkg/common/common.go @@ -94,6 +94,8 @@ const ( HTTPProxyEnvVar = "HTTP_PROXY" HTTPSProxyEnvVar = "HTTPS_PROXY" NoProxyEnvVar = "NO_PROXY" + LogLevelEnvVar = "LOG_LEVEL" + LogFormatEnvVar = "LOG_FORMAT" ) // Unsupported Server Args annotation keys diff --git a/pkg/common/common_test.go b/pkg/common/common_test.go index a5d8972a3c0..26f7b3cc432 100644 --- a/pkg/common/common_test.go +++ b/pkg/common/common_test.go @@ -295,6 +295,7 @@ func TestGenerateCliArgsFromConfigMap(t *testing.T) { Data: map[string]string{ "--default-volume-snapshot-locations": "aws:backups-primary,azure:backups-secondary", "--log-level": "debug", + "--log-format": "json", "--default-snapshot-move-data": "True", "-v": "3", "a": "somearg", @@ -305,6 +306,7 @@ func TestGenerateCliArgsFromConfigMap(t *testing.T) { "--a=somearg", "--default-snapshot-move-data=true", "--default-volume-snapshot-locations=aws:backups-primary,azure:backups-secondary", + "--log-format=json", "--log-level=debug", "-v=3", }, From 4226e63ea65e5974d0e0af87dc62cdf8581d344d Mon Sep 17 00:00:00 2001 From: Wesley Hayutin Date: Thu, 11 Sep 2025 18:47:18 -0600 Subject: [PATCH 2/3] pod/non-admin-controller-74775c6977-2mncl running --- Dockerfile | 1 + api/v1alpha1/nonadmin_types.go | 65 + api/v1alpha1/nonadminbackup_types.go | 210 +++ .../nonadminbackupstoragelocation_types.go | 99 ++ ...adminbackupstoragelocationrequest_types.go | 111 ++ api/v1alpha1/nonadmindownloadrequest_types.go | 113 ++ api/v1alpha1/nonadminrestore_types.go | 179 +++ api/v1alpha1/oadp_types.go | 6 + api/v1alpha1/zz_generated.deepcopy.go | 911 ++++++++++- .../oadp-operator.clusterserviceversion.yaml | 1023 ++++++++++++- ...enshift.io_dataprotectionapplications.yaml | 925 +++++++++++ .../oadp.openshift.io_nonadminbackups.yaml | 12 - ...nonadminbackupstoragelocationrequests.yaml | 4 - ...ift.io_nonadminbackupstoragelocations.yaml | 4 - .../oadp.openshift.io_nonadminrestores.yaml | 6 - .../oadp.openshift.io_nonadminbackups.yaml | 1362 +++++++++++++++++ ...nonadminbackupstoragelocationrequests.yaml | 185 +++ ...ift.io_nonadminbackupstoragelocations.yaml | 277 ++++ ...openshift.io_nonadmindownloadrequests.yaml | 184 +++ .../oadp.openshift.io_nonadminrestores.yaml | 743 +++++++++ config/crd/kustomization.yaml | 2 + .../oadp-operator.clusterserviceversion.yaml | 25 +- controllers/nonadmin_controller.go | 28 +- controllers/nonadmin_controller_test.go | 15 +- internal/common/constant/constant.go | 110 ++ 25 files changed, 6468 insertions(+), 132 deletions(-) create mode 100644 api/v1alpha1/nonadmin_types.go create mode 100644 api/v1alpha1/nonadminbackup_types.go create mode 100644 api/v1alpha1/nonadminbackupstoragelocation_types.go create mode 100644 api/v1alpha1/nonadminbackupstoragelocationrequest_types.go create mode 100644 api/v1alpha1/nonadmindownloadrequest_types.go create mode 100644 api/v1alpha1/nonadminrestore_types.go create mode 100644 config/crd/bases/oadp.openshift.io_nonadminbackups.yaml create mode 100644 config/crd/bases/oadp.openshift.io_nonadminbackupstoragelocationrequests.yaml create mode 100644 config/crd/bases/oadp.openshift.io_nonadminbackupstoragelocations.yaml create mode 100644 config/crd/bases/oadp.openshift.io_nonadmindownloadrequests.yaml create mode 100644 config/crd/bases/oadp.openshift.io_nonadminrestores.yaml create mode 100644 internal/common/constant/constant.go diff --git a/Dockerfile b/Dockerfile index 986a6ae2f84..22e3d45abf8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,6 +17,7 @@ COPY main.go main.go COPY api/ api/ COPY pkg/ pkg/ COPY controllers/ controllers/ +COPY internal/ internal/ # Build RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -mod=mod -a -o /go/src/manager main.go diff --git a/api/v1alpha1/nonadmin_types.go b/api/v1alpha1/nonadmin_types.go new file mode 100644 index 00000000000..e8fcec90836 --- /dev/null +++ b/api/v1alpha1/nonadmin_types.go @@ -0,0 +1,65 @@ +/* +Copyright 2024. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +// NonAdminPhase is a simple one high-level summary of the lifecycle of a NonAdminBackup, NonAdminRestore, NonAdminBackupStorageLocation, or NonAdminDownloadRequest +// +kubebuilder:validation:Enum=New;BackingOff;Created;Deleting +type NonAdminPhase string + +const ( + // NonAdminPhaseNew - NonAdmin object was accepted by the OpenShift cluster, but it has not yet been processed by the NonAdminController + NonAdminPhaseNew NonAdminPhase = "New" + // NonAdminPhaseBackingOff - Velero object was not created due to NonAdmin object error (configuration or similar) + NonAdminPhaseBackingOff NonAdminPhase = "BackingOff" + // NonAdminPhaseCreated - Velero object was created. The Phase will not have additional information about it. + NonAdminPhaseCreated NonAdminPhase = "Created" + // NonAdminPhaseDeleting - Velero object is pending deletion. The Phase will not have additional information about it. + NonAdminPhaseDeleting NonAdminPhase = "Deleting" +) + +// NonAdminCondition are used for more detailed information supporing NonAdminBackupPhase state. +// +kubebuilder:validation:Enum=Accepted;Queued;Deleting +type NonAdminCondition string + +// Predefined conditions for NonAdminController objects. +// One NonAdminController object may have multiple conditions. +// It is more granular knowledge of the NonAdminController object and represents the +// array of the conditions through which the NonAdminController has or has not passed +const ( + NonAdminConditionAccepted NonAdminCondition = "Accepted" + NonAdminConditionQueued NonAdminCondition = "Queued" + NonAdminConditionDeleting NonAdminCondition = "Deleting" +) + +// QueueInfo holds the queue position for a specific operation. +type QueueInfo struct { + // estimatedQueuePosition is the number of operations ahead in the queue (0 if not queued) + EstimatedQueuePosition int `json:"estimatedQueuePosition"` +} + +// Constants representing resource names for non-admin objects +// These are used to identify custom resources managed for non-admin users. +const ( + // NonAdminBackups represents the resource name for non-admin backups. + NonAdminBackups = "nonadminbackups" + + // NonAdminRestores represents the resource name for non-admin restores. + NonAdminRestores = "nonadminrestores" + + // NonAdminBackupStorageLocations represents the resource name for non-admin backup storage locations. + NonAdminBackupStorageLocations = "nonadminbackupstoragelocations" +) diff --git a/api/v1alpha1/nonadminbackup_types.go b/api/v1alpha1/nonadminbackup_types.go new file mode 100644 index 00000000000..6f7dcb1baf5 --- /dev/null +++ b/api/v1alpha1/nonadminbackup_types.go @@ -0,0 +1,210 @@ +/* +Copyright 2024. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + velerov1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/openshift/oadp-operator/internal/common/constant" +) + +// NonAdminBackupSpec defines the desired state of NonAdminBackup +type NonAdminBackupSpec struct { + // BackupSpec defines the specification for a Velero backup. + BackupSpec *velerov1.BackupSpec `json:"backupSpec"` + + // DeleteBackup removes the NonAdminBackup and its associated NonAdminRestores and VeleroBackup from the cluster, + // as well as the corresponding data in object storage + // +optional + DeleteBackup bool `json:"deleteBackup,omitempty"` +} + +// VeleroBackup contains information of the related Velero backup object. +type VeleroBackup struct { + // spec captures the current spec of the Velero backup. + // +optional + Spec *velerov1.BackupSpec `json:"spec,omitempty"` + + // status captures the current status of the Velero backup. + // +optional + Status *velerov1.BackupStatus `json:"status,omitempty"` + + // nacuuid references the Velero Backup object by it's label containing same NACUUID. + // +optional + NACUUID string `json:"nacuuid,omitempty"` + + // references the Velero Backup object by it's name. + // +optional + Name string `json:"name,omitempty"` + + // namespace references the Namespace in which Velero backup exists. + // +optional + Namespace string `json:"namespace,omitempty"` +} + +// VeleroDeleteBackupRequest contains information of the related Velero delete backup request object. +type VeleroDeleteBackupRequest struct { + // status captures the current status of the Velero delete backup request. + // +optional + Status *velerov1.DeleteBackupRequestStatus `json:"status,omitempty"` + + // nacuuid references the Velero delete backup request object by it's label containing same NACUUID. + // +optional + NACUUID string `json:"nacuuid,omitempty"` + + // name references the Velero delete backup request object by it's name. + // +optional + Name string `json:"name,omitempty"` + + // namespace references the Namespace in which Velero delete backup request exists. + // +optional + Namespace string `json:"namespace,omitempty"` +} + +// DataMoverDataUploads contains information of the related Velero DataUpload objects. +type DataMoverDataUploads struct { + // number of DataUploads related to this NonAdminBackup's Backup + // +optional + Total int `json:"total,omitempty"` + + // number of DataUploads related to this NonAdminBackup's Backup in phase New + // +optional + New int `json:"new,omitempty"` + + // number of DataUploads related to this NonAdminBackup's Backup in phase Accepted + // +optional + Accepted int `json:"accepted,omitempty"` + + // number of DataUploads related to this NonAdminBackup's Backup in phase Prepared + // +optional + Prepared int `json:"prepared,omitempty"` + + // number of DataUploads related to this NonAdminBackup's Backup in phase InProgress + // +optional + InProgress int `json:"inProgress,omitempty"` + + // number of DataUploads related to this NonAdminBackup's Backup in phase Canceling + // +optional + Canceling int `json:"canceling,omitempty"` + + // number of DataUploads related to this NonAdminBackup's Backup in phase Canceled + // +optional + Canceled int `json:"canceled,omitempty"` + + // number of DataUploads related to this NonAdminBackup's Backup in phase Failed + // +optional + Failed int `json:"failed,omitempty"` + + // number of DataUploads related to this NonAdminBackup's Backup in phase Completed + // +optional + Completed int `json:"completed,omitempty"` +} + +// FileSystemPodVolumeBackups contains information of the related Velero PodVolumeBackup objects. +type FileSystemPodVolumeBackups struct { + // number of PodVolumeBackups related to this NonAdminBackup's Backup + // +optional + Total int `json:"total,omitempty"` + + // number of PodVolumeBackups related to this NonAdminBackup's Backup in phase New + // +optional + New int `json:"new,omitempty"` + + // number of PodVolumeBackups related to this NonAdminBackup's Backup in phase InProgress + // +optional + InProgress int `json:"inProgress,omitempty"` + + // number of PodVolumeBackups related to this NonAdminBackup's Backup in phase Failed + // +optional + Failed int `json:"failed,omitempty"` + + // number of PodVolumeBackups related to this NonAdminBackup's Backup in phase Completed + // +optional + Completed int `json:"completed,omitempty"` +} + +// NonAdminBackupStatus defines the observed state of NonAdminBackup +type NonAdminBackupStatus struct { + // +optional + VeleroBackup *VeleroBackup `json:"veleroBackup,omitempty"` + + // +optional + VeleroDeleteBackupRequest *VeleroDeleteBackupRequest `json:"veleroDeleteBackupRequest,omitempty"` + + // +optional + DataMoverDataUploads *DataMoverDataUploads `json:"dataMoverDataUploads,omitempty"` + + // +optional + FileSystemPodVolumeBackups *FileSystemPodVolumeBackups `json:"fileSystemPodVolumeBackups,omitempty"` + + // queueInfo is used to estimate how many backups are scheduled before the given VeleroBackup in the OADP namespace. + // This number is not guaranteed to be accurate, but it should be close. It's inaccurate for cases when + // Velero pod is not running or being restarted after Backup object were created. + // It counts only VeleroBackups that are still subject to be handled by OADP/Velero. + // +optional + QueueInfo *QueueInfo `json:"queueInfo,omitempty"` + + // phase is a simple one high-level summary of the lifecycle of an NonAdminBackup. + Phase NonAdminPhase `json:"phase,omitempty"` + + Conditions []metav1.Condition `json:"conditions,omitempty"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:resource:path=nonadminbackups,shortName=nab +// +kubebuilder:printcolumn:name="Request-Phase",type="string",JSONPath=".status.phase" +// +kubebuilder:printcolumn:name="Velero-Phase",type="string",JSONPath=".status.veleroBackup.status.phase" +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" + +// NonAdminBackup is the Schema for the nonadminbackups API +type NonAdminBackup struct { + Spec NonAdminBackupSpec `json:"spec,omitempty"` + Status NonAdminBackupStatus `json:"status,omitempty"` + + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` +} + +// +kubebuilder:object:root=true + +// NonAdminBackupList contains a list of NonAdminBackup +type NonAdminBackupList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []NonAdminBackup `json:"items"` +} + +func init() { + SchemeBuilder.Register(&NonAdminBackup{}, &NonAdminBackupList{}) +} + +// Helper Functions to avoid digging into NAB controller to understand how to get desired values + +// VeleroBackupName returns the name of the VeleroBackup object. +func (nab *NonAdminBackup) VeleroBackupName() string { + if nab.Status.VeleroBackup == nil { + return constant.EmptyString + } + return nab.Status.VeleroBackup.Name +} + +// UsesNaBSL returns true if backup is using NonAdminBackupStorageLocation +func (nab *NonAdminBackup) UsesNaBSL() bool { + return nab.Spec.BackupSpec != nil && nab.Spec.BackupSpec.StorageLocation != constant.EmptyString +} diff --git a/api/v1alpha1/nonadminbackupstoragelocation_types.go b/api/v1alpha1/nonadminbackupstoragelocation_types.go new file mode 100644 index 00000000000..367e454f8a7 --- /dev/null +++ b/api/v1alpha1/nonadminbackupstoragelocation_types.go @@ -0,0 +1,99 @@ +/* +Copyright 2024. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + velerov1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// NonAdminBSLCondition contains additional conditions to the +// generic ones defined as NonAdminCondition +type NonAdminBSLCondition string + +// Predefined NonAdminBSLConditions +const ( + NonAdminBSLConditionSecretSynced NonAdminBSLCondition = "SecretSynced" + NonAdminBSLConditionBSLSynced NonAdminBSLCondition = "BackupStorageLocationSynced" + NonAdminBSLConditionApproved NonAdminBSLCondition = "ClusterAdminApproved" + NonAdminBSLConditionSpecUpdateApproved NonAdminBSLCondition = "SpecUpdateApproved" +) + +// NonAdminBackupStorageLocationSpec defines the desired state of NonAdminBackupStorageLocation +type NonAdminBackupStorageLocationSpec struct { + BackupStorageLocationSpec *velerov1.BackupStorageLocationSpec `json:"backupStorageLocationSpec"` +} + +// VeleroBackupStorageLocation contains information of the related Velero backup object. +type VeleroBackupStorageLocation struct { + // status captures the current status of the Velero backup storage location. + // +optional + Status *velerov1.BackupStorageLocationStatus `json:"status,omitempty"` + + // nacuuid references the Velero BackupStorageLocation object by it's label containing same NACUUID. + // +optional + NACUUID string `json:"nacuuid,omitempty"` + + // references the Velero BackupStorageLocation object by it's name. + // +optional + Name string `json:"name,omitempty"` + + // namespace references the Namespace in which Velero backup storage location exists. + // +optional + Namespace string `json:"namespace,omitempty"` +} + +// NonAdminBackupStorageLocationStatus defines the observed state of NonAdminBackupStorageLocation +type NonAdminBackupStorageLocationStatus struct { + // +optional + VeleroBackupStorageLocation *VeleroBackupStorageLocation `json:"veleroBackupStorageLocation,omitempty"` + + // phase is a simple one high-level summary of the lifecycle of an NonAdminBackupStorageLocation. + Phase NonAdminPhase `json:"phase,omitempty"` + + Conditions []metav1.Condition `json:"conditions,omitempty"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:resource:path=nonadminbackupstoragelocations,shortName=nabsl +// +kubebuilder:printcolumn:name="Request-Approved",type="string",JSONPath=".status.conditions[?(@.type=='ClusterAdminApproved')].status" +// +kubebuilder:printcolumn:name="Request-Phase",type="string",JSONPath=".status.phase" +// +kubebuilder:printcolumn:name="Velero-Phase",type="string",JSONPath=".status.veleroBackupStorageLocation.status.phase" +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" + +// NonAdminBackupStorageLocation is the Schema for the nonadminbackupstoragelocations API +type NonAdminBackupStorageLocation struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec NonAdminBackupStorageLocationSpec `json:"spec,omitempty"` + Status NonAdminBackupStorageLocationStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// NonAdminBackupStorageLocationList contains a list of NonAdminBackupStorageLocation +type NonAdminBackupStorageLocationList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []NonAdminBackupStorageLocation `json:"items"` +} + +func init() { + SchemeBuilder.Register(&NonAdminBackupStorageLocation{}, &NonAdminBackupStorageLocationList{}) +} diff --git a/api/v1alpha1/nonadminbackupstoragelocationrequest_types.go b/api/v1alpha1/nonadminbackupstoragelocationrequest_types.go new file mode 100644 index 00000000000..5705e4c82d5 --- /dev/null +++ b/api/v1alpha1/nonadminbackupstoragelocationrequest_types.go @@ -0,0 +1,111 @@ +/* +Copyright 2024. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + velerov1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// NonAdminBSLRequest controls the approval of the NonAdminBackupStorageLocation +// +kubebuilder:validation:Enum=approve;reject;pending +type NonAdminBSLRequest string + +// NonAdminBSLRequestPhase is the phase of the NonAdminBackupStorageLocationRequest +// +kubebuilder:validation:Enum=Pending;Approved;Rejected +type NonAdminBSLRequestPhase string + +// Predefined NonAdminBSLRequestConditions +const ( + NonAdminBSLRequestApproved NonAdminBSLRequest = "approve" + NonAdminBSLRequestRejected NonAdminBSLRequest = "reject" + NonAdminBSLRequestPending NonAdminBSLRequest = "pending" +) + +// Predefined NonAdminBSLRequestPhases +const ( + NonAdminBSLRequestPhasePending NonAdminBSLRequestPhase = "Pending" + NonAdminBSLRequestPhaseApproved NonAdminBSLRequestPhase = "Approved" + NonAdminBSLRequestPhaseRejected NonAdminBSLRequestPhase = "Rejected" +) + +// NonAdminBackupStorageLocationRequestSpec defines the desired state of NonAdminBackupStorageLocationRequest +type NonAdminBackupStorageLocationRequestSpec struct { + // approvalDecision is the decision of the cluster admin on the Requested NonAdminBackupStorageLocation creation. + // The value may be set to either approve or reject. + // +optional + ApprovalDecision NonAdminBSLRequest `json:"approvalDecision,omitempty"` +} + +// SourceNonAdminBSL contains information of the NonAdminBackupStorageLocation object that triggered NonAdminBSLRequest +type SourceNonAdminBSL struct { + // requestedSpec contains the requested Velero BackupStorageLocation spec from the NonAdminBackupStorageLocation + // +optionl + RequestedSpec *velerov1.BackupStorageLocationSpec `json:"requestedSpec"` + + // nacuuid references the NonAdminBackupStorageLocation object by it's label containing same NACUUID. + // +optional + NACUUID string `json:"nacuuid,omitempty"` + + // name references the NonAdminBackupStorageLocation object by it's name. + // +optional + Name string `json:"name,omitempty"` + + // namespace references the Namespace in which NonAdminBackupStorageLocation exists. + // +optional + Namespace string `json:"namespace,omitempty"` +} + +// NonAdminBackupStorageLocationRequestStatus defines the observed state of NonAdminBackupStorageLocationRequest +type NonAdminBackupStorageLocationRequestStatus struct { + // nonAdminBackupStorageLocation contains information of the NonAdminBackupStorageLocation object that triggered NonAdminBSLRequest + // +optional + SourceNonAdminBSL *SourceNonAdminBSL `json:"nonAdminBackupStorageLocation,omitempty"` + + // phase represents the current state of the NonAdminBSLRequest. It can be either Pending, Approved or Rejected. + // +optional + Phase NonAdminBSLRequestPhase `json:"phase,omitempty"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:resource:path=nonadminbackupstoragelocationrequests,shortName=nabslrequest +// +kubebuilder:printcolumn:name="Request-Phase",type="string",JSONPath=".status.phase" +// +kubebuilder:printcolumn:name="Request-Namespace",type="string",JSONPath=".status.nonAdminBackupStorageLocation.namespace" +// +kubebuilder:printcolumn:name="Request-Name",type="string",JSONPath=".status.nonAdminBackupStorageLocation.name" +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" + +// NonAdminBackupStorageLocationRequest is the Schema for the nonadminbackupstoragelocationrequests API +type NonAdminBackupStorageLocationRequest struct { + Status NonAdminBackupStorageLocationRequestStatus `json:"status,omitempty"` + Spec NonAdminBackupStorageLocationRequestSpec `json:"spec,omitempty"` + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` +} + +// +kubebuilder:object:root=true + +// NonAdminBackupStorageLocationRequestList contains a list of NonAdminBackupStorageLocationRequest +type NonAdminBackupStorageLocationRequestList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []NonAdminBackupStorageLocationRequest `json:"items"` +} + +func init() { + SchemeBuilder.Register(&NonAdminBackupStorageLocationRequest{}, &NonAdminBackupStorageLocationRequestList{}) +} diff --git a/api/v1alpha1/nonadmindownloadrequest_types.go b/api/v1alpha1/nonadmindownloadrequest_types.go new file mode 100644 index 00000000000..4add538aaab --- /dev/null +++ b/api/v1alpha1/nonadmindownloadrequest_types.go @@ -0,0 +1,113 @@ +/* +Copyright 2024. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + "fmt" + + velerov1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// NonAdminDownloadRequestSpec defines the desired state of NonAdminDownloadRequest. +// Mirrors velero DownloadRequestSpec to allow non admins to download information for a non admin backup/restore +type NonAdminDownloadRequestSpec struct { + // Target is what to download (e.g. logs for a backup). + Target velerov1.DownloadTarget `json:"target"` +} + +// VeleroDownloadRequest represents VeleroDownloadRequest +type VeleroDownloadRequest struct { + // VeleroDownloadRequestStatus represents VeleroDownloadRequestStatus + // +optional + Status *velerov1.DownloadRequestStatus `json:"status,omitempty"` +} + +// NonAdminDownloadRequestStatus defines the observed state of NonAdminDownloadRequest. +type NonAdminDownloadRequestStatus struct { + // +optional + VeleroDownloadRequest VeleroDownloadRequest `json:"velero,omitempty"` + // phase is a simple one high-level summary of the lifecycle of an NonAdminDownloadRequest + Phase NonAdminPhase `json:"phase,omitempty"` + + Conditions []metav1.Condition `json:"conditions,omitempty"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:resource:path=nonadmindownloadrequests,shortName=nadr +// +kubebuilder:printcolumn:name="Request-Phase",type="string",JSONPath=".status.phase" +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" + +// NonAdminDownloadRequest is the Schema for the nonadmindownloadrequests API. +type NonAdminDownloadRequest struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec NonAdminDownloadRequestSpec `json:"spec,omitempty"` + Status NonAdminDownloadRequestStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// NonAdminDownloadRequestList contains a list of NonAdminDownloadRequest. +type NonAdminDownloadRequestList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []NonAdminDownloadRequest `json:"items"` +} + +func init() { + SchemeBuilder.Register(&NonAdminDownloadRequest{}, &NonAdminDownloadRequestList{}) +} + +// NonAdminDownloadRequestConditionType prevents untyped strings for NADR conditions functions +type NonAdminDownloadRequestConditionType string + +const ( + // ConditionNonAdminBackupStorageLocationNotUsed block download requests processing if NaBSL is not used + ConditionNonAdminBackupStorageLocationNotUsed NonAdminDownloadRequestConditionType = "NonAdminBackupStorageLocationNotUsed" + // ConditionNonAdminBackupNotAvailable indicates backup is not available, and will backoff download request + ConditionNonAdminBackupNotAvailable NonAdminDownloadRequestConditionType = "NonAdminBackupNotAvailable" + // ConditionNonAdminRestoreNotAvailable indicates restore is not available, and will backoff download request + ConditionNonAdminRestoreNotAvailable NonAdminDownloadRequestConditionType = "NonAdminRestoreNotAvailable" + // ConditionNonAdminProcessed indicates that the NADR is in a terminal state + ConditionNonAdminProcessed NonAdminDownloadRequestConditionType = "Processed" +) + +// ReadyForProcessing returns if this NonAdminDownloadRequests is in a state ready for processing +// +// Terminal conditions include +// - NonAdminBackupStorageLocationNotUsed: we currently require NaBSL usage on the NAB/NAR to process this download request +// returns true if ready for processing, false otherwise +func (nadr *NonAdminDownloadRequest) ReadyForProcessing() bool { + // if nadr has ConditionNonAdminBackupStorageLocationUsed return false + if nadr.Status.Conditions != nil { + for _, condition := range nadr.Status.Conditions { + if condition.Type == string(ConditionNonAdminBackupStorageLocationNotUsed) && + condition.Status == metav1.ConditionTrue { + return false + } + } + } + return true // required fields are set via velero validation markers +} + +// VeleroDownloadRequestName defines velero download request name for this NonAdminDownloadRequest +func (nadr *NonAdminDownloadRequest) VeleroDownloadRequestName() string { + return fmt.Sprintf("nadr-%s", string(nadr.GetUID())) +} diff --git a/api/v1alpha1/nonadminrestore_types.go b/api/v1alpha1/nonadminrestore_types.go new file mode 100644 index 00000000000..6ef6b0881ca --- /dev/null +++ b/api/v1alpha1/nonadminrestore_types.go @@ -0,0 +1,179 @@ +/* +Copyright 2024. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + velerov1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/openshift/oadp-operator/internal/common/constant" +) + +// NonAdminRestoreSpec defines the desired state of NonAdminRestore +type NonAdminRestoreSpec struct { + // restoreSpec defines the specification for a Velero restore. + RestoreSpec *velerov1.RestoreSpec `json:"restoreSpec"` +} + +// VeleroRestore contains information of the related Velero restore object. +type VeleroRestore struct { + // status captures the current status of the Velero restore. + // +optional + Status *velerov1.RestoreStatus `json:"status,omitempty"` + + // references the Velero Restore object by it's name. + // +optional + Name string `json:"name,omitempty"` + + // nacuuid references the Velero Restore object by it's label containing same NACUUID. + // +optional + NACUUID string `json:"nacuuid,omitempty"` + + // namespace references the Namespace in which Velero Restore exists. + // +optional + Namespace string `json:"namespace,omitempty"` +} + +// DataMoverDataDownloads contains information of the related Velero DataDownload objects. +type DataMoverDataDownloads struct { + // number of DataDownloads related to this NonAdminRestore's Restore + // +optional + Total int `json:"total,omitempty"` + + // number of DataDownloads related to this NonAdminRestore's Restore in phase New + // +optional + New int `json:"new,omitempty"` + + // number of DataDownloads related to this NonAdminRestore's Restore in phase Accepted + // +optional + Accepted int `json:"accepted,omitempty"` + + // number of DataDownloads related to this NonAdminRestore's Restore in phase Prepared + // +optional + Prepared int `json:"prepared,omitempty"` + + // number of DataDownloads related to this NonAdminRestore's Restore in phase InProgress + // +optional + InProgress int `json:"inProgress,omitempty"` + + // number of DataDownloads related to this NonAdminRestore's Restore in phase Canceling + // +optional + Canceling int `json:"canceling,omitempty"` + + // number of DataDownloads related to this NonAdminRestore's Restore in phase Canceled + // +optional + Canceled int `json:"canceled,omitempty"` + + // number of DataDownloads related to this NonAdminRestore's Restore in phase Failed + // +optional + Failed int `json:"failed,omitempty"` + + // number of DataDownloads related to this NonAdminRestore's Restore in phase Completed + // +optional + Completed int `json:"completed,omitempty"` +} + +// FileSystemPodVolumeRestores contains information of the related Velero PodVolumeRestore objects. +type FileSystemPodVolumeRestores struct { + // number of PodVolumeRestores related to this NonAdminRestore's Restore + // +optional + Total int `json:"total,omitempty"` + + // number of PodVolumeRestores related to this NonAdminRestore's Restore in phase New + // +optional + New int `json:"new,omitempty"` + + // number of PodVolumeRestores related to this NonAdminRestore's Restore in phase InProgress + // +optional + InProgress int `json:"inProgress,omitempty"` + + // number of PodVolumeRestores related to this NonAdminRestore's Restore in phase Failed + // +optional + Failed int `json:"failed,omitempty"` + + // number of PodVolumeRestores related to this NonAdminRestore's Restore in phase Completed + // +optional + Completed int `json:"completed,omitempty"` +} + +// NonAdminRestoreStatus defines the observed state of NonAdminRestore +type NonAdminRestoreStatus struct { + // +optional + VeleroRestore *VeleroRestore `json:"veleroRestore,omitempty"` + + // +optional + DataMoverDataDownloads *DataMoverDataDownloads `json:"dataMoverDataDownloads,omitempty"` + + // +optional + FileSystemPodVolumeRestores *FileSystemPodVolumeRestores `json:"fileSystemPodVolumeRestores,omitempty"` + + // queueInfo is used to estimate how many restores are scheduled before the given VeleroRestore in the OADP namespace. + // This number is not guaranteed to be accurate, but it should be close. It's inaccurate for cases when + // Velero pod is not running or being restarted after Restore object were created. + // It counts only VeleroRestores that are still subject to be handled by OADP/Velero. + // +optional + QueueInfo *QueueInfo `json:"queueInfo,omitempty"` + + // phase is a simple one high-level summary of the lifecycle of an NonAdminRestore. + Phase NonAdminPhase `json:"phase,omitempty"` + + Conditions []metav1.Condition `json:"conditions,omitempty"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:resource:path=nonadminrestores,shortName=nar +// +kubebuilder:printcolumn:name="Request-Phase",type="string",JSONPath=".status.phase" +// +kubebuilder:printcolumn:name="Velero-Phase",type="string",JSONPath=".status.veleroRestore.status.phase" +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" + +// NonAdminRestore is the Schema for the nonadminrestores API +type NonAdminRestore struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec NonAdminRestoreSpec `json:"spec,omitempty"` + Status NonAdminRestoreStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// NonAdminRestoreList contains a list of NonAdminRestore +type NonAdminRestoreList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []NonAdminRestore `json:"items"` +} + +func init() { + SchemeBuilder.Register(&NonAdminRestore{}, &NonAdminRestoreList{}) +} + +// Helper Functions to avoid digging into NAR controller to understand how to get desired values + +// VeleroRestoreName returns the name of the VeleroRestore object. +func (nar *NonAdminRestore) VeleroRestoreName() string { + if nar.Status.VeleroRestore == nil { + return constant.EmptyString + } + return nar.Status.VeleroRestore.Name +} + +// NonAdminBackupName returns NonAdminBackup name of this NAR +func (nar *NonAdminRestore) NonAdminBackupName() string { + return nar.Spec.RestoreSpec.BackupName +} diff --git a/api/v1alpha1/oadp_types.go b/api/v1alpha1/oadp_types.go index c3d6505219f..b76988cb550 100644 --- a/api/v1alpha1/oadp_types.go +++ b/api/v1alpha1/oadp_types.go @@ -76,6 +76,12 @@ const OperatorTypeKey UnsupportedImageKey = "operator-type" const OperatorTypeMTC = "mtc" +// NAC defaults +const ( + DefaultGarbageCollectionPeriod = 24 * time.Hour + DefaultBackupSyncPeriod = 2 * time.Minute +) + type VeleroConfig struct { // featureFlags defines the list of features to enable for Velero instance // +optional diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 41119dbcbbc..540dc55e8d0 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -22,8 +22,8 @@ package v1alpha1 import ( "github.com/openshift/oadp-operator/pkg/velero/server" - velerov1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" - "k8s.io/api/core/v1" + "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -63,7 +63,7 @@ func (in *BackupLocation) DeepCopyInto(out *BackupLocation) { *out = *in if in.Velero != nil { in, out := &in.Velero, &out.Velero - *out = new(velerov1.BackupStorageLocationSpec) + *out = new(v1.BackupStorageLocationSpec) (*in).DeepCopyInto(*out) } if in.CloudStorage != nil { @@ -155,7 +155,7 @@ func (in *CloudStorageLocation) DeepCopyInto(out *CloudStorageLocation) { } if in.Credential != nil { in, out := &in.Credential, &out.Credential - *out = new(v1.SecretKeySelector) + *out = new(corev1.SecretKeySelector) (*in).DeepCopyInto(*out) } if in.BackupSyncPeriod != nil { @@ -269,6 +269,36 @@ func (in *DataMover) DeepCopy() *DataMover { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataMoverDataDownloads) DeepCopyInto(out *DataMoverDataDownloads) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataMoverDataDownloads. +func (in *DataMoverDataDownloads) DeepCopy() *DataMoverDataDownloads { + if in == nil { + return nil + } + out := new(DataMoverDataDownloads) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataMoverDataUploads) DeepCopyInto(out *DataMoverDataUploads) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataMoverDataUploads. +func (in *DataMoverDataUploads) DeepCopy() *DataMoverDataUploads { + if in == nil { + return nil + } + out := new(DataMoverDataUploads) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DataMoverVolumeOptions) DeepCopyInto(out *DataMoverVolumeOptions) { *out = *in @@ -402,7 +432,7 @@ func (in *DataProtectionApplicationSpec) DeepCopyInto(out *DataProtectionApplica } if in.ImagePullPolicy != nil { in, out := &in.ImagePullPolicy, &out.ImagePullPolicy - *out = new(v1.PullPolicy) + *out = new(corev1.PullPolicy) **out = **in } if in.NonAdmin != nil { @@ -456,7 +486,7 @@ func (in *EnforceBackupStorageLocationSpec) DeepCopyInto(out *EnforceBackupStora } if in.Credential != nil { in, out := &in.Credential, &out.Credential - *out = new(v1.SecretKeySelector) + *out = new(corev1.SecretKeySelector) (*in).DeepCopyInto(*out) } in.StorageType.DeepCopyInto(&out.StorageType) @@ -502,6 +532,36 @@ func (in *Features) DeepCopy() *Features { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FileSystemPodVolumeBackups) DeepCopyInto(out *FileSystemPodVolumeBackups) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FileSystemPodVolumeBackups. +func (in *FileSystemPodVolumeBackups) DeepCopy() *FileSystemPodVolumeBackups { + if in == nil { + return nil + } + out := new(FileSystemPodVolumeBackups) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FileSystemPodVolumeRestores) DeepCopyInto(out *FileSystemPodVolumeRestores) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FileSystemPodVolumeRestores. +func (in *FileSystemPodVolumeRestores) DeepCopy() *FileSystemPodVolumeRestores { + if in == nil { + return nil + } + out := new(FileSystemPodVolumeRestores) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NodeAgentCommonFields) DeepCopyInto(out *NodeAgentCommonFields) { *out = *in @@ -558,12 +618,12 @@ func (in *NonAdmin) DeepCopyInto(out *NonAdmin) { } if in.EnforceBackupSpec != nil { in, out := &in.EnforceBackupSpec, &out.EnforceBackupSpec - *out = new(velerov1.BackupSpec) + *out = new(v1.BackupSpec) (*in).DeepCopyInto(*out) } if in.EnforceRestoreSpec != nil { in, out := &in.EnforceRestoreSpec, &out.EnforceRestoreSpec - *out = new(velerov1.RestoreSpec) + *out = new(v1.RestoreSpec) (*in).DeepCopyInto(*out) } if in.EnforceBSLSpec != nil { @@ -599,165 +659,790 @@ func (in *NonAdmin) DeepCopy() *NonAdmin { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ObjectStorageLocation) DeepCopyInto(out *ObjectStorageLocation) { +func (in *NonAdminBackup) DeepCopyInto(out *NonAdminBackup) { *out = *in - if in.CACert != nil { - in, out := &in.CACert, &out.CACert - *out = make([]byte, len(*in)) - copy(*out, *in) - } + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectStorageLocation. -func (in *ObjectStorageLocation) DeepCopy() *ObjectStorageLocation { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminBackup. +func (in *NonAdminBackup) DeepCopy() *NonAdminBackup { if in == nil { return nil } - out := new(ObjectStorageLocation) + out := new(NonAdminBackup) in.DeepCopyInto(out) return out } +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NonAdminBackup) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PodConfig) DeepCopyInto(out *PodConfig) { +func (in *NonAdminBackupList) DeepCopyInto(out *NonAdminBackupList) { *out = *in - if in.Labels != nil { - in, out := &in.Labels, &out.Labels - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]NonAdminBackup, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) } } - if in.NodeSelector != nil { - in, out := &in.NodeSelector, &out.NodeSelector - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val - } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminBackupList. +func (in *NonAdminBackupList) DeepCopy() *NonAdminBackupList { + if in == nil { + return nil } - if in.Tolerations != nil { - in, out := &in.Tolerations, &out.Tolerations - *out = make([]v1.Toleration, len(*in)) + out := new(NonAdminBackupList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NonAdminBackupList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NonAdminBackupSpec) DeepCopyInto(out *NonAdminBackupSpec) { + *out = *in + if in.BackupSpec != nil { + in, out := &in.BackupSpec, &out.BackupSpec + *out = new(v1.BackupSpec) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminBackupSpec. +func (in *NonAdminBackupSpec) DeepCopy() *NonAdminBackupSpec { + if in == nil { + return nil + } + out := new(NonAdminBackupSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NonAdminBackupStatus) DeepCopyInto(out *NonAdminBackupStatus) { + *out = *in + if in.VeleroBackup != nil { + in, out := &in.VeleroBackup, &out.VeleroBackup + *out = new(VeleroBackup) + (*in).DeepCopyInto(*out) + } + if in.VeleroDeleteBackupRequest != nil { + in, out := &in.VeleroDeleteBackupRequest, &out.VeleroDeleteBackupRequest + *out = new(VeleroDeleteBackupRequest) + (*in).DeepCopyInto(*out) + } + if in.DataMoverDataUploads != nil { + in, out := &in.DataMoverDataUploads, &out.DataMoverDataUploads + *out = new(DataMoverDataUploads) + **out = **in + } + if in.FileSystemPodVolumeBackups != nil { + in, out := &in.FileSystemPodVolumeBackups, &out.FileSystemPodVolumeBackups + *out = new(FileSystemPodVolumeBackups) + **out = **in + } + if in.QueueInfo != nil { + in, out := &in.QueueInfo, &out.QueueInfo + *out = new(QueueInfo) + **out = **in + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]metav1.Condition, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } } - in.ResourceAllocations.DeepCopyInto(&out.ResourceAllocations) - if in.Env != nil { - in, out := &in.Env, &out.Env - *out = make([]v1.EnvVar, len(*in)) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminBackupStatus. +func (in *NonAdminBackupStatus) DeepCopy() *NonAdminBackupStatus { + if in == nil { + return nil + } + out := new(NonAdminBackupStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NonAdminBackupStorageLocation) DeepCopyInto(out *NonAdminBackupStorageLocation) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminBackupStorageLocation. +func (in *NonAdminBackupStorageLocation) DeepCopy() *NonAdminBackupStorageLocation { + if in == nil { + return nil + } + out := new(NonAdminBackupStorageLocation) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NonAdminBackupStorageLocation) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NonAdminBackupStorageLocationList) DeepCopyInto(out *NonAdminBackupStorageLocationList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]NonAdminBackupStorageLocation, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodConfig. -func (in *PodConfig) DeepCopy() *PodConfig { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminBackupStorageLocationList. +func (in *NonAdminBackupStorageLocationList) DeepCopy() *NonAdminBackupStorageLocationList { if in == nil { return nil } - out := new(PodConfig) + out := new(NonAdminBackupStorageLocationList) in.DeepCopyInto(out) return out } +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NonAdminBackupStorageLocationList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ResticConfig) DeepCopyInto(out *ResticConfig) { +func (in *NonAdminBackupStorageLocationRequest) DeepCopyInto(out *NonAdminBackupStorageLocationRequest) { *out = *in - in.NodeAgentCommonFields.DeepCopyInto(&out.NodeAgentCommonFields) + in.Status.DeepCopyInto(&out.Status) + out.Spec = in.Spec + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResticConfig. -func (in *ResticConfig) DeepCopy() *ResticConfig { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminBackupStorageLocationRequest. +func (in *NonAdminBackupStorageLocationRequest) DeepCopy() *NonAdminBackupStorageLocationRequest { if in == nil { return nil } - out := new(ResticConfig) + out := new(NonAdminBackupStorageLocationRequest) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NonAdminBackupStorageLocationRequest) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NonAdminBackupStorageLocationRequestList) DeepCopyInto(out *NonAdminBackupStorageLocationRequestList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]NonAdminBackupStorageLocationRequest, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminBackupStorageLocationRequestList. +func (in *NonAdminBackupStorageLocationRequestList) DeepCopy() *NonAdminBackupStorageLocationRequestList { + if in == nil { + return nil + } + out := new(NonAdminBackupStorageLocationRequestList) in.DeepCopyInto(out) return out } +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NonAdminBackupStorageLocationRequestList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *RetainPolicy) DeepCopyInto(out *RetainPolicy) { +func (in *NonAdminBackupStorageLocationRequestSpec) DeepCopyInto(out *NonAdminBackupStorageLocationRequestSpec) { *out = *in } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RetainPolicy. -func (in *RetainPolicy) DeepCopy() *RetainPolicy { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminBackupStorageLocationRequestSpec. +func (in *NonAdminBackupStorageLocationRequestSpec) DeepCopy() *NonAdminBackupStorageLocationRequestSpec { if in == nil { return nil } - out := new(RetainPolicy) + out := new(NonAdminBackupStorageLocationRequestSpec) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SnapshotLocation) DeepCopyInto(out *SnapshotLocation) { +func (in *NonAdminBackupStorageLocationRequestStatus) DeepCopyInto(out *NonAdminBackupStorageLocationRequestStatus) { *out = *in - if in.Velero != nil { - in, out := &in.Velero, &out.Velero - *out = new(velerov1.VolumeSnapshotLocationSpec) + if in.SourceNonAdminBSL != nil { + in, out := &in.SourceNonAdminBSL, &out.SourceNonAdminBSL + *out = new(SourceNonAdminBSL) (*in).DeepCopyInto(*out) } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SnapshotLocation. -func (in *SnapshotLocation) DeepCopy() *SnapshotLocation { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminBackupStorageLocationRequestStatus. +func (in *NonAdminBackupStorageLocationRequestStatus) DeepCopy() *NonAdminBackupStorageLocationRequestStatus { if in == nil { return nil } - out := new(SnapshotLocation) + out := new(NonAdminBackupStorageLocationRequestStatus) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *StorageType) DeepCopyInto(out *StorageType) { +func (in *NonAdminBackupStorageLocationSpec) DeepCopyInto(out *NonAdminBackupStorageLocationSpec) { *out = *in - if in.ObjectStorage != nil { - in, out := &in.ObjectStorage, &out.ObjectStorage - *out = new(ObjectStorageLocation) + if in.BackupStorageLocationSpec != nil { + in, out := &in.BackupStorageLocationSpec, &out.BackupStorageLocationSpec + *out = new(v1.BackupStorageLocationSpec) (*in).DeepCopyInto(*out) } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageType. -func (in *StorageType) DeepCopy() *StorageType { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminBackupStorageLocationSpec. +func (in *NonAdminBackupStorageLocationSpec) DeepCopy() *NonAdminBackupStorageLocationSpec { if in == nil { return nil } - out := new(StorageType) + out := new(NonAdminBackupStorageLocationSpec) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *VeleroConfig) DeepCopyInto(out *VeleroConfig) { +func (in *NonAdminBackupStorageLocationStatus) DeepCopyInto(out *NonAdminBackupStorageLocationStatus) { *out = *in - if in.FeatureFlags != nil { - in, out := &in.FeatureFlags, &out.FeatureFlags - *out = make([]string, len(*in)) - copy(*out, *in) - } - if in.DefaultPlugins != nil { - in, out := &in.DefaultPlugins, &out.DefaultPlugins - *out = make([]DefaultPlugin, len(*in)) - copy(*out, *in) - } - if in.CustomPlugins != nil { - in, out := &in.CustomPlugins, &out.CustomPlugins - *out = make([]CustomPlugin, len(*in)) - copy(*out, *in) - } - if in.PodConfig != nil { - in, out := &in.PodConfig, &out.PodConfig - *out = new(PodConfig) + if in.VeleroBackupStorageLocation != nil { + in, out := &in.VeleroBackupStorageLocation, &out.VeleroBackupStorageLocation + *out = new(VeleroBackupStorageLocation) (*in).DeepCopyInto(*out) } - if in.DefaultVolumesToFSBackup != nil { - in, out := &in.DefaultVolumesToFSBackup, &out.DefaultVolumesToFSBackup + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]metav1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminBackupStorageLocationStatus. +func (in *NonAdminBackupStorageLocationStatus) DeepCopy() *NonAdminBackupStorageLocationStatus { + if in == nil { + return nil + } + out := new(NonAdminBackupStorageLocationStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NonAdminDownloadRequest) DeepCopyInto(out *NonAdminDownloadRequest) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminDownloadRequest. +func (in *NonAdminDownloadRequest) DeepCopy() *NonAdminDownloadRequest { + if in == nil { + return nil + } + out := new(NonAdminDownloadRequest) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NonAdminDownloadRequest) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NonAdminDownloadRequestList) DeepCopyInto(out *NonAdminDownloadRequestList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]NonAdminDownloadRequest, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminDownloadRequestList. +func (in *NonAdminDownloadRequestList) DeepCopy() *NonAdminDownloadRequestList { + if in == nil { + return nil + } + out := new(NonAdminDownloadRequestList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NonAdminDownloadRequestList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NonAdminDownloadRequestSpec) DeepCopyInto(out *NonAdminDownloadRequestSpec) { + *out = *in + out.Target = in.Target +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminDownloadRequestSpec. +func (in *NonAdminDownloadRequestSpec) DeepCopy() *NonAdminDownloadRequestSpec { + if in == nil { + return nil + } + out := new(NonAdminDownloadRequestSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NonAdminDownloadRequestStatus) DeepCopyInto(out *NonAdminDownloadRequestStatus) { + *out = *in + in.VeleroDownloadRequest.DeepCopyInto(&out.VeleroDownloadRequest) + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]metav1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminDownloadRequestStatus. +func (in *NonAdminDownloadRequestStatus) DeepCopy() *NonAdminDownloadRequestStatus { + if in == nil { + return nil + } + out := new(NonAdminDownloadRequestStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NonAdminRestore) DeepCopyInto(out *NonAdminRestore) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminRestore. +func (in *NonAdminRestore) DeepCopy() *NonAdminRestore { + if in == nil { + return nil + } + out := new(NonAdminRestore) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NonAdminRestore) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NonAdminRestoreList) DeepCopyInto(out *NonAdminRestoreList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]NonAdminRestore, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminRestoreList. +func (in *NonAdminRestoreList) DeepCopy() *NonAdminRestoreList { + if in == nil { + return nil + } + out := new(NonAdminRestoreList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NonAdminRestoreList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NonAdminRestoreSpec) DeepCopyInto(out *NonAdminRestoreSpec) { + *out = *in + if in.RestoreSpec != nil { + in, out := &in.RestoreSpec, &out.RestoreSpec + *out = new(v1.RestoreSpec) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminRestoreSpec. +func (in *NonAdminRestoreSpec) DeepCopy() *NonAdminRestoreSpec { + if in == nil { + return nil + } + out := new(NonAdminRestoreSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NonAdminRestoreStatus) DeepCopyInto(out *NonAdminRestoreStatus) { + *out = *in + if in.VeleroRestore != nil { + in, out := &in.VeleroRestore, &out.VeleroRestore + *out = new(VeleroRestore) + (*in).DeepCopyInto(*out) + } + if in.DataMoverDataDownloads != nil { + in, out := &in.DataMoverDataDownloads, &out.DataMoverDataDownloads + *out = new(DataMoverDataDownloads) + **out = **in + } + if in.FileSystemPodVolumeRestores != nil { + in, out := &in.FileSystemPodVolumeRestores, &out.FileSystemPodVolumeRestores + *out = new(FileSystemPodVolumeRestores) + **out = **in + } + if in.QueueInfo != nil { + in, out := &in.QueueInfo, &out.QueueInfo + *out = new(QueueInfo) + **out = **in + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]metav1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminRestoreStatus. +func (in *NonAdminRestoreStatus) DeepCopy() *NonAdminRestoreStatus { + if in == nil { + return nil + } + out := new(NonAdminRestoreStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ObjectStorageLocation) DeepCopyInto(out *ObjectStorageLocation) { + *out = *in + if in.CACert != nil { + in, out := &in.CACert, &out.CACert + *out = make([]byte, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectStorageLocation. +func (in *ObjectStorageLocation) DeepCopy() *ObjectStorageLocation { + if in == nil { + return nil + } + out := new(ObjectStorageLocation) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodConfig) DeepCopyInto(out *PodConfig) { + *out = *in + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.NodeSelector != nil { + in, out := &in.NodeSelector, &out.NodeSelector + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Tolerations != nil { + in, out := &in.Tolerations, &out.Tolerations + *out = make([]corev1.Toleration, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + in.ResourceAllocations.DeepCopyInto(&out.ResourceAllocations) + if in.Env != nil { + in, out := &in.Env, &out.Env + *out = make([]corev1.EnvVar, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodConfig. +func (in *PodConfig) DeepCopy() *PodConfig { + if in == nil { + return nil + } + out := new(PodConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *QueueInfo) DeepCopyInto(out *QueueInfo) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new QueueInfo. +func (in *QueueInfo) DeepCopy() *QueueInfo { + if in == nil { + return nil + } + out := new(QueueInfo) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResticConfig) DeepCopyInto(out *ResticConfig) { + *out = *in + in.NodeAgentCommonFields.DeepCopyInto(&out.NodeAgentCommonFields) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResticConfig. +func (in *ResticConfig) DeepCopy() *ResticConfig { + if in == nil { + return nil + } + out := new(ResticConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RetainPolicy) DeepCopyInto(out *RetainPolicy) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RetainPolicy. +func (in *RetainPolicy) DeepCopy() *RetainPolicy { + if in == nil { + return nil + } + out := new(RetainPolicy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SnapshotLocation) DeepCopyInto(out *SnapshotLocation) { + *out = *in + if in.Velero != nil { + in, out := &in.Velero, &out.Velero + *out = new(v1.VolumeSnapshotLocationSpec) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SnapshotLocation. +func (in *SnapshotLocation) DeepCopy() *SnapshotLocation { + if in == nil { + return nil + } + out := new(SnapshotLocation) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SourceNonAdminBSL) DeepCopyInto(out *SourceNonAdminBSL) { + *out = *in + if in.RequestedSpec != nil { + in, out := &in.RequestedSpec, &out.RequestedSpec + *out = new(v1.BackupStorageLocationSpec) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SourceNonAdminBSL. +func (in *SourceNonAdminBSL) DeepCopy() *SourceNonAdminBSL { + if in == nil { + return nil + } + out := new(SourceNonAdminBSL) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageType) DeepCopyInto(out *StorageType) { + *out = *in + if in.ObjectStorage != nil { + in, out := &in.ObjectStorage, &out.ObjectStorage + *out = new(ObjectStorageLocation) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageType. +func (in *StorageType) DeepCopy() *StorageType { + if in == nil { + return nil + } + out := new(StorageType) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VeleroBackup) DeepCopyInto(out *VeleroBackup) { + *out = *in + if in.Spec != nil { + in, out := &in.Spec, &out.Spec + *out = new(v1.BackupSpec) + (*in).DeepCopyInto(*out) + } + if in.Status != nil { + in, out := &in.Status, &out.Status + *out = new(v1.BackupStatus) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VeleroBackup. +func (in *VeleroBackup) DeepCopy() *VeleroBackup { + if in == nil { + return nil + } + out := new(VeleroBackup) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VeleroBackupStorageLocation) DeepCopyInto(out *VeleroBackupStorageLocation) { + *out = *in + if in.Status != nil { + in, out := &in.Status, &out.Status + *out = new(v1.BackupStorageLocationStatus) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VeleroBackupStorageLocation. +func (in *VeleroBackupStorageLocation) DeepCopy() *VeleroBackupStorageLocation { + if in == nil { + return nil + } + out := new(VeleroBackupStorageLocation) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VeleroConfig) DeepCopyInto(out *VeleroConfig) { + *out = *in + if in.FeatureFlags != nil { + in, out := &in.FeatureFlags, &out.FeatureFlags + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.DefaultPlugins != nil { + in, out := &in.DefaultPlugins, &out.DefaultPlugins + *out = make([]DefaultPlugin, len(*in)) + copy(*out, *in) + } + if in.CustomPlugins != nil { + in, out := &in.CustomPlugins, &out.CustomPlugins + *out = make([]CustomPlugin, len(*in)) + copy(*out, *in) + } + if in.PodConfig != nil { + in, out := &in.PodConfig, &out.PodConfig + *out = new(PodConfig) + (*in).DeepCopyInto(*out) + } + if in.DefaultVolumesToFSBackup != nil { + in, out := &in.DefaultVolumesToFSBackup, &out.DefaultVolumesToFSBackup *out = new(bool) **out = **in } @@ -798,6 +1483,66 @@ func (in *VeleroConfig) DeepCopy() *VeleroConfig { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VeleroDeleteBackupRequest) DeepCopyInto(out *VeleroDeleteBackupRequest) { + *out = *in + if in.Status != nil { + in, out := &in.Status, &out.Status + *out = new(v1.DeleteBackupRequestStatus) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VeleroDeleteBackupRequest. +func (in *VeleroDeleteBackupRequest) DeepCopy() *VeleroDeleteBackupRequest { + if in == nil { + return nil + } + out := new(VeleroDeleteBackupRequest) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VeleroDownloadRequest) DeepCopyInto(out *VeleroDownloadRequest) { + *out = *in + if in.Status != nil { + in, out := &in.Status, &out.Status + *out = new(v1.DownloadRequestStatus) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VeleroDownloadRequest. +func (in *VeleroDownloadRequest) DeepCopy() *VeleroDownloadRequest { + if in == nil { + return nil + } + out := new(VeleroDownloadRequest) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VeleroRestore) DeepCopyInto(out *VeleroRestore) { + *out = *in + if in.Status != nil { + in, out := &in.Status, &out.Status + *out = new(v1.RestoreStatus) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VeleroRestore. +func (in *VeleroRestore) DeepCopy() *VeleroRestore { + if in == nil { + return nil + } + out := new(VeleroRestore) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VolumeOptions) DeepCopyInto(out *VolumeOptions) { *out = *in diff --git a/bundle/manifests/oadp-operator.clusterserviceversion.yaml b/bundle/manifests/oadp-operator.clusterserviceversion.yaml index cd4f8cc8eab..c5f35529a41 100644 --- a/bundle/manifests/oadp-operator.clusterserviceversion.yaml +++ b/bundle/manifests/oadp-operator.clusterserviceversion.yaml @@ -2,7 +2,152 @@ apiVersion: operators.coreos.com/v1alpha1 kind: ClusterServiceVersion metadata: annotations: - alm-examples: '[]' + alm-examples: |- + [ + { + "apiVersion": "oadp.openshift.io/v1alpha1", + "kind": "DataProtectionApplication", + "metadata": { + "name": "velero-sample" + }, + "spec": { + "backupLocations": [ + { + "velero": { + "config": { + "profile": "default", + "region": "us-east-1" + }, + "credential": { + "key": "cloud", + "name": "cloud-credentials" + }, + "default": true, + "objectStorage": { + "bucket": "my-bucket-name", + "prefix": "velero" + }, + "provider": "aws" + } + } + ], + "configuration": { + "nodeAgent": { + "enable": true, + "uploaderType": "restic" + }, + "velero": { + "defaultPlugins": [ + "openshift", + "aws", + "kubevirt" + ] + } + }, + "snapshotLocations": [ + { + "velero": { + "config": { + "profile": "default", + "region": "us-west-2" + }, + "provider": "aws" + } + } + ] + } + }, + { + "apiVersion": "velero.io/v1", + "kind": "Backup", + "metadata": { + "name": "backup", + "namespace": "openshift-adp" + }, + "spec": {} + }, + { + "apiVersion": "velero.io/v1", + "kind": "BackupStorageLocation", + "metadata": { + "name": "backupstoragelocation", + "namespace": "openshift-adp" + }, + "spec": {} + }, + { + "apiVersion": "velero.io/v1", + "kind": "DeleteBackupRequest", + "metadata": { + "name": "deletebackuprequest", + "namespace": "openshift-adp" + }, + "spec": {} + }, + { + "apiVersion": "velero.io/v1", + "kind": "DownloadRequest", + "metadata": { + "name": "downloadrequest", + "namespace": "openshift-adp" + }, + "spec": {} + }, + { + "apiVersion": "velero.io/v1", + "kind": "PodVolumeBackup", + "metadata": { + "name": "podvolumebackup", + "namespace": "openshift-adp" + }, + "spec": {} + }, + { + "apiVersion": "velero.io/v1", + "kind": "PodVolumeRestore", + "metadata": { + "name": "podvolumerestore", + "namespace": "openshift-adp" + }, + "spec": {} + }, + { + "apiVersion": "velero.io/v1", + "kind": "Restore", + "metadata": { + "name": "restore", + "namespace": "openshift-adp" + }, + "spec": {} + }, + { + "apiVersion": "velero.io/v1", + "kind": "Schedule", + "metadata": { + "name": "schedule", + "namespace": "openshift-adp" + }, + "spec": {} + }, + { + "apiVersion": "velero.io/v1", + "kind": "ServerStatusRequest", + "metadata": { + "name": "serverstatusrequest", + "namespace": "openshift-adp" + }, + "spec": {} + }, + { + "apiVersion": "velero.io/v1", + "kind": "VolumeSnapshotLocation", + "metadata": { + "name": "volumesnapshotlocation", + "namespace": "openshift-adp" + }, + "spec": {} + } + ] capabilities: Seamless Upgrades categories: | Cloud Provider,Developer Tools,Modernization & Migration,OpenShift Optional,Storage @@ -39,7 +184,399 @@ metadata: namespace: openshift-adp spec: apiservicedefinitions: {} - customresourcedefinitions: {} + customresourcedefinitions: + owned: + - description: A backup repository is an indicator of a connection from the restic/kopia + server to the backupstoragelocation. + displayName: BackupRepository + kind: BackupRepository + name: backuprepositories.velero.io + statusDescriptors: + - description: Phase is the current state of the BackupRepository. + displayName: Phase + path: phase + - description: Message is a message about the current status of the BackupRepository. + displayName: Message + path: message + - description: LastMaintenanceTime is the last time maintenance was run. + displayName: LastMaintenanceTime + path: lastMaintenanceTime + version: v1 + - 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). + displayName: Backup + kind: Backup + name: backups.velero.io + statusDescriptors: + - 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. + displayName: CompletionTimestamp + path: completionTimestamp + - description: Expiration is when this Backup is eligible for garbage collection. + displayName: Expiration + path: expiration + - description: Format Version is the backup format version, including major, + minor, and patch version. + displayName: FormatVersion + path: formatVersion + - description: Phase is the current state of the Backup + displayName: Phase + path: phase + - 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. + displayName: Progress + path: progress + - description: Start Timestamp records the time a backup was started. Separate + from CreationTimestamp, since that value changes on restores. The server's + time is used for StartTimestamps. + displayName: StartTimestamp + path: startTimestamp + - description: ValidationErrors are a slice of all validation errors (if applicable). + displayName: Validation Errors + path: validationErrors + - description: VolumeSnapshotsAttempted is the total number of attempted volume + snapshots for this backup. + displayName: VolumeSnapshotsAttempted + path: volumeSnapshotsAttempted + - description: VolumeSnapshotsCompleted is the total number of successfully + completed volume snapshots for this backup. + displayName: VolumeSnapshotsCompleted + path: volumeSnapshotsCompleted + - 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. + displayName: Warnings + path: warnings + - 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. + displayName: Errors + path: errors + version: v1 + - description: BackupStorageLocation represents an object storage location (such + as Amazon S3 Bucket) where Velero stores backup objects. + displayName: BackupStorageLocation + kind: BackupStorageLocation + name: backupstoragelocations.velero.io + statusDescriptors: + - description: Phase is the current state of the BackupStorageLocation + displayName: Phase + path: phase + - description: LastSyncedTime is the last time the contents of the location + were synced into + displayName: LastSyncedTime + path: lastSyncedTime + - description: LastValidationTime is the last time the backup store location + was validated + displayName: LastValidationTime + path: lastValidationTime + version: v1 + - description: The CloudStorage API automates the creation of a bucket for object + storage. + displayName: CloudStorage + kind: CloudStorage + name: cloudstorages.oadp.openshift.io + statusDescriptors: + - description: LastSyncTimestamp is the last time the contents of the CloudStorage + was synced + displayName: LastSyncTimestamp + path: lastSyncTimestamp + - description: Name is the name requested for the bucket (aws, gcp) or container + (azure) + displayName: Name + path: name + version: v1alpha1 + - description: DataDownload represents a data download of a volume snapshot. There + is one DataDownload created per volume to be restored. + displayName: DataDownload + kind: DataDownload + name: datadownloads.velero.io + statusDescriptors: + - description: Phase is the current state of the DataDownload. + displayName: Phase + path: phase + - description: CompletionTimestamp records the time a restore was completed. + Completion time is recorded even on failed restores. The server's time is + used for CompletionTimestamps + displayName: CompletionTimestamp + path: completionTimestamp + - description: Message is a message about the current status of the BackupRepository. + displayName: Message + path: message + - description: Node is the name of the node where the DataDownload is processed. + displayName: Node + path: node + - description: Progress holds the total number of bytes of the snapshot and + the current number of restored bytes. This can be used to display progress + information about the restore operation. + displayName: Progress + path: progress + - description: StartTimestamp records the time a restore was started. The server's + time is used for StartTimestamps + displayName: StartTimestamp + path: startTimestamp + version: v2alpha1 + - description: DataProtectionApplication represents configuration to install a + data protection application to safely backup and restore, perform disaster + recovery and migrate Kubernetes cluster resources and persistent volumes. + displayName: DataProtectionApplication + kind: DataProtectionApplication + name: dataprotectionapplications.oadp.openshift.io + statusDescriptors: + - description: Conditions defines the observed state of DataProtectionApplication + displayName: Conditions + path: conditions + version: v1alpha1 + - description: DataUpload acts as the protocol between data mover plugins and + data mover controller for the datamover backup operation + displayName: DataUpload + kind: DataUpload + name: datauploads.velero.io + statusDescriptors: + - 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 + displayName: CompletionTimestamp + path: completionTimestamp + - description: DataMoverResult stores data-mover-specific information as a result + of the DataUpload. + displayName: DataMoverResult + path: dataMoverResult + - description: Message is a message about the DataUpload's status. + displayName: Message + path: message + - description: Node is the name of the node where the DataUpload is processed. + displayName: Node + path: node + - description: Path is the full path of the snapshot volume being backed up. + displayName: Path + path: path + - description: Phase is the current state of the DataUpload. + displayName: Phase + path: phase + - description: Progress holds the total number of bytes of the volume and the + current number of backed up bytes. This can be used to display progress + information about the backup operation. + displayName: Progress + path: progress + - description: SnapshotID is the identifier for the snapshot in the backup repository. + displayName: SnapshotID + path: snapshotID + - 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 + displayName: StartTimestamp + path: startTimestamp + version: v2alpha1 + - description: DeleteBackupRequest is a request to delete one or more backups. + displayName: DeleteBackupRequest + kind: DeleteBackupRequest + name: deletebackuprequests.velero.io + statusDescriptors: + - description: Phase is the current status of a DeleteBackupRequest + displayName: Phase + path: phase + - description: Errors contains any errors that were encountered during the deletion + process. + displayName: Errors + path: errors + version: v1 + - description: DownloadRequest is a request to download an artifact from object + storage such as a backup log file. + displayName: DownloadRequest + kind: DownloadRequest + name: downloadrequests.velero.io + statusDescriptors: + - description: Phase is the current state of the DownloadRequest. + displayName: Phase + path: phase + - description: DownloadURL contains the pre-signed URL for the target file. + displayName: DownloadURL + path: downloadURL + - description: Expiration is when this DownloadRequest expires and can be deleted + by the system. + displayName: Expiration + path: expiration + version: v1 + - description: NonAdminBackup is the Schema for the nonadminbackups API + displayName: Non Admin Backup + kind: NonAdminBackup + name: nonadminbackups.oadp.openshift.io + version: v1alpha1 + - description: NonAdminBackupStorageLocationRequest is the Schema for the nonadminbackupstoragelocationrequests + API + displayName: Non Admin BackupStorageLocationRequest + kind: NonAdminBackupStorageLocationRequest + name: nonadminbackupstoragelocationrequests.oadp.openshift.io + version: v1alpha1 + - description: NonAdminBackupStorageLocation is the Schema for the nonadminbackupstoragelocations + API + displayName: Non Admin BackupStorageLocation + kind: NonAdminBackupStorageLocation + name: nonadminbackupstoragelocations.oadp.openshift.io + version: v1alpha1 + - description: NonAdminDownloadRequest is the Schema for the nonadmindownloadrequests + API + displayName: Non Admin DownloadRequest + kind: NonAdminDownloadRequest + name: nonadmindownloadrequests.oadp.openshift.io + version: v1alpha1 + - description: NonAdminRestore is the Schema for the nonadminrestores API + displayName: Non Admin Restore + kind: NonAdminRestore + name: nonadminrestores.oadp.openshift.io + version: v1alpha1 + - description: A velero pod volume backup is a restic backup of persistent volumes + attached to a running pod. + displayName: PodVolumeBackup + kind: PodVolumeBackup + name: podvolumebackups.velero.io + statusDescriptors: + - description: Phase is the current state of the PodVolumeBackup. + displayName: Phase + path: phase + - description: Path is the full path within the controller pod being backed + up. + displayName: Path + path: path + - description: SnapshotID is the identifier for the snapshot of the pod volume. + displayName: SnapshotID + path: snapshotID + - description: Message is a message about the pod volume backup's status. + displayName: Message + path: message + - 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 + displayName: StartTimestamp + path: startTimestamp + - 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 + displayName: CompletionTimestamp + path: completionTimestamp + - description: Progress holds the total number of bytes of the volume and the + current number of backed up bytes. This can be used to display progress + information about the backup operation. + displayName: Progress + path: progress + version: v1 + - description: A velero pod volume restore is a restic restore of persistent volumes + attached to a running pod. + displayName: PodVolumeRestore + kind: PodVolumeRestore + name: podvolumerestores.velero.io + statusDescriptors: + - description: Phase is the current state of the PodVolumeRestore. + displayName: Phase + path: phase + - description: Message is a message about the pod volume restore's status. + displayName: Message + path: message + - description: StartTimestamp records the time a restore was started. The server's + time is used for StartTimestamps + displayName: StartTimestamp + path: startTimestamp + - description: CompletionTimestamp records the time a restore was completed. + Completion time is recorded even on failed restores. The server's time is + used for CompletionTimestamps + displayName: CompletionTimestamp + path: completionTimestamp + - description: Progress holds the total number of bytes of the snapshot and + the current number of restored bytes. This can be used to display progress + information about the restore operation. + displayName: Progress + path: progress + version: v1 + - description: Restore is a Velero resource that represents the application of + resources from a Velero backup to a target Kubernetes cluster. + displayName: Restore + kind: Restore + name: restores.velero.io + statusDescriptors: + - description: Phase is the current state of the Restore + displayName: Phase + path: phase + - description: ValidationErrors is a slice of all validation errors (if applicable) + displayName: ValidationErrors + path: validationErrors + - 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. + displayName: Warnings + path: warnings + - 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. + displayName: Errors + path: errors + - description: FailureReason is an error that caused the entire restore to fail. + displayName: FailureReason + path: failureReason + - description: StartTimestamp records the time the restore operation was started. + The server's time is used for StartTimestamps + displayName: StartTimestamp + path: startTimestamp + - 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 + displayName: CompletionTimestamp + path: completionTimestamp + - 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. + displayName: Progress + path: progress + version: v1 + - description: Schedule is a Velero resource that represents a pre-scheduled or + periodic Backup that should be run. + displayName: Schedule + kind: Schedule + name: schedules.velero.io + statusDescriptors: + - description: Phase is the current phase of the Schedule + displayName: Phase + path: phase + - description: LastBackup is the last time a Backup was run for this Schedule + schedule + displayName: LastBackup + path: lastBackup + - description: ValidationErrors is a slice of all validation errors (if applicable) + displayName: ValidationErrors + path: validationErrors + version: v1 + - description: ServerStatusRequest is a request to access current status information + about the Velero server. + displayName: ServerStatusRequest + kind: ServerStatusRequest + name: serverstatusrequests.velero.io + statusDescriptors: + - description: Phase is the current lifecycle phase of the ServerStatusRequest. + displayName: Phase + path: phase + - description: ProcessedTimestamp is when the ServerStatusRequest was processed + by the ServerStatusRequestController. + displayName: ProcessedTimestamp + path: processedTimestamp + - description: ServerVersion is the Velero server version. + displayName: ServerVersion + path: serverVersion + - description: Plugins list information about the plugins running on the Velero + server + displayName: Plugins + path: plugins + version: v1 + - description: VolumeSnapshotLocation is a location where Velero stores volume + snapshots. + displayName: VolumeSnapshotLocation + kind: VolumeSnapshotLocation + name: volumesnapshotlocations.velero.io + statusDescriptors: + - description: Phase is the current lifecycle phase of the VolumeSnapshotLocation + displayName: Phase + path: phase + version: v1 description: | **OpenShift API for Data Protection (OADP)** operator sets up and installs Velero on the OpenShift platform, allowing users to backup and restore @@ -70,7 +607,485 @@ spec: mediatype: image/png install: spec: - deployments: [] + clusterPermissions: + - rules: + - apiGroups: + - "" + resources: + - namespaces + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - secrets + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - oadp.openshift.io + resources: + - dataprotectionapplications + verbs: + - list + - apiGroups: + - oadp.openshift.io + resources: + - nonadminbackups + - nonadminbackupstoragelocationrequests + - nonadminbackupstoragelocations + - nonadmindownloadrequests + - nonadminrestores + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - oadp.openshift.io + resources: + - nonadminbackups/finalizers + - nonadminbackupstoragelocations/finalizers + - nonadmindownloadrequests/finalizers + - nonadminrestores/finalizers + verbs: + - update + - apiGroups: + - oadp.openshift.io + resources: + - nonadminbackups/status + - nonadminbackupstoragelocationrequests/status + - nonadminbackupstoragelocations/status + - nonadmindownloadrequests/status + - nonadminrestores/status + verbs: + - get + - patch + - update + - apiGroups: + - velero.io + resources: + - backups + - backupstoragelocations + - deletebackuprequests + - downloadrequests + - restores + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - velero.io + resources: + - backupstoragelocations/status + verbs: + - get + - patch + - update + - apiGroups: + - velero.io + resources: + - datadownloads + - datauploads + - podvolumebackups + - podvolumerestores + verbs: + - get + - list + - watch + - apiGroups: + - velero.io + resources: + - downloadrequests/status + verbs: + - get + serviceAccountName: non-admin-controller + - rules: + - apiGroups: + - config.openshift.io + resources: + - infrastructures + verbs: + - get + - list + - watch + - apiGroups: + - cloudcredential.openshift.io + resources: + - credentialsrequests + verbs: + - create + - update + - get + - apiGroups: + - oadp.openshift.io + resources: + - '*' + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - coordination.k8s.io + - corev1 + resources: + - secrets + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - oadp.openshift.io + resources: + - buckets + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - oadp.openshift.io + resources: + - buckets/finalizers + verbs: + - update + - apiGroups: + - oadp.openshift.io + resources: + - buckets/status + verbs: + - get + - patch + - update + - apiGroups: + - oadp.openshift.io + resources: + - leases + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - velero.io + resources: + - '*' + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - security.openshift.io + resources: + - securitycontextconstraints + verbs: + - list + - get + - create + - delete + - patch + - update + - watch + - apiGroups: + - security.openshift.io + resourceNames: + - privileged + resources: + - securitycontextconstraints + verbs: + - use + - apiGroups: + - "" + resources: + - secrets + - configmaps + - pods + - services + - serviceaccounts + - endpoints + - persistentvolumeclaims + - events + verbs: + - list + - get + - create + - delete + - deletecollection + - patch + - update + - watch + - apiGroups: + - "" + resources: + - namespaces + verbs: + - list + - get + - create + - patch + - update + - watch + - apiGroups: + - apps + resources: + - deployments + - daemonsets + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - route.openshift.io + resources: + - routes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - monitoring.coreos.com + resources: + - servicemonitors + verbs: + - get + - create + - list + - delete + - update + - patch + - watch + - apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create + - apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create + serviceAccountName: openshift-adp-controller-manager + - rules: + - apiGroups: + - build.openshift.io + - migration.openshift.io + - rbac.authorization.k8s.io + - velero.io + resources: + - '*' + verbs: + - '*' + - apiGroups: + - "" + resources: + - serviceaccounts + verbs: + - '*' + - apiGroups: + - packages.operators.coreos.com + resources: + - packagemanifests + verbs: + - '*' + - apiGroups: + - '*' + resources: + - '*' + verbs: + - get + - watch + - list + - update + - patch + - create + - delete + - assign + - deletecollection + - nonResourceURLs: + - '*' + verbs: + - '*' + - apiGroups: + - security.openshift.io + resourceNames: + - privileged + resources: + - securitycontextconstraints + verbs: + - use + serviceAccountName: velero + deployments: + - label: + control-plane: controller-manager + name: openshift-adp-controller-manager + spec: + replicas: 1 + selector: + matchLabels: + control-plane: controller-manager + strategy: {} + template: + metadata: + labels: + control-plane: controller-manager + spec: + containers: + - args: + - --leader-elect + command: + - /manager + env: + - name: WATCH_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.annotations['olm.targetNamespaces'] + - name: RESTIC_PV_HOSTPATH + - name: FS_PV_HOSTPATH + - name: PLUGINS_HOSTPATH + - name: RELATED_IMAGE_VELERO + value: quay.io/konveyor/velero:oadp-1.4 + - name: RELATED_IMAGE_VELERO_RESTORE_HELPER + value: quay.io/konveyor/velero-restore-helper:oadp-1.4 + - name: RELATED_IMAGE_OPENSHIFT_VELERO_PLUGIN + value: quay.io/konveyor/openshift-velero-plugin:oadp-1.4 + - name: RELATED_IMAGE_VELERO_PLUGIN_FOR_AWS + value: quay.io/konveyor/velero-plugin-for-aws:oadp-1.4 + - name: RELATED_IMAGE_VELERO_PLUGIN_FOR_LEGACY_AWS + value: quay.io/konveyor/velero-plugin-for-legacy-aws:oadp-1.4 + - name: RELATED_IMAGE_VELERO_PLUGIN_FOR_MICROSOFT_AZURE + value: quay.io/konveyor/velero-plugin-for-microsoft-azure:oadp-1.4 + - name: RELATED_IMAGE_VELERO_PLUGIN_FOR_GCP + value: quay.io/konveyor/velero-plugin-for-gcp:oadp-1.4 + - name: RELATED_IMAGE_KUBEVIRT_VELERO_PLUGIN + value: quay.io/konveyor/kubevirt-velero-plugin:v0.7.0 + - name: RELATED_IMAGE_HYPERSHIFT_VELERO_PLUGIN + value: quay.io/redhat-user-workloads/ocp-art-tenant/oadp-hypershift-oadp-plugin-oadp-1-4 + - name: RELATED_IMAGE_MUSTGATHER + value: registry.redhat.io/oadp/oadp-mustgather-rhel8:v1.2 + - name: RELATED_IMAGE_NON_ADMIN_CONTROLLER + value: quay.io/konveyor/oadp-non-admin:oadp-1.4 + image: quay.io/konveyor/oadp-operator:oadp-1.4 + imagePullPolicy: Always + livenessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 15 + periodSeconds: 20 + name: manager + readinessProbe: + httpGet: + path: /readyz + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 10 + resources: + limits: + cpu: "1" + memory: 512Mi + requests: + cpu: 500m + memory: 128Mi + securityContext: + allowPrivilegeEscalation: false + startupProbe: + failureThreshold: 12 + httpGet: + path: /healthz + port: 8081 + periodSeconds: 10 + volumeMounts: + - mountPath: /var/run/secrets/openshift/serviceaccount + name: bound-sa-token + readOnly: true + securityContext: + runAsNonRoot: true + serviceAccountName: openshift-adp-controller-manager + terminationGracePeriodSeconds: 10 + volumes: + - name: bound-sa-token + projected: + sources: + - serviceAccountToken: + audience: openshift + expirationSeconds: 3600 + path: token + permissions: + - rules: + - apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch + serviceAccountName: openshift-adp-controller-manager strategy: deployment installModes: - supported: true @@ -144,5 +1159,7 @@ spec: name: hypershift-velero-plugin - image: registry.redhat.io/oadp/oadp-mustgather-rhel8:v1.2 name: mustgather + - image: quay.io/konveyor/oadp-non-admin:oadp-1.4 + name: non-admin-controller replaces: oadp-operator.v1.4.5 version: 1.4.6 diff --git a/bundle/manifests/oadp.openshift.io_dataprotectionapplications.yaml b/bundle/manifests/oadp.openshift.io_dataprotectionapplications.yaml index 793b39495a7..75a4140bc73 100644 --- a/bundle/manifests/oadp.openshift.io_dataprotectionapplications.yaml +++ b/bundle/manifests/oadp.openshift.io_dataprotectionapplications.yaml @@ -1204,6 +1204,931 @@ spec: - IfNotPresent - Never type: string + logFormat: + default: text + description: The format for log output. Valid values are text, json. (default text) + enum: + - text + - json + type: string + nonAdmin: + description: nonAdmin defines the configuration for the DPA to enable backup and restore operations for non-admin users + properties: + backupSyncPeriod: + description: |- + BackupSyncPeriod specifies the interval at which backups from the OADP namespace are synchronized with non-admin namespaces. + A value of 0 disables sync. + By default 2m + type: string + enable: + description: Enables non admin feature, by default is disabled + type: boolean + enforceBSLSpec: + description: which backupstoragelocation spec field values to enforce + properties: + accessMode: + description: AccessMode defines the permissions for the backup storage location. + enum: + - ReadOnly + - ReadWrite + type: string + backupSyncPeriod: + description: BackupSyncPeriod defines how frequently to sync backup API objects from object storage. A value of 0 disables sync. + nullable: true + type: string + config: + additionalProperties: + type: string + description: Config is for provider-specific configuration fields. + type: object + credential: + description: Credential contains the credential information intended to be used with this location + properties: + key: + description: The key of the secret to select from. Must be a valid secret key. + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + objectStorage: + description: ObjectStorageLocation defines the enforced values for the Velero ObjectStorageLocation + nullable: true + properties: + bucket: + description: Bucket is the bucket to use for object storage. + type: string + caCert: + description: CACert defines a CA bundle to use when verifying TLS connections to the provider. + format: byte + type: string + prefix: + description: Prefix is the path inside a bucket to use for Velero storage. Optional. + type: string + type: object + provider: + description: Provider is the provider of the backup storage. + type: string + validationFrequency: + description: ValidationFrequency defines how frequently to validate the corresponding object storage. A value of 0 disables validation. + nullable: true + type: string + type: object + enforceBackupSpec: + description: which bakup spec field values to enforce + 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 + enforceRestoreSpec: + description: which restore spec field values to enforce + 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 + garbageCollectionPeriod: + description: |- + GarbageCollectionPeriod defines how frequently to look for possible leftover non admin related objects in OADP namespace. + A value of 0 disables garbage collection. + By default 24h + type: string + requireApprovalForBSL: + description: |- + RequireApprovalForBSL specifies whether cluster administrator approval is required + for creating Velero BackupStorageLocation (BSL) resources. + - If set to false, all NonAdminBackupStorageLocationApproval CRDs will be automatically approved, + including those that were previously pending or rejected. + - If set to true, any existing BackupStorageLocation CRDs that lack the necessary approvals may be deleted, + leaving the associated NonAdminBackup objects non-restorable until approval is granted. + Defaults to false + type: boolean + type: object podAnnotations: additionalProperties: type: string diff --git a/bundle/manifests/oadp.openshift.io_nonadminbackups.yaml b/bundle/manifests/oadp.openshift.io_nonadminbackups.yaml index 75df43810be..907b8ce085c 100644 --- a/bundle/manifests/oadp.openshift.io_nonadminbackups.yaml +++ b/bundle/manifests/oadp.openshift.io_nonadminbackups.yaml @@ -188,13 +188,11 @@ spec: items: type: string type: array - x-kubernetes-list-type: atomic required: - key - operator type: object type: array - x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -380,13 +378,11 @@ spec: items: type: string type: array - x-kubernetes-list-type: atomic required: - key - operator type: object type: array - x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -443,13 +439,11 @@ spec: items: type: string type: array - x-kubernetes-list-type: atomic required: - key - operator type: object type: array - x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -839,13 +833,11 @@ spec: items: type: string type: array - x-kubernetes-list-type: atomic required: - key - operator type: object type: array - x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -1031,13 +1023,11 @@ spec: items: type: string type: array - x-kubernetes-list-type: atomic required: - key - operator type: object type: array - x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -1094,13 +1084,11 @@ spec: items: type: string type: array - x-kubernetes-list-type: atomic required: - key - operator type: object type: array - x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string diff --git a/bundle/manifests/oadp.openshift.io_nonadminbackupstoragelocationrequests.yaml b/bundle/manifests/oadp.openshift.io_nonadminbackupstoragelocationrequests.yaml index 0f1f473a48e..93b1add6444 100644 --- a/bundle/manifests/oadp.openshift.io_nonadminbackupstoragelocationrequests.yaml +++ b/bundle/manifests/oadp.openshift.io_nonadminbackupstoragelocationrequests.yaml @@ -118,12 +118,8 @@ spec: be a valid secret key. type: string name: - default: "" description: |- Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: diff --git a/bundle/manifests/oadp.openshift.io_nonadminbackupstoragelocations.yaml b/bundle/manifests/oadp.openshift.io_nonadminbackupstoragelocations.yaml index ae737171d4d..59a97a6071f 100644 --- a/bundle/manifests/oadp.openshift.io_nonadminbackupstoragelocations.yaml +++ b/bundle/manifests/oadp.openshift.io_nonadminbackupstoragelocations.yaml @@ -86,12 +86,8 @@ spec: a valid secret key. type: string name: - default: "" description: |- Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: diff --git a/bundle/manifests/oadp.openshift.io_nonadminrestores.yaml b/bundle/manifests/oadp.openshift.io_nonadminrestores.yaml index 42d4a9a0506..4f83f9efa49 100644 --- a/bundle/manifests/oadp.openshift.io_nonadminrestores.yaml +++ b/bundle/manifests/oadp.openshift.io_nonadminrestores.yaml @@ -151,13 +151,11 @@ spec: items: type: string type: array - x-kubernetes-list-type: atomic required: - key - operator type: object type: array - x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -307,13 +305,11 @@ spec: items: type: string type: array - x-kubernetes-list-type: atomic required: - key - operator type: object type: array - x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -372,13 +368,11 @@ spec: items: type: string type: array - x-kubernetes-list-type: atomic required: - key - operator type: object type: array - x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string diff --git a/config/crd/bases/oadp.openshift.io_nonadminbackups.yaml b/config/crd/bases/oadp.openshift.io_nonadminbackups.yaml new file mode 100644 index 00000000000..21026681a77 --- /dev/null +++ b/config/crd/bases/oadp.openshift.io_nonadminbackups.yaml @@ -0,0 +1,1362 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + name: nonadminbackups.oadp.openshift.io +spec: + group: oadp.openshift.io + names: + kind: NonAdminBackup + listKind: NonAdminBackupList + plural: nonadminbackups + shortNames: + - nab + singular: nonadminbackup + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.phase + name: Request-Phase + type: string + - jsonPath: .status.veleroBackup.status.phase + name: Velero-Phase + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: NonAdminBackup is the Schema for the nonadminbackups 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: NonAdminBackupSpec defines the desired state of NonAdminBackup + properties: + backupSpec: + 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 + deleteBackup: + description: |- + DeleteBackup removes the NonAdminBackup and its associated NonAdminRestores and VeleroBackup from the cluster, + as well as the corresponding data in object storage + type: boolean + required: + - backupSpec + type: object + status: + description: NonAdminBackupStatus defines the observed state of NonAdminBackup + properties: + conditions: + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + dataMoverDataUploads: + description: DataMoverDataUploads contains information of the related + Velero DataUpload objects. + properties: + accepted: + description: number of DataUploads related to this NonAdminBackup's + Backup in phase Accepted + type: integer + canceled: + description: number of DataUploads related to this NonAdminBackup's + Backup in phase Canceled + type: integer + canceling: + description: number of DataUploads related to this NonAdminBackup's + Backup in phase Canceling + type: integer + completed: + description: number of DataUploads related to this NonAdminBackup's + Backup in phase Completed + type: integer + failed: + description: number of DataUploads related to this NonAdminBackup's + Backup in phase Failed + type: integer + inProgress: + description: number of DataUploads related to this NonAdminBackup's + Backup in phase InProgress + type: integer + new: + description: number of DataUploads related to this NonAdminBackup's + Backup in phase New + type: integer + prepared: + description: number of DataUploads related to this NonAdminBackup's + Backup in phase Prepared + type: integer + total: + description: number of DataUploads related to this NonAdminBackup's + Backup + type: integer + type: object + fileSystemPodVolumeBackups: + description: FileSystemPodVolumeBackups contains information of the + related Velero PodVolumeBackup objects. + properties: + completed: + description: number of PodVolumeBackups related to this NonAdminBackup's + Backup in phase Completed + type: integer + failed: + description: number of PodVolumeBackups related to this NonAdminBackup's + Backup in phase Failed + type: integer + inProgress: + description: number of PodVolumeBackups related to this NonAdminBackup's + Backup in phase InProgress + type: integer + new: + description: number of PodVolumeBackups related to this NonAdminBackup's + Backup in phase New + type: integer + total: + description: number of PodVolumeBackups related to this NonAdminBackup's + Backup + type: integer + type: object + phase: + description: phase is a simple one high-level summary of the lifecycle + of an NonAdminBackup. + enum: + - New + - BackingOff + - Created + - Deleting + type: string + queueInfo: + description: |- + queueInfo is used to estimate how many backups are scheduled before the given VeleroBackup in the OADP namespace. + This number is not guaranteed to be accurate, but it should be close. It's inaccurate for cases when + Velero pod is not running or being restarted after Backup object were created. + It counts only VeleroBackups that are still subject to be handled by OADP/Velero. + properties: + estimatedQueuePosition: + description: estimatedQueuePosition is the number of operations + ahead in the queue (0 if not queued) + type: integer + required: + - estimatedQueuePosition + type: object + veleroBackup: + description: VeleroBackup contains information of the related Velero + backup object. + properties: + nacuuid: + description: nacuuid references the Velero Backup object by it's + label containing same NACUUID. + type: string + name: + description: references the Velero Backup object by it's name. + type: string + namespace: + description: namespace references the Namespace in which Velero + backup exists. + type: string + spec: + description: spec captures the current spec of the 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: status captures the current status of the 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 + veleroDeleteBackupRequest: + description: VeleroDeleteBackupRequest contains information of the + related Velero delete backup request object. + properties: + nacuuid: + description: nacuuid references the Velero delete backup request + object by it's label containing same NACUUID. + type: string + name: + description: name references the Velero delete backup request + object by it's name. + type: string + namespace: + description: namespace references the Namespace in which Velero + delete backup request exists. + type: string + status: + description: status captures the current status of the Velero + delete backup request. + properties: + errors: + description: Errors contains any errors that were encountered + during the deletion process. + items: + type: string + nullable: true + type: array + phase: + description: Phase is the current state of the DeleteBackupRequest. + enum: + - New + - InProgress + - Processed + type: string + type: object + type: object + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/bases/oadp.openshift.io_nonadminbackupstoragelocationrequests.yaml b/config/crd/bases/oadp.openshift.io_nonadminbackupstoragelocationrequests.yaml new file mode 100644 index 00000000000..18d951cadec --- /dev/null +++ b/config/crd/bases/oadp.openshift.io_nonadminbackupstoragelocationrequests.yaml @@ -0,0 +1,185 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + name: nonadminbackupstoragelocationrequests.oadp.openshift.io +spec: + group: oadp.openshift.io + names: + kind: NonAdminBackupStorageLocationRequest + listKind: NonAdminBackupStorageLocationRequestList + plural: nonadminbackupstoragelocationrequests + shortNames: + - nabslrequest + singular: nonadminbackupstoragelocationrequest + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.phase + name: Request-Phase + type: string + - jsonPath: .status.nonAdminBackupStorageLocation.namespace + name: Request-Namespace + type: string + - jsonPath: .status.nonAdminBackupStorageLocation.name + name: Request-Name + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: NonAdminBackupStorageLocationRequest is the Schema for the nonadminbackupstoragelocationrequests + 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: NonAdminBackupStorageLocationRequestSpec defines the desired + state of NonAdminBackupStorageLocationRequest + properties: + approvalDecision: + description: |- + approvalDecision is the decision of the cluster admin on the Requested NonAdminBackupStorageLocation creation. + The value may be set to either approve or reject. + enum: + - approve + - reject + - pending + type: string + type: object + status: + description: NonAdminBackupStorageLocationRequestStatus defines the observed + state of NonAdminBackupStorageLocationRequest + properties: + nonAdminBackupStorageLocation: + description: nonAdminBackupStorageLocation contains information of + the NonAdminBackupStorageLocation object that triggered NonAdminBSLRequest + properties: + nacuuid: + description: nacuuid references the NonAdminBackupStorageLocation + object by it's label containing same NACUUID. + type: string + name: + description: name references the NonAdminBackupStorageLocation + object by it's name. + type: string + namespace: + description: namespace references the Namespace in which NonAdminBackupStorageLocation + exists. + type: string + requestedSpec: + description: requestedSpec contains the requested Velero BackupStorageLocation + spec from the NonAdminBackupStorageLocation + properties: + accessMode: + description: AccessMode defines the permissions for the backup + storage location. + enum: + - ReadOnly + - ReadWrite + type: string + backupSyncPeriod: + description: BackupSyncPeriod defines how frequently to sync + backup API objects from object storage. A value of 0 disables + sync. + nullable: true + type: string + config: + additionalProperties: + type: string + description: Config is for provider-specific configuration + fields. + type: object + credential: + description: Credential contains the credential information + intended to be used with this location + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + default: + description: Default indicates this location is the default + backup storage location. + type: boolean + objectStorage: + description: ObjectStorageLocation specifies the settings + necessary to connect to a provider's object storage. + properties: + bucket: + description: Bucket is the bucket to use for object storage. + type: string + caCert: + description: CACert defines a CA bundle to use when verifying + TLS connections to the provider. + format: byte + type: string + prefix: + description: Prefix is the path inside a bucket to use + for Velero storage. Optional. + type: string + required: + - bucket + type: object + provider: + description: Provider is the provider of the backup storage. + type: string + validationFrequency: + description: ValidationFrequency defines how frequently to + validate the corresponding object storage. A value of 0 + disables validation. + nullable: true + type: string + required: + - objectStorage + - provider + type: object + required: + - requestedSpec + type: object + phase: + description: phase represents the current state of the NonAdminBSLRequest. + It can be either Pending, Approved or Rejected. + enum: + - Pending + - Approved + - Rejected + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/bases/oadp.openshift.io_nonadminbackupstoragelocations.yaml b/config/crd/bases/oadp.openshift.io_nonadminbackupstoragelocations.yaml new file mode 100644 index 00000000000..cbae62fc080 --- /dev/null +++ b/config/crd/bases/oadp.openshift.io_nonadminbackupstoragelocations.yaml @@ -0,0 +1,277 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + name: nonadminbackupstoragelocations.oadp.openshift.io +spec: + group: oadp.openshift.io + names: + kind: NonAdminBackupStorageLocation + listKind: NonAdminBackupStorageLocationList + plural: nonadminbackupstoragelocations + shortNames: + - nabsl + singular: nonadminbackupstoragelocation + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=='ClusterAdminApproved')].status + name: Request-Approved + type: string + - jsonPath: .status.phase + name: Request-Phase + type: string + - jsonPath: .status.veleroBackupStorageLocation.status.phase + name: Velero-Phase + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: NonAdminBackupStorageLocation is the Schema for the nonadminbackupstoragelocations + 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: NonAdminBackupStorageLocationSpec defines the desired state + of NonAdminBackupStorageLocation + properties: + backupStorageLocationSpec: + description: BackupStorageLocationSpec defines the desired state of + a Velero BackupStorageLocation + properties: + accessMode: + description: AccessMode defines the permissions for the backup + storage location. + enum: + - ReadOnly + - ReadWrite + type: string + backupSyncPeriod: + description: BackupSyncPeriod defines how frequently to sync backup + API objects from object storage. A value of 0 disables sync. + nullable: true + type: string + config: + additionalProperties: + type: string + description: Config is for provider-specific configuration fields. + type: object + credential: + description: Credential contains the credential information intended + to be used with this location + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key must be + defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + default: + description: Default indicates this location is the default backup + storage location. + type: boolean + objectStorage: + description: ObjectStorageLocation specifies the settings necessary + to connect to a provider's object storage. + properties: + bucket: + description: Bucket is the bucket to use for object storage. + type: string + caCert: + description: CACert defines a CA bundle to use when verifying + TLS connections to the provider. + format: byte + type: string + prefix: + description: Prefix is the path inside a bucket to use for + Velero storage. Optional. + type: string + required: + - bucket + type: object + provider: + description: Provider is the provider of the backup storage. + type: string + validationFrequency: + description: ValidationFrequency defines how frequently to validate + the corresponding object storage. A value of 0 disables validation. + nullable: true + type: string + required: + - objectStorage + - provider + type: object + required: + - backupStorageLocationSpec + type: object + status: + description: NonAdminBackupStorageLocationStatus defines the observed + state of NonAdminBackupStorageLocation + properties: + conditions: + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + phase: + description: phase is a simple one high-level summary of the lifecycle + of an NonAdminBackupStorageLocation. + enum: + - New + - BackingOff + - Created + - Deleting + type: string + veleroBackupStorageLocation: + description: VeleroBackupStorageLocation contains information of the + related Velero backup object. + properties: + nacuuid: + description: nacuuid references the Velero BackupStorageLocation + object by it's label containing same NACUUID. + type: string + name: + description: references the Velero BackupStorageLocation object + by it's name. + type: string + namespace: + description: namespace references the Namespace in which Velero + backup storage location exists. + type: string + status: + description: status captures the current status of the Velero + backup storage location. + properties: + accessMode: + description: |- + AccessMode is an unused field. + + Deprecated: there is now an AccessMode field on the Spec and this field + will be removed entirely as of v2.0. + enum: + - ReadOnly + - ReadWrite + type: string + lastSyncedRevision: + description: |- + LastSyncedRevision is the value of the `metadata/revision` file in the backup + storage location the last time the BSL's contents were synced into the cluster. + + Deprecated: this field is no longer updated or used for detecting changes to + the location's contents and will be removed entirely in v2.0. + type: string + lastSyncedTime: + description: |- + LastSyncedTime is the last time the contents of the location were synced into + the cluster. + format: date-time + nullable: true + type: string + lastValidationTime: + description: |- + LastValidationTime is the last time the backup store location was validated + the cluster. + format: date-time + nullable: true + type: string + message: + description: Message is a message about the backup storage + location's status. + type: string + phase: + description: Phase is the current state of the BackupStorageLocation. + enum: + - Available + - Unavailable + type: string + type: object + type: object + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/bases/oadp.openshift.io_nonadmindownloadrequests.yaml b/config/crd/bases/oadp.openshift.io_nonadmindownloadrequests.yaml new file mode 100644 index 00000000000..4306f7b56ae --- /dev/null +++ b/config/crd/bases/oadp.openshift.io_nonadmindownloadrequests.yaml @@ -0,0 +1,184 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + name: nonadmindownloadrequests.oadp.openshift.io +spec: + group: oadp.openshift.io + names: + kind: NonAdminDownloadRequest + listKind: NonAdminDownloadRequestList + plural: nonadmindownloadrequests + shortNames: + - nadr + singular: nonadmindownloadrequest + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.phase + name: Request-Phase + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: NonAdminDownloadRequest is the Schema for the nonadmindownloadrequests + 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: |- + NonAdminDownloadRequestSpec defines the desired state of NonAdminDownloadRequest. + Mirrors velero DownloadRequestSpec to allow non admins to download information for a non admin backup/restore + properties: + target: + description: Target is what to download (e.g. logs for a backup). + properties: + kind: + description: Kind is the type of file to download. + enum: + - BackupLog + - BackupContents + - BackupVolumeSnapshots + - BackupItemOperations + - BackupResourceList + - BackupResults + - RestoreLog + - RestoreResults + - RestoreResourceList + - RestoreItemOperations + - CSIBackupVolumeSnapshots + - CSIBackupVolumeSnapshotContents + - BackupVolumeInfos + - RestoreVolumeInfo + type: string + name: + description: Name is the name of the Kubernetes resource with + which the file is associated. + type: string + required: + - kind + - name + type: object + required: + - target + type: object + status: + description: NonAdminDownloadRequestStatus defines the observed state + of NonAdminDownloadRequest. + properties: + conditions: + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + phase: + description: phase is a simple one high-level summary of the lifecycle + of an NonAdminDownloadRequest + enum: + - New + - BackingOff + - Created + - Deleting + type: string + velero: + description: VeleroDownloadRequest represents VeleroDownloadRequest + properties: + status: + description: VeleroDownloadRequestStatus represents VeleroDownloadRequestStatus + properties: + downloadURL: + description: DownloadURL contains the pre-signed URL for the + target file. + type: string + expiration: + description: Expiration is when this DownloadRequest expires + and can be deleted by the system. + format: date-time + nullable: true + type: string + phase: + description: Phase is the current state of the DownloadRequest. + enum: + - New + - Processed + type: string + type: object + type: object + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/bases/oadp.openshift.io_nonadminrestores.yaml b/config/crd/bases/oadp.openshift.io_nonadminrestores.yaml new file mode 100644 index 00000000000..04609619879 --- /dev/null +++ b/config/crd/bases/oadp.openshift.io_nonadminrestores.yaml @@ -0,0 +1,743 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + name: nonadminrestores.oadp.openshift.io +spec: + group: oadp.openshift.io + names: + kind: NonAdminRestore + listKind: NonAdminRestoreList + plural: nonadminrestores + shortNames: + - nar + singular: nonadminrestore + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.phase + name: Request-Phase + type: string + - jsonPath: .status.veleroRestore.status.phase + name: Velero-Phase + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: NonAdminRestore is the Schema for the nonadminrestores 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: NonAdminRestoreSpec defines the desired state of NonAdminRestore + properties: + restoreSpec: + 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 + required: + - restoreSpec + type: object + status: + description: NonAdminRestoreStatus defines the observed state of NonAdminRestore + properties: + conditions: + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + dataMoverDataDownloads: + description: DataMoverDataDownloads contains information of the related + Velero DataDownload objects. + properties: + accepted: + description: number of DataDownloads related to this NonAdminRestore's + Restore in phase Accepted + type: integer + canceled: + description: number of DataDownloads related to this NonAdminRestore's + Restore in phase Canceled + type: integer + canceling: + description: number of DataDownloads related to this NonAdminRestore's + Restore in phase Canceling + type: integer + completed: + description: number of DataDownloads related to this NonAdminRestore's + Restore in phase Completed + type: integer + failed: + description: number of DataDownloads related to this NonAdminRestore's + Restore in phase Failed + type: integer + inProgress: + description: number of DataDownloads related to this NonAdminRestore's + Restore in phase InProgress + type: integer + new: + description: number of DataDownloads related to this NonAdminRestore's + Restore in phase New + type: integer + prepared: + description: number of DataDownloads related to this NonAdminRestore's + Restore in phase Prepared + type: integer + total: + description: number of DataDownloads related to this NonAdminRestore's + Restore + type: integer + type: object + fileSystemPodVolumeRestores: + description: FileSystemPodVolumeRestores contains information of the + related Velero PodVolumeRestore objects. + properties: + completed: + description: number of PodVolumeRestores related to this NonAdminRestore's + Restore in phase Completed + type: integer + failed: + description: number of PodVolumeRestores related to this NonAdminRestore's + Restore in phase Failed + type: integer + inProgress: + description: number of PodVolumeRestores related to this NonAdminRestore's + Restore in phase InProgress + type: integer + new: + description: number of PodVolumeRestores related to this NonAdminRestore's + Restore in phase New + type: integer + total: + description: number of PodVolumeRestores related to this NonAdminRestore's + Restore + type: integer + type: object + phase: + description: phase is a simple one high-level summary of the lifecycle + of an NonAdminRestore. + enum: + - New + - BackingOff + - Created + - Deleting + type: string + queueInfo: + description: |- + queueInfo is used to estimate how many restores are scheduled before the given VeleroRestore in the OADP namespace. + This number is not guaranteed to be accurate, but it should be close. It's inaccurate for cases when + Velero pod is not running or being restarted after Restore object were created. + It counts only VeleroRestores that are still subject to be handled by OADP/Velero. + properties: + estimatedQueuePosition: + description: estimatedQueuePosition is the number of operations + ahead in the queue (0 if not queued) + type: integer + required: + - estimatedQueuePosition + type: object + veleroRestore: + description: VeleroRestore contains information of the related Velero + restore object. + properties: + nacuuid: + description: nacuuid references the Velero Restore object by it's + label containing same NACUUID. + type: string + name: + description: references the Velero Restore object by it's name. + type: string + namespace: + description: namespace references the Namespace in which Velero + Restore exists. + type: string + status: + description: status captures the current status of the 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 + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index 2971b10189d..b3de3211d43 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -20,6 +20,8 @@ resources: - bases/oadp.openshift.io_nonadminbackups.yaml - bases/oadp.openshift.io_nonadminrestores.yaml - bases/oadp.openshift.io_nonadmindownloadrequests.yaml +- bases/oadp.openshift.io_nonadminbackupstoragelocations.yaml +- bases/oadp.openshift.io_nonadminbackupstoragelocationrequests.yaml #+kubebuilder:scaffold:crdkustomizeresource patchesStrategicMerge: diff --git a/config/manifests/bases/oadp-operator.clusterserviceversion.yaml b/config/manifests/bases/oadp-operator.clusterserviceversion.yaml index 3a163e08fec..21bcd595833 100644 --- a/config/manifests/bases/oadp-operator.clusterserviceversion.yaml +++ b/config/manifests/bases/oadp-operator.clusterserviceversion.yaml @@ -404,7 +404,30 @@ spec: - description: NonAdminBackup is the Schema for the nonadminbackups API displayName: Non Admin Backup kind: NonAdminBackup - name: nonadminbackups.nac.oadp.openshift.io + name: nonadminbackups.oadp.openshift.io + version: v1alpha1 + - description: NonAdminRestore is the Schema for the nonadminrestores API + displayName: Non Admin Restore + kind: NonAdminRestore + name: nonadminrestores.oadp.openshift.io + version: v1alpha1 + - description: NonAdminDownloadRequest is the Schema for the nonadmindownloadrequests + API + displayName: Non Admin DownloadRequest + kind: NonAdminDownloadRequest + name: nonadmindownloadrequests.oadp.openshift.io + version: v1alpha1 + - description: NonAdminBackupStorageLocation is the Schema for the nonadminbackupstoragelocations + API + displayName: Non Admin BackupStorageLocation + kind: NonAdminBackupStorageLocation + name: nonadminbackupstoragelocations.oadp.openshift.io + version: v1alpha1 + - description: NonAdminBackupStorageLocationRequest is the Schema for the nonadminbackupstoragelocationrequests + API + displayName: Non Admin BackupStorageLocationRequest + kind: NonAdminBackupStorageLocationRequest + name: nonadminbackupstoragelocationrequests.oadp.openshift.io version: v1alpha1 description: | **OpenShift API for Data Protection (OADP)** operator sets up and installs diff --git a/controllers/nonadmin_controller.go b/controllers/nonadmin_controller.go index be9b2181105..ba202bd26ee 100644 --- a/controllers/nonadmin_controller.go +++ b/controllers/nonadmin_controller.go @@ -49,6 +49,11 @@ var ( ) func (r *DPAReconciler) ReconcileNonAdminController(log logr.Logger) (bool, error) { + dpa := oadpv1alpha1.DataProtectionApplication{} + if err := r.Get(r.Context, r.NamespacedName, &dpa); err != nil { + return false, err + } + nonAdminDeployment := &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: nonAdminObjectName, @@ -57,7 +62,7 @@ func (r *DPAReconciler) ReconcileNonAdminController(log logr.Logger) (bool, erro } // Delete (possible) previously deployment - if !r.checkNonAdminEnabled() { + if !r.checkNonAdminEnabled(&dpa) { if err := r.Get( r.Context, types.NamespacedName{ @@ -99,13 +104,13 @@ func (r *DPAReconciler) ReconcileNonAdminController(log logr.Logger) (bool, erro r.Client, nonAdminDeployment, func() error { - err := r.buildNonAdminDeployment(nonAdminDeployment) + err := r.buildNonAdminDeployment(nonAdminDeployment, &dpa) if err != nil { return err } // Setting controller owner reference on the non admin controller deployment - return controllerutil.SetControllerReference(r.dpa, nonAdminDeployment, r.Scheme) + return controllerutil.SetControllerReference(&dpa, nonAdminDeployment, r.Scheme) }, ) if err != nil { @@ -123,14 +128,14 @@ func (r *DPAReconciler) ReconcileNonAdminController(log logr.Logger) (bool, erro return true, nil } -func (r *DPAReconciler) buildNonAdminDeployment(deploymentObject *appsv1.Deployment) error { - nonAdminImage := r.getNonAdminImage() - imagePullPolicy, err := common.GetImagePullPolicy(r.dpa.Spec.ImagePullPolicy, nonAdminImage) +func (r *DPAReconciler) buildNonAdminDeployment(deploymentObject *appsv1.Deployment, dpa *oadpv1alpha1.DataProtectionApplication) error { + nonAdminImage := r.getNonAdminImage(dpa) + imagePullPolicy, err := common.GetImagePullPolicy(dpa.Spec.ImagePullPolicy, nonAdminImage) if err != nil { r.Log.Error(err, "imagePullPolicy regex failed") } ensureRequiredLabels(deploymentObject) - err = ensureRequiredSpecs(deploymentObject, r.dpa, nonAdminImage, imagePullPolicy) + err = ensureRequiredSpecs(deploymentObject, dpa, nonAdminImage, imagePullPolicy) if err != nil { return err } @@ -244,15 +249,14 @@ func ensureRequiredSpecs(deploymentObject *appsv1.Deployment, dpa *oadpv1alpha1. return nil } -func (r *DPAReconciler) checkNonAdminEnabled() bool { - if r.dpa.Spec.NonAdmin != nil && r.dpa.Spec.NonAdmin.Enable != nil { - return *r.dpa.Spec.NonAdmin.Enable +func (r *DPAReconciler) checkNonAdminEnabled(dpa *oadpv1alpha1.DataProtectionApplication) bool { + if dpa.Spec.NonAdmin != nil && dpa.Spec.NonAdmin.Enable != nil { + return *dpa.Spec.NonAdmin.Enable } return false } -func (r *DPAReconciler) getNonAdminImage() string { - dpa := r.dpa +func (r *DPAReconciler) getNonAdminImage(dpa *oadpv1alpha1.DataProtectionApplication) string { unsupportedOverride := dpa.Spec.UnsupportedOverrides[oadpv1alpha1.NonAdminControllerImageKey] if unsupportedOverride != "" { return unsupportedOverride diff --git a/controllers/nonadmin_controller_test.go b/controllers/nonadmin_controller_test.go index 3b6c1082d05..1c83e4c28e6 100644 --- a/controllers/nonadmin_controller_test.go +++ b/controllers/nonadmin_controller_test.go @@ -244,7 +244,7 @@ var _ = ginkgo.Describe("Test ReconcileNonAdminController function", func() { }) func TestDPAReconcilerBuildNonAdminDeployment(t *testing.T) { - r := &DPAReconciler{dpa: &oadpv1alpha1.DataProtectionApplication{ + dpa := &oadpv1alpha1.DataProtectionApplication{ Spec: oadpv1alpha1.DataProtectionApplicationSpec{ NonAdmin: &oadpv1alpha1.NonAdmin{ Enable: ptr.To(true), @@ -253,10 +253,11 @@ func TestDPAReconcilerBuildNonAdminDeployment(t *testing.T) { Velero: &oadpv1alpha1.VeleroConfig{}, }, }, - }} + } + r := &DPAReconciler{} t.Setenv("RELATED_IMAGE_NON_ADMIN_CONTROLLER", defaultNonAdminImage) deployment := createTestDeployment("test-build-deployment") - err := r.buildNonAdminDeployment(deployment) + err := r.buildNonAdminDeployment(deployment, dpa) if err != nil { t.Errorf("buildNonAdminDeployment() errored out: %v", err) } @@ -496,8 +497,8 @@ func TestDPAReconcilerCheckNonAdminEnabled(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - r := &DPAReconciler{dpa: test.dpa} - result := r.checkNonAdminEnabled() + r := &DPAReconciler{} + result := r.checkNonAdminEnabled(test.dpa) if result != test.result { t.Errorf("Results differ: got '%v' but expected '%v'", result, test.result) } @@ -543,11 +544,11 @@ func TestDPAReconcilerGetNonAdminImage(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - r := &DPAReconciler{dpa: test.dpa} + r := &DPAReconciler{} if len(test.env) > 0 { t.Setenv("RELATED_IMAGE_NON_ADMIN_CONTROLLER", test.env) } - image := r.getNonAdminImage() + image := r.getNonAdminImage(test.dpa) if image != test.image { t.Errorf("Images differ: got '%v' but expected '%v'", image, test.image) } diff --git a/internal/common/constant/constant.go b/internal/common/constant/constant.go new file mode 100644 index 00000000000..d04a2977153 --- /dev/null +++ b/internal/common/constant/constant.go @@ -0,0 +1,110 @@ +/* +Copyright 2024. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package constant contains all common constants used in the project +package constant + +import ( + "k8s.io/apimachinery/pkg/util/validation" +) + +// Common labels for objects manipulated by the Non Admin Controller +// Labels should be used to identify the NAC object +// Annotations on the other hand should be used to define ownership +// of the specific Object, such as Backup/Restore. +const ( + OadpOperatorLabel = "openshift.io/oadp" + OadpLabel = OadpOperatorLabel + OadpLabelValue = TrueString + ManagedByLabel = "app.kubernetes.io/managed-by" + ManagedByLabelValue = "oadp-nac-controller" // TODO why not use same project name as in PROJECT file? + NabOriginNACUUIDLabel = OadpOperatorLabel + "-nab-origin-nacuuid" + NarOriginNACUUIDLabel = OadpOperatorLabel + "-nar-origin-nacuuid" + NabslOriginNACUUIDLabel = OadpOperatorLabel + "-nabsl-origin-nacuuid" + NadrOriginNACUUIDLabel = OadpOperatorLabel + "-nadr-origin-nacuuid" + NabSyncLabel = OadpOperatorLabel + "-nab-synced-from-nacuuid" + + NabOriginNameAnnotation = OadpOperatorLabel + "-nab-origin-name" + NabOriginNamespaceAnnotation = OadpOperatorLabel + "-nab-origin-namespace" + NarOriginNameAnnotation = OadpOperatorLabel + "-nar-origin-name" + NarOriginNamespaceAnnotation = OadpOperatorLabel + "-nar-origin-namespace" + NabslOriginNameAnnotation = OadpOperatorLabel + "-nabsl-origin-name" + NabslOriginNamespaceAnnotation = OadpOperatorLabel + "-nabsl-origin-namespace" + NadrOriginNameAnnotation = OadpOperatorLabel + "-nadr-origin-name" + NadrOriginNamespaceAnnotation = OadpOperatorLabel + "-nadr-origin-namespace" + + NabFinalizerName = "nonadminbackup.oadp.openshift.io/finalizer" + NarFinalizerName = "nonadminrestore.oadp.openshift.io/finalizer" + NabslFinalizerName = "nonadminbackupstoragelocation.oadp.openshift.io/finalizer" +) + +// Common environment variables for the Non Admin Controller +const ( + NamespaceEnvVar = "WATCH_NAMESPACE" + // Numeric Log Level corresponding to logrus levels (matching velero). + // 0 = panic + // 1 = Fatal + // 2 = Error + // 3 = Warn + // 4 = Info + // 5 = Debug + // 6 = Trace + LogLevelEnvVar = "LOG_LEVEL" + LogFormatEnvVar = "LOG_FORMAT" +) + +// EmptyString defines a constant for the empty string +const EmptyString = "" + +// NameDelimiter defines character that is used to separate name parts +const NameDelimiter = "-" + +// TrueString defines a constant for the True string +const TrueString = "True" + +// NamespaceString defines a constant for the Namespace string +const NamespaceString = "Namespace" + +// NameString defines a constant for the Name string +const NameString = "name" + +// CurrentPhaseString defines a constant for the Current Phase string +const CurrentPhaseString = "currentPhase" + +// UUIDString defines a constant for the UUID string +const UUIDString = "UUID" + +// JSONTagString defines a constant for the JSON tag string +const JSONTagString = "json" + +// CommaString defines a constant for the comma string +const CommaString = "," + +// MaximumNacObjectNameLength represents Generated Non Admin Object Name and +// must be below 63 characters, because it's used within object Label Value +const MaximumNacObjectNameLength = validation.DNS1123LabelMaxLength + +// NABRestrictedErr holds an error message template for a non-admin backup operation that is restricted. +const NABRestrictedErr = "NonAdminBackup %s is restricted" + +// NARRestrictedErr holds an error message template for a non-admin restore operation that is restricted. +const NARRestrictedErr = "NonAdminRestore %s is restricted" + +// Magic numbers +const ( + Base10 = 10 + Bits32 = 32 +) From 6af3a5faca018d13465a3a8d995db7bc1fb8e548 Mon Sep 17 00:00:00 2001 From: Wesley Hayutin Date: Mon, 15 Sep 2025 13:02:31 -0600 Subject: [PATCH 3/3] more refactor and compare against 1.5 --- api/v1alpha1/nonadmin_types.go | 65 -- api/v1alpha1/nonadminbackup_types.go | 210 ----- .../nonadminbackupstoragelocation_types.go | 99 -- ...adminbackupstoragelocationrequest_types.go | 111 --- api/v1alpha1/nonadmindownloadrequest_types.go | 113 --- api/v1alpha1/nonadminrestore_types.go | 179 ---- api/v1alpha1/zz_generated.deepcopy.go | 887 ++---------------- .../oadp.openshift.io_nonadminbackups.yaml | 12 + ...nonadminbackupstoragelocationrequests.yaml | 4 + ...ift.io_nonadminbackupstoragelocations.yaml | 4 + .../oadp.openshift.io_nonadminrestores.yaml | 6 + .../oadp.openshift.io_nonadminbackups.yaml | 12 + ...nonadminbackupstoragelocationrequests.yaml | 4 + ...ift.io_nonadminbackupstoragelocations.yaml | 4 + .../oadp.openshift.io_nonadminrestores.yaml | 6 + config/crd/kustomization.yaml | 19 +- controllers/dpa_controller.go | 3 + controllers/nonadmin_controller.go | 28 +- controllers/nonadmin_controller_test.go | 17 +- 19 files changed, 158 insertions(+), 1625 deletions(-) delete mode 100644 api/v1alpha1/nonadmin_types.go delete mode 100644 api/v1alpha1/nonadminbackup_types.go delete mode 100644 api/v1alpha1/nonadminbackupstoragelocation_types.go delete mode 100644 api/v1alpha1/nonadminbackupstoragelocationrequest_types.go delete mode 100644 api/v1alpha1/nonadmindownloadrequest_types.go delete mode 100644 api/v1alpha1/nonadminrestore_types.go diff --git a/api/v1alpha1/nonadmin_types.go b/api/v1alpha1/nonadmin_types.go deleted file mode 100644 index e8fcec90836..00000000000 --- a/api/v1alpha1/nonadmin_types.go +++ /dev/null @@ -1,65 +0,0 @@ -/* -Copyright 2024. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package v1alpha1 - -// NonAdminPhase is a simple one high-level summary of the lifecycle of a NonAdminBackup, NonAdminRestore, NonAdminBackupStorageLocation, or NonAdminDownloadRequest -// +kubebuilder:validation:Enum=New;BackingOff;Created;Deleting -type NonAdminPhase string - -const ( - // NonAdminPhaseNew - NonAdmin object was accepted by the OpenShift cluster, but it has not yet been processed by the NonAdminController - NonAdminPhaseNew NonAdminPhase = "New" - // NonAdminPhaseBackingOff - Velero object was not created due to NonAdmin object error (configuration or similar) - NonAdminPhaseBackingOff NonAdminPhase = "BackingOff" - // NonAdminPhaseCreated - Velero object was created. The Phase will not have additional information about it. - NonAdminPhaseCreated NonAdminPhase = "Created" - // NonAdminPhaseDeleting - Velero object is pending deletion. The Phase will not have additional information about it. - NonAdminPhaseDeleting NonAdminPhase = "Deleting" -) - -// NonAdminCondition are used for more detailed information supporing NonAdminBackupPhase state. -// +kubebuilder:validation:Enum=Accepted;Queued;Deleting -type NonAdminCondition string - -// Predefined conditions for NonAdminController objects. -// One NonAdminController object may have multiple conditions. -// It is more granular knowledge of the NonAdminController object and represents the -// array of the conditions through which the NonAdminController has or has not passed -const ( - NonAdminConditionAccepted NonAdminCondition = "Accepted" - NonAdminConditionQueued NonAdminCondition = "Queued" - NonAdminConditionDeleting NonAdminCondition = "Deleting" -) - -// QueueInfo holds the queue position for a specific operation. -type QueueInfo struct { - // estimatedQueuePosition is the number of operations ahead in the queue (0 if not queued) - EstimatedQueuePosition int `json:"estimatedQueuePosition"` -} - -// Constants representing resource names for non-admin objects -// These are used to identify custom resources managed for non-admin users. -const ( - // NonAdminBackups represents the resource name for non-admin backups. - NonAdminBackups = "nonadminbackups" - - // NonAdminRestores represents the resource name for non-admin restores. - NonAdminRestores = "nonadminrestores" - - // NonAdminBackupStorageLocations represents the resource name for non-admin backup storage locations. - NonAdminBackupStorageLocations = "nonadminbackupstoragelocations" -) diff --git a/api/v1alpha1/nonadminbackup_types.go b/api/v1alpha1/nonadminbackup_types.go deleted file mode 100644 index 6f7dcb1baf5..00000000000 --- a/api/v1alpha1/nonadminbackup_types.go +++ /dev/null @@ -1,210 +0,0 @@ -/* -Copyright 2024. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package v1alpha1 - -import ( - velerov1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/openshift/oadp-operator/internal/common/constant" -) - -// NonAdminBackupSpec defines the desired state of NonAdminBackup -type NonAdminBackupSpec struct { - // BackupSpec defines the specification for a Velero backup. - BackupSpec *velerov1.BackupSpec `json:"backupSpec"` - - // DeleteBackup removes the NonAdminBackup and its associated NonAdminRestores and VeleroBackup from the cluster, - // as well as the corresponding data in object storage - // +optional - DeleteBackup bool `json:"deleteBackup,omitempty"` -} - -// VeleroBackup contains information of the related Velero backup object. -type VeleroBackup struct { - // spec captures the current spec of the Velero backup. - // +optional - Spec *velerov1.BackupSpec `json:"spec,omitempty"` - - // status captures the current status of the Velero backup. - // +optional - Status *velerov1.BackupStatus `json:"status,omitempty"` - - // nacuuid references the Velero Backup object by it's label containing same NACUUID. - // +optional - NACUUID string `json:"nacuuid,omitempty"` - - // references the Velero Backup object by it's name. - // +optional - Name string `json:"name,omitempty"` - - // namespace references the Namespace in which Velero backup exists. - // +optional - Namespace string `json:"namespace,omitempty"` -} - -// VeleroDeleteBackupRequest contains information of the related Velero delete backup request object. -type VeleroDeleteBackupRequest struct { - // status captures the current status of the Velero delete backup request. - // +optional - Status *velerov1.DeleteBackupRequestStatus `json:"status,omitempty"` - - // nacuuid references the Velero delete backup request object by it's label containing same NACUUID. - // +optional - NACUUID string `json:"nacuuid,omitempty"` - - // name references the Velero delete backup request object by it's name. - // +optional - Name string `json:"name,omitempty"` - - // namespace references the Namespace in which Velero delete backup request exists. - // +optional - Namespace string `json:"namespace,omitempty"` -} - -// DataMoverDataUploads contains information of the related Velero DataUpload objects. -type DataMoverDataUploads struct { - // number of DataUploads related to this NonAdminBackup's Backup - // +optional - Total int `json:"total,omitempty"` - - // number of DataUploads related to this NonAdminBackup's Backup in phase New - // +optional - New int `json:"new,omitempty"` - - // number of DataUploads related to this NonAdminBackup's Backup in phase Accepted - // +optional - Accepted int `json:"accepted,omitempty"` - - // number of DataUploads related to this NonAdminBackup's Backup in phase Prepared - // +optional - Prepared int `json:"prepared,omitempty"` - - // number of DataUploads related to this NonAdminBackup's Backup in phase InProgress - // +optional - InProgress int `json:"inProgress,omitempty"` - - // number of DataUploads related to this NonAdminBackup's Backup in phase Canceling - // +optional - Canceling int `json:"canceling,omitempty"` - - // number of DataUploads related to this NonAdminBackup's Backup in phase Canceled - // +optional - Canceled int `json:"canceled,omitempty"` - - // number of DataUploads related to this NonAdminBackup's Backup in phase Failed - // +optional - Failed int `json:"failed,omitempty"` - - // number of DataUploads related to this NonAdminBackup's Backup in phase Completed - // +optional - Completed int `json:"completed,omitempty"` -} - -// FileSystemPodVolumeBackups contains information of the related Velero PodVolumeBackup objects. -type FileSystemPodVolumeBackups struct { - // number of PodVolumeBackups related to this NonAdminBackup's Backup - // +optional - Total int `json:"total,omitempty"` - - // number of PodVolumeBackups related to this NonAdminBackup's Backup in phase New - // +optional - New int `json:"new,omitempty"` - - // number of PodVolumeBackups related to this NonAdminBackup's Backup in phase InProgress - // +optional - InProgress int `json:"inProgress,omitempty"` - - // number of PodVolumeBackups related to this NonAdminBackup's Backup in phase Failed - // +optional - Failed int `json:"failed,omitempty"` - - // number of PodVolumeBackups related to this NonAdminBackup's Backup in phase Completed - // +optional - Completed int `json:"completed,omitempty"` -} - -// NonAdminBackupStatus defines the observed state of NonAdminBackup -type NonAdminBackupStatus struct { - // +optional - VeleroBackup *VeleroBackup `json:"veleroBackup,omitempty"` - - // +optional - VeleroDeleteBackupRequest *VeleroDeleteBackupRequest `json:"veleroDeleteBackupRequest,omitempty"` - - // +optional - DataMoverDataUploads *DataMoverDataUploads `json:"dataMoverDataUploads,omitempty"` - - // +optional - FileSystemPodVolumeBackups *FileSystemPodVolumeBackups `json:"fileSystemPodVolumeBackups,omitempty"` - - // queueInfo is used to estimate how many backups are scheduled before the given VeleroBackup in the OADP namespace. - // This number is not guaranteed to be accurate, but it should be close. It's inaccurate for cases when - // Velero pod is not running or being restarted after Backup object were created. - // It counts only VeleroBackups that are still subject to be handled by OADP/Velero. - // +optional - QueueInfo *QueueInfo `json:"queueInfo,omitempty"` - - // phase is a simple one high-level summary of the lifecycle of an NonAdminBackup. - Phase NonAdminPhase `json:"phase,omitempty"` - - Conditions []metav1.Condition `json:"conditions,omitempty"` -} - -// +kubebuilder:object:root=true -// +kubebuilder:subresource:status -// +kubebuilder:resource:path=nonadminbackups,shortName=nab -// +kubebuilder:printcolumn:name="Request-Phase",type="string",JSONPath=".status.phase" -// +kubebuilder:printcolumn:name="Velero-Phase",type="string",JSONPath=".status.veleroBackup.status.phase" -// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" - -// NonAdminBackup is the Schema for the nonadminbackups API -type NonAdminBackup struct { - Spec NonAdminBackupSpec `json:"spec,omitempty"` - Status NonAdminBackupStatus `json:"status,omitempty"` - - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` -} - -// +kubebuilder:object:root=true - -// NonAdminBackupList contains a list of NonAdminBackup -type NonAdminBackupList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []NonAdminBackup `json:"items"` -} - -func init() { - SchemeBuilder.Register(&NonAdminBackup{}, &NonAdminBackupList{}) -} - -// Helper Functions to avoid digging into NAB controller to understand how to get desired values - -// VeleroBackupName returns the name of the VeleroBackup object. -func (nab *NonAdminBackup) VeleroBackupName() string { - if nab.Status.VeleroBackup == nil { - return constant.EmptyString - } - return nab.Status.VeleroBackup.Name -} - -// UsesNaBSL returns true if backup is using NonAdminBackupStorageLocation -func (nab *NonAdminBackup) UsesNaBSL() bool { - return nab.Spec.BackupSpec != nil && nab.Spec.BackupSpec.StorageLocation != constant.EmptyString -} diff --git a/api/v1alpha1/nonadminbackupstoragelocation_types.go b/api/v1alpha1/nonadminbackupstoragelocation_types.go deleted file mode 100644 index 367e454f8a7..00000000000 --- a/api/v1alpha1/nonadminbackupstoragelocation_types.go +++ /dev/null @@ -1,99 +0,0 @@ -/* -Copyright 2024. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package v1alpha1 - -import ( - velerov1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// NonAdminBSLCondition contains additional conditions to the -// generic ones defined as NonAdminCondition -type NonAdminBSLCondition string - -// Predefined NonAdminBSLConditions -const ( - NonAdminBSLConditionSecretSynced NonAdminBSLCondition = "SecretSynced" - NonAdminBSLConditionBSLSynced NonAdminBSLCondition = "BackupStorageLocationSynced" - NonAdminBSLConditionApproved NonAdminBSLCondition = "ClusterAdminApproved" - NonAdminBSLConditionSpecUpdateApproved NonAdminBSLCondition = "SpecUpdateApproved" -) - -// NonAdminBackupStorageLocationSpec defines the desired state of NonAdminBackupStorageLocation -type NonAdminBackupStorageLocationSpec struct { - BackupStorageLocationSpec *velerov1.BackupStorageLocationSpec `json:"backupStorageLocationSpec"` -} - -// VeleroBackupStorageLocation contains information of the related Velero backup object. -type VeleroBackupStorageLocation struct { - // status captures the current status of the Velero backup storage location. - // +optional - Status *velerov1.BackupStorageLocationStatus `json:"status,omitempty"` - - // nacuuid references the Velero BackupStorageLocation object by it's label containing same NACUUID. - // +optional - NACUUID string `json:"nacuuid,omitempty"` - - // references the Velero BackupStorageLocation object by it's name. - // +optional - Name string `json:"name,omitempty"` - - // namespace references the Namespace in which Velero backup storage location exists. - // +optional - Namespace string `json:"namespace,omitempty"` -} - -// NonAdminBackupStorageLocationStatus defines the observed state of NonAdminBackupStorageLocation -type NonAdminBackupStorageLocationStatus struct { - // +optional - VeleroBackupStorageLocation *VeleroBackupStorageLocation `json:"veleroBackupStorageLocation,omitempty"` - - // phase is a simple one high-level summary of the lifecycle of an NonAdminBackupStorageLocation. - Phase NonAdminPhase `json:"phase,omitempty"` - - Conditions []metav1.Condition `json:"conditions,omitempty"` -} - -// +kubebuilder:object:root=true -// +kubebuilder:subresource:status -// +kubebuilder:resource:path=nonadminbackupstoragelocations,shortName=nabsl -// +kubebuilder:printcolumn:name="Request-Approved",type="string",JSONPath=".status.conditions[?(@.type=='ClusterAdminApproved')].status" -// +kubebuilder:printcolumn:name="Request-Phase",type="string",JSONPath=".status.phase" -// +kubebuilder:printcolumn:name="Velero-Phase",type="string",JSONPath=".status.veleroBackupStorageLocation.status.phase" -// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" - -// NonAdminBackupStorageLocation is the Schema for the nonadminbackupstoragelocations API -type NonAdminBackupStorageLocation struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec NonAdminBackupStorageLocationSpec `json:"spec,omitempty"` - Status NonAdminBackupStorageLocationStatus `json:"status,omitempty"` -} - -// +kubebuilder:object:root=true - -// NonAdminBackupStorageLocationList contains a list of NonAdminBackupStorageLocation -type NonAdminBackupStorageLocationList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []NonAdminBackupStorageLocation `json:"items"` -} - -func init() { - SchemeBuilder.Register(&NonAdminBackupStorageLocation{}, &NonAdminBackupStorageLocationList{}) -} diff --git a/api/v1alpha1/nonadminbackupstoragelocationrequest_types.go b/api/v1alpha1/nonadminbackupstoragelocationrequest_types.go deleted file mode 100644 index 5705e4c82d5..00000000000 --- a/api/v1alpha1/nonadminbackupstoragelocationrequest_types.go +++ /dev/null @@ -1,111 +0,0 @@ -/* -Copyright 2024. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package v1alpha1 - -import ( - velerov1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// NonAdminBSLRequest controls the approval of the NonAdminBackupStorageLocation -// +kubebuilder:validation:Enum=approve;reject;pending -type NonAdminBSLRequest string - -// NonAdminBSLRequestPhase is the phase of the NonAdminBackupStorageLocationRequest -// +kubebuilder:validation:Enum=Pending;Approved;Rejected -type NonAdminBSLRequestPhase string - -// Predefined NonAdminBSLRequestConditions -const ( - NonAdminBSLRequestApproved NonAdminBSLRequest = "approve" - NonAdminBSLRequestRejected NonAdminBSLRequest = "reject" - NonAdminBSLRequestPending NonAdminBSLRequest = "pending" -) - -// Predefined NonAdminBSLRequestPhases -const ( - NonAdminBSLRequestPhasePending NonAdminBSLRequestPhase = "Pending" - NonAdminBSLRequestPhaseApproved NonAdminBSLRequestPhase = "Approved" - NonAdminBSLRequestPhaseRejected NonAdminBSLRequestPhase = "Rejected" -) - -// NonAdminBackupStorageLocationRequestSpec defines the desired state of NonAdminBackupStorageLocationRequest -type NonAdminBackupStorageLocationRequestSpec struct { - // approvalDecision is the decision of the cluster admin on the Requested NonAdminBackupStorageLocation creation. - // The value may be set to either approve or reject. - // +optional - ApprovalDecision NonAdminBSLRequest `json:"approvalDecision,omitempty"` -} - -// SourceNonAdminBSL contains information of the NonAdminBackupStorageLocation object that triggered NonAdminBSLRequest -type SourceNonAdminBSL struct { - // requestedSpec contains the requested Velero BackupStorageLocation spec from the NonAdminBackupStorageLocation - // +optionl - RequestedSpec *velerov1.BackupStorageLocationSpec `json:"requestedSpec"` - - // nacuuid references the NonAdminBackupStorageLocation object by it's label containing same NACUUID. - // +optional - NACUUID string `json:"nacuuid,omitempty"` - - // name references the NonAdminBackupStorageLocation object by it's name. - // +optional - Name string `json:"name,omitempty"` - - // namespace references the Namespace in which NonAdminBackupStorageLocation exists. - // +optional - Namespace string `json:"namespace,omitempty"` -} - -// NonAdminBackupStorageLocationRequestStatus defines the observed state of NonAdminBackupStorageLocationRequest -type NonAdminBackupStorageLocationRequestStatus struct { - // nonAdminBackupStorageLocation contains information of the NonAdminBackupStorageLocation object that triggered NonAdminBSLRequest - // +optional - SourceNonAdminBSL *SourceNonAdminBSL `json:"nonAdminBackupStorageLocation,omitempty"` - - // phase represents the current state of the NonAdminBSLRequest. It can be either Pending, Approved or Rejected. - // +optional - Phase NonAdminBSLRequestPhase `json:"phase,omitempty"` -} - -// +kubebuilder:object:root=true -// +kubebuilder:subresource:status -// +kubebuilder:resource:path=nonadminbackupstoragelocationrequests,shortName=nabslrequest -// +kubebuilder:printcolumn:name="Request-Phase",type="string",JSONPath=".status.phase" -// +kubebuilder:printcolumn:name="Request-Namespace",type="string",JSONPath=".status.nonAdminBackupStorageLocation.namespace" -// +kubebuilder:printcolumn:name="Request-Name",type="string",JSONPath=".status.nonAdminBackupStorageLocation.name" -// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" - -// NonAdminBackupStorageLocationRequest is the Schema for the nonadminbackupstoragelocationrequests API -type NonAdminBackupStorageLocationRequest struct { - Status NonAdminBackupStorageLocationRequestStatus `json:"status,omitempty"` - Spec NonAdminBackupStorageLocationRequestSpec `json:"spec,omitempty"` - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` -} - -// +kubebuilder:object:root=true - -// NonAdminBackupStorageLocationRequestList contains a list of NonAdminBackupStorageLocationRequest -type NonAdminBackupStorageLocationRequestList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []NonAdminBackupStorageLocationRequest `json:"items"` -} - -func init() { - SchemeBuilder.Register(&NonAdminBackupStorageLocationRequest{}, &NonAdminBackupStorageLocationRequestList{}) -} diff --git a/api/v1alpha1/nonadmindownloadrequest_types.go b/api/v1alpha1/nonadmindownloadrequest_types.go deleted file mode 100644 index 4add538aaab..00000000000 --- a/api/v1alpha1/nonadmindownloadrequest_types.go +++ /dev/null @@ -1,113 +0,0 @@ -/* -Copyright 2024. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package v1alpha1 - -import ( - "fmt" - - velerov1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// NonAdminDownloadRequestSpec defines the desired state of NonAdminDownloadRequest. -// Mirrors velero DownloadRequestSpec to allow non admins to download information for a non admin backup/restore -type NonAdminDownloadRequestSpec struct { - // Target is what to download (e.g. logs for a backup). - Target velerov1.DownloadTarget `json:"target"` -} - -// VeleroDownloadRequest represents VeleroDownloadRequest -type VeleroDownloadRequest struct { - // VeleroDownloadRequestStatus represents VeleroDownloadRequestStatus - // +optional - Status *velerov1.DownloadRequestStatus `json:"status,omitempty"` -} - -// NonAdminDownloadRequestStatus defines the observed state of NonAdminDownloadRequest. -type NonAdminDownloadRequestStatus struct { - // +optional - VeleroDownloadRequest VeleroDownloadRequest `json:"velero,omitempty"` - // phase is a simple one high-level summary of the lifecycle of an NonAdminDownloadRequest - Phase NonAdminPhase `json:"phase,omitempty"` - - Conditions []metav1.Condition `json:"conditions,omitempty"` -} - -// +kubebuilder:object:root=true -// +kubebuilder:subresource:status -// +kubebuilder:resource:path=nonadmindownloadrequests,shortName=nadr -// +kubebuilder:printcolumn:name="Request-Phase",type="string",JSONPath=".status.phase" -// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" - -// NonAdminDownloadRequest is the Schema for the nonadmindownloadrequests API. -type NonAdminDownloadRequest struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec NonAdminDownloadRequestSpec `json:"spec,omitempty"` - Status NonAdminDownloadRequestStatus `json:"status,omitempty"` -} - -// +kubebuilder:object:root=true - -// NonAdminDownloadRequestList contains a list of NonAdminDownloadRequest. -type NonAdminDownloadRequestList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []NonAdminDownloadRequest `json:"items"` -} - -func init() { - SchemeBuilder.Register(&NonAdminDownloadRequest{}, &NonAdminDownloadRequestList{}) -} - -// NonAdminDownloadRequestConditionType prevents untyped strings for NADR conditions functions -type NonAdminDownloadRequestConditionType string - -const ( - // ConditionNonAdminBackupStorageLocationNotUsed block download requests processing if NaBSL is not used - ConditionNonAdminBackupStorageLocationNotUsed NonAdminDownloadRequestConditionType = "NonAdminBackupStorageLocationNotUsed" - // ConditionNonAdminBackupNotAvailable indicates backup is not available, and will backoff download request - ConditionNonAdminBackupNotAvailable NonAdminDownloadRequestConditionType = "NonAdminBackupNotAvailable" - // ConditionNonAdminRestoreNotAvailable indicates restore is not available, and will backoff download request - ConditionNonAdminRestoreNotAvailable NonAdminDownloadRequestConditionType = "NonAdminRestoreNotAvailable" - // ConditionNonAdminProcessed indicates that the NADR is in a terminal state - ConditionNonAdminProcessed NonAdminDownloadRequestConditionType = "Processed" -) - -// ReadyForProcessing returns if this NonAdminDownloadRequests is in a state ready for processing -// -// Terminal conditions include -// - NonAdminBackupStorageLocationNotUsed: we currently require NaBSL usage on the NAB/NAR to process this download request -// returns true if ready for processing, false otherwise -func (nadr *NonAdminDownloadRequest) ReadyForProcessing() bool { - // if nadr has ConditionNonAdminBackupStorageLocationUsed return false - if nadr.Status.Conditions != nil { - for _, condition := range nadr.Status.Conditions { - if condition.Type == string(ConditionNonAdminBackupStorageLocationNotUsed) && - condition.Status == metav1.ConditionTrue { - return false - } - } - } - return true // required fields are set via velero validation markers -} - -// VeleroDownloadRequestName defines velero download request name for this NonAdminDownloadRequest -func (nadr *NonAdminDownloadRequest) VeleroDownloadRequestName() string { - return fmt.Sprintf("nadr-%s", string(nadr.GetUID())) -} diff --git a/api/v1alpha1/nonadminrestore_types.go b/api/v1alpha1/nonadminrestore_types.go deleted file mode 100644 index 6ef6b0881ca..00000000000 --- a/api/v1alpha1/nonadminrestore_types.go +++ /dev/null @@ -1,179 +0,0 @@ -/* -Copyright 2024. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package v1alpha1 - -import ( - velerov1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/openshift/oadp-operator/internal/common/constant" -) - -// NonAdminRestoreSpec defines the desired state of NonAdminRestore -type NonAdminRestoreSpec struct { - // restoreSpec defines the specification for a Velero restore. - RestoreSpec *velerov1.RestoreSpec `json:"restoreSpec"` -} - -// VeleroRestore contains information of the related Velero restore object. -type VeleroRestore struct { - // status captures the current status of the Velero restore. - // +optional - Status *velerov1.RestoreStatus `json:"status,omitempty"` - - // references the Velero Restore object by it's name. - // +optional - Name string `json:"name,omitempty"` - - // nacuuid references the Velero Restore object by it's label containing same NACUUID. - // +optional - NACUUID string `json:"nacuuid,omitempty"` - - // namespace references the Namespace in which Velero Restore exists. - // +optional - Namespace string `json:"namespace,omitempty"` -} - -// DataMoverDataDownloads contains information of the related Velero DataDownload objects. -type DataMoverDataDownloads struct { - // number of DataDownloads related to this NonAdminRestore's Restore - // +optional - Total int `json:"total,omitempty"` - - // number of DataDownloads related to this NonAdminRestore's Restore in phase New - // +optional - New int `json:"new,omitempty"` - - // number of DataDownloads related to this NonAdminRestore's Restore in phase Accepted - // +optional - Accepted int `json:"accepted,omitempty"` - - // number of DataDownloads related to this NonAdminRestore's Restore in phase Prepared - // +optional - Prepared int `json:"prepared,omitempty"` - - // number of DataDownloads related to this NonAdminRestore's Restore in phase InProgress - // +optional - InProgress int `json:"inProgress,omitempty"` - - // number of DataDownloads related to this NonAdminRestore's Restore in phase Canceling - // +optional - Canceling int `json:"canceling,omitempty"` - - // number of DataDownloads related to this NonAdminRestore's Restore in phase Canceled - // +optional - Canceled int `json:"canceled,omitempty"` - - // number of DataDownloads related to this NonAdminRestore's Restore in phase Failed - // +optional - Failed int `json:"failed,omitempty"` - - // number of DataDownloads related to this NonAdminRestore's Restore in phase Completed - // +optional - Completed int `json:"completed,omitempty"` -} - -// FileSystemPodVolumeRestores contains information of the related Velero PodVolumeRestore objects. -type FileSystemPodVolumeRestores struct { - // number of PodVolumeRestores related to this NonAdminRestore's Restore - // +optional - Total int `json:"total,omitempty"` - - // number of PodVolumeRestores related to this NonAdminRestore's Restore in phase New - // +optional - New int `json:"new,omitempty"` - - // number of PodVolumeRestores related to this NonAdminRestore's Restore in phase InProgress - // +optional - InProgress int `json:"inProgress,omitempty"` - - // number of PodVolumeRestores related to this NonAdminRestore's Restore in phase Failed - // +optional - Failed int `json:"failed,omitempty"` - - // number of PodVolumeRestores related to this NonAdminRestore's Restore in phase Completed - // +optional - Completed int `json:"completed,omitempty"` -} - -// NonAdminRestoreStatus defines the observed state of NonAdminRestore -type NonAdminRestoreStatus struct { - // +optional - VeleroRestore *VeleroRestore `json:"veleroRestore,omitempty"` - - // +optional - DataMoverDataDownloads *DataMoverDataDownloads `json:"dataMoverDataDownloads,omitempty"` - - // +optional - FileSystemPodVolumeRestores *FileSystemPodVolumeRestores `json:"fileSystemPodVolumeRestores,omitempty"` - - // queueInfo is used to estimate how many restores are scheduled before the given VeleroRestore in the OADP namespace. - // This number is not guaranteed to be accurate, but it should be close. It's inaccurate for cases when - // Velero pod is not running or being restarted after Restore object were created. - // It counts only VeleroRestores that are still subject to be handled by OADP/Velero. - // +optional - QueueInfo *QueueInfo `json:"queueInfo,omitempty"` - - // phase is a simple one high-level summary of the lifecycle of an NonAdminRestore. - Phase NonAdminPhase `json:"phase,omitempty"` - - Conditions []metav1.Condition `json:"conditions,omitempty"` -} - -// +kubebuilder:object:root=true -// +kubebuilder:subresource:status -// +kubebuilder:resource:path=nonadminrestores,shortName=nar -// +kubebuilder:printcolumn:name="Request-Phase",type="string",JSONPath=".status.phase" -// +kubebuilder:printcolumn:name="Velero-Phase",type="string",JSONPath=".status.veleroRestore.status.phase" -// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" - -// NonAdminRestore is the Schema for the nonadminrestores API -type NonAdminRestore struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec NonAdminRestoreSpec `json:"spec,omitempty"` - Status NonAdminRestoreStatus `json:"status,omitempty"` -} - -// +kubebuilder:object:root=true - -// NonAdminRestoreList contains a list of NonAdminRestore -type NonAdminRestoreList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []NonAdminRestore `json:"items"` -} - -func init() { - SchemeBuilder.Register(&NonAdminRestore{}, &NonAdminRestoreList{}) -} - -// Helper Functions to avoid digging into NAR controller to understand how to get desired values - -// VeleroRestoreName returns the name of the VeleroRestore object. -func (nar *NonAdminRestore) VeleroRestoreName() string { - if nar.Status.VeleroRestore == nil { - return constant.EmptyString - } - return nar.Status.VeleroRestore.Name -} - -// NonAdminBackupName returns NonAdminBackup name of this NAR -func (nar *NonAdminRestore) NonAdminBackupName() string { - return nar.Spec.RestoreSpec.BackupName -} diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 540dc55e8d0..41119dbcbbc 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -22,8 +22,8 @@ package v1alpha1 import ( "github.com/openshift/oadp-operator/pkg/velero/server" - "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" - corev1 "k8s.io/api/core/v1" + velerov1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" + "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -63,7 +63,7 @@ func (in *BackupLocation) DeepCopyInto(out *BackupLocation) { *out = *in if in.Velero != nil { in, out := &in.Velero, &out.Velero - *out = new(v1.BackupStorageLocationSpec) + *out = new(velerov1.BackupStorageLocationSpec) (*in).DeepCopyInto(*out) } if in.CloudStorage != nil { @@ -155,7 +155,7 @@ func (in *CloudStorageLocation) DeepCopyInto(out *CloudStorageLocation) { } if in.Credential != nil { in, out := &in.Credential, &out.Credential - *out = new(corev1.SecretKeySelector) + *out = new(v1.SecretKeySelector) (*in).DeepCopyInto(*out) } if in.BackupSyncPeriod != nil { @@ -269,36 +269,6 @@ func (in *DataMover) DeepCopy() *DataMover { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *DataMoverDataDownloads) DeepCopyInto(out *DataMoverDataDownloads) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataMoverDataDownloads. -func (in *DataMoverDataDownloads) DeepCopy() *DataMoverDataDownloads { - if in == nil { - return nil - } - out := new(DataMoverDataDownloads) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *DataMoverDataUploads) DeepCopyInto(out *DataMoverDataUploads) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataMoverDataUploads. -func (in *DataMoverDataUploads) DeepCopy() *DataMoverDataUploads { - if in == nil { - return nil - } - out := new(DataMoverDataUploads) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DataMoverVolumeOptions) DeepCopyInto(out *DataMoverVolumeOptions) { *out = *in @@ -432,7 +402,7 @@ func (in *DataProtectionApplicationSpec) DeepCopyInto(out *DataProtectionApplica } if in.ImagePullPolicy != nil { in, out := &in.ImagePullPolicy, &out.ImagePullPolicy - *out = new(corev1.PullPolicy) + *out = new(v1.PullPolicy) **out = **in } if in.NonAdmin != nil { @@ -486,7 +456,7 @@ func (in *EnforceBackupStorageLocationSpec) DeepCopyInto(out *EnforceBackupStora } if in.Credential != nil { in, out := &in.Credential, &out.Credential - *out = new(corev1.SecretKeySelector) + *out = new(v1.SecretKeySelector) (*in).DeepCopyInto(*out) } in.StorageType.DeepCopyInto(&out.StorageType) @@ -532,36 +502,6 @@ func (in *Features) DeepCopy() *Features { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *FileSystemPodVolumeBackups) DeepCopyInto(out *FileSystemPodVolumeBackups) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FileSystemPodVolumeBackups. -func (in *FileSystemPodVolumeBackups) DeepCopy() *FileSystemPodVolumeBackups { - if in == nil { - return nil - } - out := new(FileSystemPodVolumeBackups) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *FileSystemPodVolumeRestores) DeepCopyInto(out *FileSystemPodVolumeRestores) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FileSystemPodVolumeRestores. -func (in *FileSystemPodVolumeRestores) DeepCopy() *FileSystemPodVolumeRestores { - if in == nil { - return nil - } - out := new(FileSystemPodVolumeRestores) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NodeAgentCommonFields) DeepCopyInto(out *NodeAgentCommonFields) { *out = *in @@ -618,12 +558,12 @@ func (in *NonAdmin) DeepCopyInto(out *NonAdmin) { } if in.EnforceBackupSpec != nil { in, out := &in.EnforceBackupSpec, &out.EnforceBackupSpec - *out = new(v1.BackupSpec) + *out = new(velerov1.BackupSpec) (*in).DeepCopyInto(*out) } if in.EnforceRestoreSpec != nil { in, out := &in.EnforceRestoreSpec, &out.EnforceRestoreSpec - *out = new(v1.RestoreSpec) + *out = new(velerov1.RestoreSpec) (*in).DeepCopyInto(*out) } if in.EnforceBSLSpec != nil { @@ -659,777 +599,152 @@ func (in *NonAdmin) DeepCopy() *NonAdmin { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *NonAdminBackup) DeepCopyInto(out *NonAdminBackup) { - *out = *in - in.Spec.DeepCopyInto(&out.Spec) - in.Status.DeepCopyInto(&out.Status) - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminBackup. -func (in *NonAdminBackup) DeepCopy() *NonAdminBackup { - if in == nil { - return nil - } - out := new(NonAdminBackup) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *NonAdminBackup) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *NonAdminBackupList) DeepCopyInto(out *NonAdminBackupList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]NonAdminBackup, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminBackupList. -func (in *NonAdminBackupList) DeepCopy() *NonAdminBackupList { - if in == nil { - return nil - } - out := new(NonAdminBackupList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *NonAdminBackupList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *NonAdminBackupSpec) DeepCopyInto(out *NonAdminBackupSpec) { +func (in *ObjectStorageLocation) DeepCopyInto(out *ObjectStorageLocation) { *out = *in - if in.BackupSpec != nil { - in, out := &in.BackupSpec, &out.BackupSpec - *out = new(v1.BackupSpec) - (*in).DeepCopyInto(*out) + if in.CACert != nil { + in, out := &in.CACert, &out.CACert + *out = make([]byte, len(*in)) + copy(*out, *in) } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminBackupSpec. -func (in *NonAdminBackupSpec) DeepCopy() *NonAdminBackupSpec { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectStorageLocation. +func (in *ObjectStorageLocation) DeepCopy() *ObjectStorageLocation { if in == nil { return nil } - out := new(NonAdminBackupSpec) + out := new(ObjectStorageLocation) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *NonAdminBackupStatus) DeepCopyInto(out *NonAdminBackupStatus) { +func (in *PodConfig) DeepCopyInto(out *PodConfig) { *out = *in - if in.VeleroBackup != nil { - in, out := &in.VeleroBackup, &out.VeleroBackup - *out = new(VeleroBackup) - (*in).DeepCopyInto(*out) - } - if in.VeleroDeleteBackupRequest != nil { - in, out := &in.VeleroDeleteBackupRequest, &out.VeleroDeleteBackupRequest - *out = new(VeleroDeleteBackupRequest) - (*in).DeepCopyInto(*out) - } - if in.DataMoverDataUploads != nil { - in, out := &in.DataMoverDataUploads, &out.DataMoverDataUploads - *out = new(DataMoverDataUploads) - **out = **in - } - if in.FileSystemPodVolumeBackups != nil { - in, out := &in.FileSystemPodVolumeBackups, &out.FileSystemPodVolumeBackups - *out = new(FileSystemPodVolumeBackups) - **out = **in + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } } - if in.QueueInfo != nil { - in, out := &in.QueueInfo, &out.QueueInfo - *out = new(QueueInfo) - **out = **in + if in.NodeSelector != nil { + in, out := &in.NodeSelector, &out.NodeSelector + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } } - if in.Conditions != nil { - in, out := &in.Conditions, &out.Conditions - *out = make([]metav1.Condition, len(*in)) + if in.Tolerations != nil { + in, out := &in.Tolerations, &out.Tolerations + *out = make([]v1.Toleration, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminBackupStatus. -func (in *NonAdminBackupStatus) DeepCopy() *NonAdminBackupStatus { - if in == nil { - return nil - } - out := new(NonAdminBackupStatus) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *NonAdminBackupStorageLocation) DeepCopyInto(out *NonAdminBackupStorageLocation) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) - in.Status.DeepCopyInto(&out.Status) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminBackupStorageLocation. -func (in *NonAdminBackupStorageLocation) DeepCopy() *NonAdminBackupStorageLocation { - if in == nil { - return nil - } - out := new(NonAdminBackupStorageLocation) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *NonAdminBackupStorageLocation) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *NonAdminBackupStorageLocationList) DeepCopyInto(out *NonAdminBackupStorageLocationList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]NonAdminBackupStorageLocation, len(*in)) + in.ResourceAllocations.DeepCopyInto(&out.ResourceAllocations) + if in.Env != nil { + in, out := &in.Env, &out.Env + *out = make([]v1.EnvVar, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminBackupStorageLocationList. -func (in *NonAdminBackupStorageLocationList) DeepCopy() *NonAdminBackupStorageLocationList { - if in == nil { - return nil - } - out := new(NonAdminBackupStorageLocationList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *NonAdminBackupStorageLocationList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *NonAdminBackupStorageLocationRequest) DeepCopyInto(out *NonAdminBackupStorageLocationRequest) { - *out = *in - in.Status.DeepCopyInto(&out.Status) - out.Spec = in.Spec - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminBackupStorageLocationRequest. -func (in *NonAdminBackupStorageLocationRequest) DeepCopy() *NonAdminBackupStorageLocationRequest { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodConfig. +func (in *PodConfig) DeepCopy() *PodConfig { if in == nil { return nil } - out := new(NonAdminBackupStorageLocationRequest) + out := new(PodConfig) in.DeepCopyInto(out) return out } -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *NonAdminBackupStorageLocationRequest) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *NonAdminBackupStorageLocationRequestList) DeepCopyInto(out *NonAdminBackupStorageLocationRequestList) { +func (in *ResticConfig) DeepCopyInto(out *ResticConfig) { *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]NonAdminBackupStorageLocationRequest, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } + in.NodeAgentCommonFields.DeepCopyInto(&out.NodeAgentCommonFields) } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminBackupStorageLocationRequestList. -func (in *NonAdminBackupStorageLocationRequestList) DeepCopy() *NonAdminBackupStorageLocationRequestList { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResticConfig. +func (in *ResticConfig) DeepCopy() *ResticConfig { if in == nil { return nil } - out := new(NonAdminBackupStorageLocationRequestList) + out := new(ResticConfig) in.DeepCopyInto(out) return out } -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *NonAdminBackupStorageLocationRequestList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *NonAdminBackupStorageLocationRequestSpec) DeepCopyInto(out *NonAdminBackupStorageLocationRequestSpec) { +func (in *RetainPolicy) DeepCopyInto(out *RetainPolicy) { *out = *in } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminBackupStorageLocationRequestSpec. -func (in *NonAdminBackupStorageLocationRequestSpec) DeepCopy() *NonAdminBackupStorageLocationRequestSpec { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RetainPolicy. +func (in *RetainPolicy) DeepCopy() *RetainPolicy { if in == nil { return nil } - out := new(NonAdminBackupStorageLocationRequestSpec) + out := new(RetainPolicy) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *NonAdminBackupStorageLocationRequestStatus) DeepCopyInto(out *NonAdminBackupStorageLocationRequestStatus) { +func (in *SnapshotLocation) DeepCopyInto(out *SnapshotLocation) { *out = *in - if in.SourceNonAdminBSL != nil { - in, out := &in.SourceNonAdminBSL, &out.SourceNonAdminBSL - *out = new(SourceNonAdminBSL) + if in.Velero != nil { + in, out := &in.Velero, &out.Velero + *out = new(velerov1.VolumeSnapshotLocationSpec) (*in).DeepCopyInto(*out) } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminBackupStorageLocationRequestStatus. -func (in *NonAdminBackupStorageLocationRequestStatus) DeepCopy() *NonAdminBackupStorageLocationRequestStatus { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SnapshotLocation. +func (in *SnapshotLocation) DeepCopy() *SnapshotLocation { if in == nil { return nil } - out := new(NonAdminBackupStorageLocationRequestStatus) + out := new(SnapshotLocation) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *NonAdminBackupStorageLocationSpec) DeepCopyInto(out *NonAdminBackupStorageLocationSpec) { +func (in *StorageType) DeepCopyInto(out *StorageType) { *out = *in - if in.BackupStorageLocationSpec != nil { - in, out := &in.BackupStorageLocationSpec, &out.BackupStorageLocationSpec - *out = new(v1.BackupStorageLocationSpec) + if in.ObjectStorage != nil { + in, out := &in.ObjectStorage, &out.ObjectStorage + *out = new(ObjectStorageLocation) (*in).DeepCopyInto(*out) } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminBackupStorageLocationSpec. -func (in *NonAdminBackupStorageLocationSpec) DeepCopy() *NonAdminBackupStorageLocationSpec { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageType. +func (in *StorageType) DeepCopy() *StorageType { if in == nil { return nil } - out := new(NonAdminBackupStorageLocationSpec) + out := new(StorageType) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *NonAdminBackupStorageLocationStatus) DeepCopyInto(out *NonAdminBackupStorageLocationStatus) { +func (in *VeleroConfig) DeepCopyInto(out *VeleroConfig) { *out = *in - if in.VeleroBackupStorageLocation != nil { - in, out := &in.VeleroBackupStorageLocation, &out.VeleroBackupStorageLocation - *out = new(VeleroBackupStorageLocation) - (*in).DeepCopyInto(*out) - } - if in.Conditions != nil { - in, out := &in.Conditions, &out.Conditions - *out = make([]metav1.Condition, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } + if in.FeatureFlags != nil { + in, out := &in.FeatureFlags, &out.FeatureFlags + *out = make([]string, len(*in)) + copy(*out, *in) } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminBackupStorageLocationStatus. -func (in *NonAdminBackupStorageLocationStatus) DeepCopy() *NonAdminBackupStorageLocationStatus { - if in == nil { - return nil - } - out := new(NonAdminBackupStorageLocationStatus) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *NonAdminDownloadRequest) DeepCopyInto(out *NonAdminDownloadRequest) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - out.Spec = in.Spec - in.Status.DeepCopyInto(&out.Status) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminDownloadRequest. -func (in *NonAdminDownloadRequest) DeepCopy() *NonAdminDownloadRequest { - if in == nil { - return nil - } - out := new(NonAdminDownloadRequest) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *NonAdminDownloadRequest) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *NonAdminDownloadRequestList) DeepCopyInto(out *NonAdminDownloadRequestList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]NonAdminDownloadRequest, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminDownloadRequestList. -func (in *NonAdminDownloadRequestList) DeepCopy() *NonAdminDownloadRequestList { - if in == nil { - return nil - } - out := new(NonAdminDownloadRequestList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *NonAdminDownloadRequestList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *NonAdminDownloadRequestSpec) DeepCopyInto(out *NonAdminDownloadRequestSpec) { - *out = *in - out.Target = in.Target -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminDownloadRequestSpec. -func (in *NonAdminDownloadRequestSpec) DeepCopy() *NonAdminDownloadRequestSpec { - if in == nil { - return nil - } - out := new(NonAdminDownloadRequestSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *NonAdminDownloadRequestStatus) DeepCopyInto(out *NonAdminDownloadRequestStatus) { - *out = *in - in.VeleroDownloadRequest.DeepCopyInto(&out.VeleroDownloadRequest) - if in.Conditions != nil { - in, out := &in.Conditions, &out.Conditions - *out = make([]metav1.Condition, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminDownloadRequestStatus. -func (in *NonAdminDownloadRequestStatus) DeepCopy() *NonAdminDownloadRequestStatus { - if in == nil { - return nil - } - out := new(NonAdminDownloadRequestStatus) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *NonAdminRestore) DeepCopyInto(out *NonAdminRestore) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) - in.Status.DeepCopyInto(&out.Status) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminRestore. -func (in *NonAdminRestore) DeepCopy() *NonAdminRestore { - if in == nil { - return nil - } - out := new(NonAdminRestore) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *NonAdminRestore) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *NonAdminRestoreList) DeepCopyInto(out *NonAdminRestoreList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]NonAdminRestore, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminRestoreList. -func (in *NonAdminRestoreList) DeepCopy() *NonAdminRestoreList { - if in == nil { - return nil - } - out := new(NonAdminRestoreList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *NonAdminRestoreList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *NonAdminRestoreSpec) DeepCopyInto(out *NonAdminRestoreSpec) { - *out = *in - if in.RestoreSpec != nil { - in, out := &in.RestoreSpec, &out.RestoreSpec - *out = new(v1.RestoreSpec) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminRestoreSpec. -func (in *NonAdminRestoreSpec) DeepCopy() *NonAdminRestoreSpec { - if in == nil { - return nil - } - out := new(NonAdminRestoreSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *NonAdminRestoreStatus) DeepCopyInto(out *NonAdminRestoreStatus) { - *out = *in - if in.VeleroRestore != nil { - in, out := &in.VeleroRestore, &out.VeleroRestore - *out = new(VeleroRestore) - (*in).DeepCopyInto(*out) - } - if in.DataMoverDataDownloads != nil { - in, out := &in.DataMoverDataDownloads, &out.DataMoverDataDownloads - *out = new(DataMoverDataDownloads) - **out = **in - } - if in.FileSystemPodVolumeRestores != nil { - in, out := &in.FileSystemPodVolumeRestores, &out.FileSystemPodVolumeRestores - *out = new(FileSystemPodVolumeRestores) - **out = **in - } - if in.QueueInfo != nil { - in, out := &in.QueueInfo, &out.QueueInfo - *out = new(QueueInfo) - **out = **in - } - if in.Conditions != nil { - in, out := &in.Conditions, &out.Conditions - *out = make([]metav1.Condition, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NonAdminRestoreStatus. -func (in *NonAdminRestoreStatus) DeepCopy() *NonAdminRestoreStatus { - if in == nil { - return nil - } - out := new(NonAdminRestoreStatus) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ObjectStorageLocation) DeepCopyInto(out *ObjectStorageLocation) { - *out = *in - if in.CACert != nil { - in, out := &in.CACert, &out.CACert - *out = make([]byte, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectStorageLocation. -func (in *ObjectStorageLocation) DeepCopy() *ObjectStorageLocation { - if in == nil { - return nil - } - out := new(ObjectStorageLocation) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PodConfig) DeepCopyInto(out *PodConfig) { - *out = *in - if in.Labels != nil { - in, out := &in.Labels, &out.Labels - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } - if in.NodeSelector != nil { - in, out := &in.NodeSelector, &out.NodeSelector - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } - if in.Tolerations != nil { - in, out := &in.Tolerations, &out.Tolerations - *out = make([]corev1.Toleration, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - in.ResourceAllocations.DeepCopyInto(&out.ResourceAllocations) - if in.Env != nil { - in, out := &in.Env, &out.Env - *out = make([]corev1.EnvVar, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodConfig. -func (in *PodConfig) DeepCopy() *PodConfig { - if in == nil { - return nil - } - out := new(PodConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *QueueInfo) DeepCopyInto(out *QueueInfo) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new QueueInfo. -func (in *QueueInfo) DeepCopy() *QueueInfo { - if in == nil { - return nil - } - out := new(QueueInfo) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ResticConfig) DeepCopyInto(out *ResticConfig) { - *out = *in - in.NodeAgentCommonFields.DeepCopyInto(&out.NodeAgentCommonFields) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResticConfig. -func (in *ResticConfig) DeepCopy() *ResticConfig { - if in == nil { - return nil - } - out := new(ResticConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *RetainPolicy) DeepCopyInto(out *RetainPolicy) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RetainPolicy. -func (in *RetainPolicy) DeepCopy() *RetainPolicy { - if in == nil { - return nil - } - out := new(RetainPolicy) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SnapshotLocation) DeepCopyInto(out *SnapshotLocation) { - *out = *in - if in.Velero != nil { - in, out := &in.Velero, &out.Velero - *out = new(v1.VolumeSnapshotLocationSpec) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SnapshotLocation. -func (in *SnapshotLocation) DeepCopy() *SnapshotLocation { - if in == nil { - return nil - } - out := new(SnapshotLocation) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SourceNonAdminBSL) DeepCopyInto(out *SourceNonAdminBSL) { - *out = *in - if in.RequestedSpec != nil { - in, out := &in.RequestedSpec, &out.RequestedSpec - *out = new(v1.BackupStorageLocationSpec) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SourceNonAdminBSL. -func (in *SourceNonAdminBSL) DeepCopy() *SourceNonAdminBSL { - if in == nil { - return nil - } - out := new(SourceNonAdminBSL) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *StorageType) DeepCopyInto(out *StorageType) { - *out = *in - if in.ObjectStorage != nil { - in, out := &in.ObjectStorage, &out.ObjectStorage - *out = new(ObjectStorageLocation) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageType. -func (in *StorageType) DeepCopy() *StorageType { - if in == nil { - return nil - } - out := new(StorageType) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *VeleroBackup) DeepCopyInto(out *VeleroBackup) { - *out = *in - if in.Spec != nil { - in, out := &in.Spec, &out.Spec - *out = new(v1.BackupSpec) - (*in).DeepCopyInto(*out) - } - if in.Status != nil { - in, out := &in.Status, &out.Status - *out = new(v1.BackupStatus) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VeleroBackup. -func (in *VeleroBackup) DeepCopy() *VeleroBackup { - if in == nil { - return nil - } - out := new(VeleroBackup) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *VeleroBackupStorageLocation) DeepCopyInto(out *VeleroBackupStorageLocation) { - *out = *in - if in.Status != nil { - in, out := &in.Status, &out.Status - *out = new(v1.BackupStorageLocationStatus) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VeleroBackupStorageLocation. -func (in *VeleroBackupStorageLocation) DeepCopy() *VeleroBackupStorageLocation { - if in == nil { - return nil - } - out := new(VeleroBackupStorageLocation) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *VeleroConfig) DeepCopyInto(out *VeleroConfig) { - *out = *in - if in.FeatureFlags != nil { - in, out := &in.FeatureFlags, &out.FeatureFlags - *out = make([]string, len(*in)) - copy(*out, *in) - } - if in.DefaultPlugins != nil { - in, out := &in.DefaultPlugins, &out.DefaultPlugins - *out = make([]DefaultPlugin, len(*in)) - copy(*out, *in) + if in.DefaultPlugins != nil { + in, out := &in.DefaultPlugins, &out.DefaultPlugins + *out = make([]DefaultPlugin, len(*in)) + copy(*out, *in) } if in.CustomPlugins != nil { in, out := &in.CustomPlugins, &out.CustomPlugins @@ -1483,66 +798,6 @@ func (in *VeleroConfig) DeepCopy() *VeleroConfig { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *VeleroDeleteBackupRequest) DeepCopyInto(out *VeleroDeleteBackupRequest) { - *out = *in - if in.Status != nil { - in, out := &in.Status, &out.Status - *out = new(v1.DeleteBackupRequestStatus) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VeleroDeleteBackupRequest. -func (in *VeleroDeleteBackupRequest) DeepCopy() *VeleroDeleteBackupRequest { - if in == nil { - return nil - } - out := new(VeleroDeleteBackupRequest) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *VeleroDownloadRequest) DeepCopyInto(out *VeleroDownloadRequest) { - *out = *in - if in.Status != nil { - in, out := &in.Status, &out.Status - *out = new(v1.DownloadRequestStatus) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VeleroDownloadRequest. -func (in *VeleroDownloadRequest) DeepCopy() *VeleroDownloadRequest { - if in == nil { - return nil - } - out := new(VeleroDownloadRequest) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *VeleroRestore) DeepCopyInto(out *VeleroRestore) { - *out = *in - if in.Status != nil { - in, out := &in.Status, &out.Status - *out = new(v1.RestoreStatus) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VeleroRestore. -func (in *VeleroRestore) DeepCopy() *VeleroRestore { - if in == nil { - return nil - } - out := new(VeleroRestore) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VolumeOptions) DeepCopyInto(out *VolumeOptions) { *out = *in diff --git a/bundle/manifests/oadp.openshift.io_nonadminbackups.yaml b/bundle/manifests/oadp.openshift.io_nonadminbackups.yaml index 907b8ce085c..75df43810be 100644 --- a/bundle/manifests/oadp.openshift.io_nonadminbackups.yaml +++ b/bundle/manifests/oadp.openshift.io_nonadminbackups.yaml @@ -188,11 +188,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -378,11 +380,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -439,11 +443,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -833,11 +839,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -1023,11 +1031,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -1084,11 +1094,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string diff --git a/bundle/manifests/oadp.openshift.io_nonadminbackupstoragelocationrequests.yaml b/bundle/manifests/oadp.openshift.io_nonadminbackupstoragelocationrequests.yaml index 93b1add6444..0f1f473a48e 100644 --- a/bundle/manifests/oadp.openshift.io_nonadminbackupstoragelocationrequests.yaml +++ b/bundle/manifests/oadp.openshift.io_nonadminbackupstoragelocationrequests.yaml @@ -118,8 +118,12 @@ spec: be a valid secret key. type: string name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: diff --git a/bundle/manifests/oadp.openshift.io_nonadminbackupstoragelocations.yaml b/bundle/manifests/oadp.openshift.io_nonadminbackupstoragelocations.yaml index 59a97a6071f..ae737171d4d 100644 --- a/bundle/manifests/oadp.openshift.io_nonadminbackupstoragelocations.yaml +++ b/bundle/manifests/oadp.openshift.io_nonadminbackupstoragelocations.yaml @@ -86,8 +86,12 @@ spec: a valid secret key. type: string name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: diff --git a/bundle/manifests/oadp.openshift.io_nonadminrestores.yaml b/bundle/manifests/oadp.openshift.io_nonadminrestores.yaml index 4f83f9efa49..42d4a9a0506 100644 --- a/bundle/manifests/oadp.openshift.io_nonadminrestores.yaml +++ b/bundle/manifests/oadp.openshift.io_nonadminrestores.yaml @@ -151,11 +151,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -305,11 +307,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -368,11 +372,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string diff --git a/config/crd/bases/oadp.openshift.io_nonadminbackups.yaml b/config/crd/bases/oadp.openshift.io_nonadminbackups.yaml index 21026681a77..4ef8629eda5 100644 --- a/config/crd/bases/oadp.openshift.io_nonadminbackups.yaml +++ b/config/crd/bases/oadp.openshift.io_nonadminbackups.yaml @@ -188,11 +188,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -378,11 +380,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -439,11 +443,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -833,11 +839,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -1023,11 +1031,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -1084,11 +1094,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string diff --git a/config/crd/bases/oadp.openshift.io_nonadminbackupstoragelocationrequests.yaml b/config/crd/bases/oadp.openshift.io_nonadminbackupstoragelocationrequests.yaml index 18d951cadec..52013c47678 100644 --- a/config/crd/bases/oadp.openshift.io_nonadminbackupstoragelocationrequests.yaml +++ b/config/crd/bases/oadp.openshift.io_nonadminbackupstoragelocationrequests.yaml @@ -118,8 +118,12 @@ spec: be a valid secret key. type: string name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: diff --git a/config/crd/bases/oadp.openshift.io_nonadminbackupstoragelocations.yaml b/config/crd/bases/oadp.openshift.io_nonadminbackupstoragelocations.yaml index cbae62fc080..e08f0a5dd03 100644 --- a/config/crd/bases/oadp.openshift.io_nonadminbackupstoragelocations.yaml +++ b/config/crd/bases/oadp.openshift.io_nonadminbackupstoragelocations.yaml @@ -86,8 +86,12 @@ spec: a valid secret key. type: string name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string optional: diff --git a/config/crd/bases/oadp.openshift.io_nonadminrestores.yaml b/config/crd/bases/oadp.openshift.io_nonadminrestores.yaml index 04609619879..2a29371e270 100644 --- a/config/crd/bases/oadp.openshift.io_nonadminrestores.yaml +++ b/config/crd/bases/oadp.openshift.io_nonadminrestores.yaml @@ -151,11 +151,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -305,11 +307,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -368,11 +372,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index b3de3211d43..498c2fb8aa2 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -2,6 +2,8 @@ # since it depends on service name and namespace that are out of this kustomize package. # It should be run by config/default resources: +- bases/oadp.openshift.io_nonadminbackupstoragelocationrequests.yaml +- bases/oadp.openshift.io_nonadminbackupstoragelocations.yaml - bases/oadp.openshift.io_dataprotectionapplications.yaml - bases/oadp.openshift.io_cloudstorages.yaml - bases/velero.io_backuprepositories.yaml @@ -20,21 +22,24 @@ resources: - bases/oadp.openshift.io_nonadminbackups.yaml - bases/oadp.openshift.io_nonadminrestores.yaml - bases/oadp.openshift.io_nonadmindownloadrequests.yaml -- bases/oadp.openshift.io_nonadminbackupstoragelocations.yaml -- bases/oadp.openshift.io_nonadminbackupstoragelocationrequests.yaml #+kubebuilder:scaffold:crdkustomizeresource -patchesStrategicMerge: +patches: # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix. # patches here are for enabling the conversion webhook for each CRD -#- patches/webhook_in_veleroes.yaml +#- path: patches/webhook_in_dataprotectionapplications.yaml +#- path: patches/webhook_in_cloudstorages.yaml #+kubebuilder:scaffold:crdkustomizewebhookpatch # [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix. # patches here are for enabling the CA injection for each CRD -#- patches/cainjection_in_veleroes.yaml +#- path: patches/cainjection_in_dataprotectionapplications.yaml +#- path: patches/cainjection_in_cloudstorages.yaml +#- path: patches/cainjection_in_dataprotectiontests.yaml #+kubebuilder:scaffold:crdkustomizecainjectionpatch +# [WEBHOOK] To enable webhook, uncomment the following section # the following config is for teaching kustomize how to do kustomization for CRDs. -configurations: -- kustomizeconfig.yaml + +#configurations: +#- kustomizeconfig.yaml \ No newline at end of file diff --git a/controllers/dpa_controller.go b/controllers/dpa_controller.go index f0a088d1f1c..765f70d7b4a 100644 --- a/controllers/dpa_controller.go +++ b/controllers/dpa_controller.go @@ -89,6 +89,9 @@ func (r *DPAReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R return result, nil } + // set the dpa field for use in reconciler methods + r.dpa = &dpa + // set client to pkg/client for use in non-reconcile functions oadpClient.SetClient(r.Client) diff --git a/controllers/nonadmin_controller.go b/controllers/nonadmin_controller.go index ba202bd26ee..be9b2181105 100644 --- a/controllers/nonadmin_controller.go +++ b/controllers/nonadmin_controller.go @@ -49,11 +49,6 @@ var ( ) func (r *DPAReconciler) ReconcileNonAdminController(log logr.Logger) (bool, error) { - dpa := oadpv1alpha1.DataProtectionApplication{} - if err := r.Get(r.Context, r.NamespacedName, &dpa); err != nil { - return false, err - } - nonAdminDeployment := &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: nonAdminObjectName, @@ -62,7 +57,7 @@ func (r *DPAReconciler) ReconcileNonAdminController(log logr.Logger) (bool, erro } // Delete (possible) previously deployment - if !r.checkNonAdminEnabled(&dpa) { + if !r.checkNonAdminEnabled() { if err := r.Get( r.Context, types.NamespacedName{ @@ -104,13 +99,13 @@ func (r *DPAReconciler) ReconcileNonAdminController(log logr.Logger) (bool, erro r.Client, nonAdminDeployment, func() error { - err := r.buildNonAdminDeployment(nonAdminDeployment, &dpa) + err := r.buildNonAdminDeployment(nonAdminDeployment) if err != nil { return err } // Setting controller owner reference on the non admin controller deployment - return controllerutil.SetControllerReference(&dpa, nonAdminDeployment, r.Scheme) + return controllerutil.SetControllerReference(r.dpa, nonAdminDeployment, r.Scheme) }, ) if err != nil { @@ -128,14 +123,14 @@ func (r *DPAReconciler) ReconcileNonAdminController(log logr.Logger) (bool, erro return true, nil } -func (r *DPAReconciler) buildNonAdminDeployment(deploymentObject *appsv1.Deployment, dpa *oadpv1alpha1.DataProtectionApplication) error { - nonAdminImage := r.getNonAdminImage(dpa) - imagePullPolicy, err := common.GetImagePullPolicy(dpa.Spec.ImagePullPolicy, nonAdminImage) +func (r *DPAReconciler) buildNonAdminDeployment(deploymentObject *appsv1.Deployment) error { + nonAdminImage := r.getNonAdminImage() + imagePullPolicy, err := common.GetImagePullPolicy(r.dpa.Spec.ImagePullPolicy, nonAdminImage) if err != nil { r.Log.Error(err, "imagePullPolicy regex failed") } ensureRequiredLabels(deploymentObject) - err = ensureRequiredSpecs(deploymentObject, dpa, nonAdminImage, imagePullPolicy) + err = ensureRequiredSpecs(deploymentObject, r.dpa, nonAdminImage, imagePullPolicy) if err != nil { return err } @@ -249,14 +244,15 @@ func ensureRequiredSpecs(deploymentObject *appsv1.Deployment, dpa *oadpv1alpha1. return nil } -func (r *DPAReconciler) checkNonAdminEnabled(dpa *oadpv1alpha1.DataProtectionApplication) bool { - if dpa.Spec.NonAdmin != nil && dpa.Spec.NonAdmin.Enable != nil { - return *dpa.Spec.NonAdmin.Enable +func (r *DPAReconciler) checkNonAdminEnabled() bool { + if r.dpa.Spec.NonAdmin != nil && r.dpa.Spec.NonAdmin.Enable != nil { + return *r.dpa.Spec.NonAdmin.Enable } return false } -func (r *DPAReconciler) getNonAdminImage(dpa *oadpv1alpha1.DataProtectionApplication) string { +func (r *DPAReconciler) getNonAdminImage() string { + dpa := r.dpa unsupportedOverride := dpa.Spec.UnsupportedOverrides[oadpv1alpha1.NonAdminControllerImageKey] if unsupportedOverride != "" { return unsupportedOverride diff --git a/controllers/nonadmin_controller_test.go b/controllers/nonadmin_controller_test.go index 1c83e4c28e6..f09a528ff22 100644 --- a/controllers/nonadmin_controller_test.go +++ b/controllers/nonadmin_controller_test.go @@ -10,7 +10,7 @@ import ( "github.com/onsi/ginkgo/v2" "github.com/onsi/gomega" "github.com/sirupsen/logrus" - v1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" + "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -244,7 +244,7 @@ var _ = ginkgo.Describe("Test ReconcileNonAdminController function", func() { }) func TestDPAReconcilerBuildNonAdminDeployment(t *testing.T) { - dpa := &oadpv1alpha1.DataProtectionApplication{ + r := &DPAReconciler{dpa: &oadpv1alpha1.DataProtectionApplication{ Spec: oadpv1alpha1.DataProtectionApplicationSpec{ NonAdmin: &oadpv1alpha1.NonAdmin{ Enable: ptr.To(true), @@ -253,11 +253,10 @@ func TestDPAReconcilerBuildNonAdminDeployment(t *testing.T) { Velero: &oadpv1alpha1.VeleroConfig{}, }, }, - } - r := &DPAReconciler{} + }} t.Setenv("RELATED_IMAGE_NON_ADMIN_CONTROLLER", defaultNonAdminImage) deployment := createTestDeployment("test-build-deployment") - err := r.buildNonAdminDeployment(deployment, dpa) + err := r.buildNonAdminDeployment(deployment) if err != nil { t.Errorf("buildNonAdminDeployment() errored out: %v", err) } @@ -497,8 +496,8 @@ func TestDPAReconcilerCheckNonAdminEnabled(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - r := &DPAReconciler{} - result := r.checkNonAdminEnabled(test.dpa) + r := &DPAReconciler{dpa: test.dpa} + result := r.checkNonAdminEnabled() if result != test.result { t.Errorf("Results differ: got '%v' but expected '%v'", result, test.result) } @@ -544,11 +543,11 @@ func TestDPAReconcilerGetNonAdminImage(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - r := &DPAReconciler{} + r := &DPAReconciler{dpa: test.dpa} if len(test.env) > 0 { t.Setenv("RELATED_IMAGE_NON_ADMIN_CONTROLLER", test.env) } - image := r.getNonAdminImage(test.dpa) + image := r.getNonAdminImage() if image != test.image { t.Errorf("Images differ: got '%v' but expected '%v'", image, test.image) }