Merge branch 'main' into issue-fix-5875

This commit is contained in:
Lyndon-Li
2023-05-18 16:03:17 +08:00
116 changed files with 3676 additions and 785 deletions

View File

@@ -14,7 +14,7 @@ jobs:
uses: codespell-project/actions-codespell@master
with:
# ignore the config/.../crd.go file as it's generated binary data that is edited elswhere.
skip: .git,*.png,*.jpg,*.woff,*.ttf,*.gif,*.ico,./config/crd/v1beta1/crds/crds.go,./config/crd/v1/crds/crds.go,./go.sum,./LICENSE
skip: .git,*.png,*.jpg,*.woff,*.ttf,*.gif,*.ico,./config/crd/v1beta1/crds/crds.go,./config/crd/v1/crds/crds.go,,./config/crd/v2alpha1/crds/crds.go,./go.sum,./LICENSE
ignore_words_list: iam,aks,ist,bridget,ue,shouldnot,atleast
check_filenames: true
check_hidden: true

View File

@@ -68,7 +68,7 @@ RUN mkdir -p /output/usr/bin && \
# Velero image packing section
FROM gcr.io/distroless/base-nossl-debian11:nonroot
LABEL maintainer="Nolan Brubaker <brubakern@vmware.com>"
LABEL maintainer="Xun Jiang <jxun@vmware.com>"
COPY --from=velero-builder /output /

View File

@@ -229,6 +229,10 @@ endif
update:
@$(MAKE) shell CMD="-c 'hack/update-all.sh'"
# update-crd is for development purpose only, it is faster than update, so is a shortcut when you want to generate CRD changes only
update-crd:
@$(MAKE) shell CMD="-c 'hack/update-3generated-crd-code.sh'"
build-dirs:
@mkdir -p _output/bin/$(GOOS)/$(GOARCH)
@mkdir -p .go/src/$(PKG) .go/pkg .go/bin .go/std/$(GOOS)/$(GOARCH) .go/go-build .go/golangci-lint

View File

@@ -12,6 +12,8 @@ k8s_yaml([
'config/crd/v1/bases/velero.io_schedules.yaml',
'config/crd/v1/bases/velero.io_serverstatusrequests.yaml',
'config/crd/v1/bases/velero.io_volumesnapshotlocations.yaml',
'config/crd/v2alpha1/bases/velero.io_datauploads.yaml',
'config/crd/v2alpha1/bases/velero.io_datadownloads.yaml',
])
# default values
@@ -60,7 +62,7 @@ RUN wget --output-document /restart.sh --quiet https://raw.githubusercontent.com
additional_docker_helper_commands = """
# Install delve to allow debugging
RUN go get github.com/go-delve/delve/cmd/dlv
RUN go install github.com/go-delve/delve/cmd/dlv@latest
RUN wget -qO- https://dl.k8s.io/v1.25.2/kubernetes-client-linux-amd64.tar.gz | tar xvz
RUN wget -qO- https://get.docker.com | sh

View File

@@ -0,0 +1,2 @@
Remove any dataSource or dataSourceRef fields from PVCs in PVC BIA for cases of
prior PVC restores with CSI

View File

@@ -0,0 +1 @@
Add data mover CRD under v2alpha1, include DataUpload CRD and DataDownload CRD

View File

@@ -0,0 +1 @@
log volumes to backup to help debug why `IsPodRunning` is called.

View File

@@ -0,0 +1 @@
Fix issue #5123, Kopia repository supports self-cert CA for S3 compatible storage.

View File

@@ -40,6 +40,11 @@ spec:
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.
@@ -454,6 +459,11 @@ spec:
- 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.

View File

@@ -70,6 +70,11 @@ spec:
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.
@@ -490,6 +495,11 @@ spec:
- 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

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,169 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.12.0
name: datadownloads.velero.io
spec:
group: velero.io
names:
kind: DataDownload
listKind: DataDownloadList
plural: datadownloads
singular: datadownload
scope: Namespaced
versions:
- additionalPrinterColumns:
- description: DataDownload status such as New/InProgress
jsonPath: .status.phase
name: Status
type: string
- description: Time duration since this DataDownload was started
jsonPath: .status.startTimestamp
name: Started
type: date
- description: Completed bytes
format: int64
jsonPath: .status.progress.bytesDone
name: Bytes Done
type: integer
- description: Total bytes
format: int64
jsonPath: .status.progress.totalBytes
name: Total Bytes
type: integer
- description: Name of the Backup Storage Location where the backup data is stored
jsonPath: .spec.backupStorageLocation
name: Storage Location
type: string
- description: Time duration since this DataDownload was created
jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v2alpha1
schema:
openAPIV3Schema:
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: DataDownloadSpec is the specification for a DataDownload.
properties:
backupStorageLocation:
description: BackupStorageLocation is the name of the backup storage
location where the backup repository is stored.
type: string
cancel:
description: Cancel indicates request to cancel the ongoing DataDownload.
It can be set when the DataDownload is in InProgress phase
type: boolean
dataMoverConfig:
additionalProperties:
type: string
description: DataMoverConfig is for data-mover-specific configuration
fields.
type: object
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
operationTimeout:
description: OperationTimeout specifies the time used to wait internal
operations, before returning error as timeout.
type: string
snapshotID:
description: SnapshotID is the ID of the Velero backup snapshot to
be restored from.
type: string
sourceNamespace:
description: SourceNamespace is the original namespace where the volume
is backed up from. It may be different from SourcePVC's namespace
if namespace is remapped during restore.
type: string
targetVolume:
description: TargetVolume is the information of the target PVC and
PV.
properties:
namespace:
description: Namespace is the target namespace
type: string
pv:
description: PV is the name of the target PV that is created by
Velero restore
type: string
pvc:
description: PVC is the name of the target PVC that is created
by Velero restore
type: string
required:
- namespace
- pv
- pvc
type: object
required:
- backupStorageLocation
- operationTimeout
- snapshotID
- sourceNamespace
- targetVolume
type: object
status:
description: DataDownloadStatus is the current status of a DataDownload.
properties:
completionTimestamp:
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
format: date-time
nullable: true
type: string
message:
description: Message is a message about the DataDownload's status.
type: string
phase:
description: Phase is the current state of the DataDownload.
enum:
- New
- Accepted
- Prepared
- InProgress
- Canceling
- Canceled
- Completed
- Failed
type: string
progress:
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.
properties:
bytesDone:
format: int64
type: integer
totalBytes:
format: int64
type: integer
type: object
startTimestamp:
description: StartTimestamp records the time a restore was started.
The server's time is used for StartTimestamps
format: date-time
nullable: true
type: string
type: object
type: object
served: true
storage: true
subresources: {}

View File

@@ -0,0 +1,193 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.12.0
name: datauploads.velero.io
spec:
group: velero.io
names:
kind: DataUpload
listKind: DataUploadList
plural: datauploads
singular: dataupload
scope: Namespaced
versions:
- additionalPrinterColumns:
- description: DataUpload status such as New/InProgress
jsonPath: .status.phase
name: Status
type: string
- description: Time duration since this DataUpload was started
jsonPath: .status.startTimestamp
name: Started
type: date
- description: Completed bytes
format: int64
jsonPath: .status.progress.bytesDone
name: Bytes Done
type: integer
- description: Total bytes
format: int64
jsonPath: .status.progress.totalBytes
name: Total Bytes
type: integer
- description: Name of the Backup Storage Location where this backup should be
stored
jsonPath: .spec.backupStorageLocation
name: Storage Location
type: string
- description: Time duration since this DataUpload was created
jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v2alpha1
schema:
openAPIV3Schema:
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: DataUploadSpec is the specification for a DataUpload.
properties:
backupStorageLocation:
description: BackupStorageLocation is the name of the backup storage
location where the backup repository is stored.
type: string
cancel:
description: Cancel indicates request to cancel the ongoing DataUpload.
It can be set when the DataUpload is in InProgress phase
type: boolean
csiSnapshot:
description: If SnapshotType is CSI, CSISnapshot provides the information
of the CSI snapshot.
nullable: true
properties:
snapshotClass:
description: StorageClass is the name of the snapshot class that
the volume snapshot is created with
type: string
storageClass:
description: StorageClass is the name of the storage class of
the PVC that the volume snapshot is created from
type: string
volumeSnapshot:
description: VolumeSnapshot is the name of the volume snapshot
to be backed up
type: string
required:
- storageClass
- volumeSnapshot
type: object
dataMoverConfig:
additionalProperties:
type: string
description: DataMoverConfig is for data-mover-specific configuration
fields.
nullable: true
type: object
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
operationTimeout:
description: OperationTimeout specifies the time used to wait internal
operations, before returning error as timeout.
type: string
snapshotType:
description: SnapshotType is the type of the snapshot to be backed
up.
type: string
sourceNamespace:
description: SourceNamespace is the original namespace where the volume
is backed up from. It is the same namespace for SourcePVC and CSI
namespaced objects.
type: string
sourcePVC:
description: SourcePVC is the name of the PVC which the snapshot is
taken for.
type: string
required:
- backupStorageLocation
- operationTimeout
- snapshotType
- sourceNamespace
- sourcePVC
type: object
status:
description: DataUploadStatus is the current status of a DataUpload.
properties:
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
dataMoverResult:
additionalProperties:
type: string
description: DataMoverResult stores data-mover-specific information
as a result of the DataUpload.
nullable: true
type: object
message:
description: Message is a message about the DataUpload's status.
type: string
path:
description: Path is the full path of the snapshot volume being backed
up.
type: string
phase:
description: Phase is the current state of the DataUpload.
enum:
- New
- Accepted
- Prepared
- InProgress
- Canceling
- Canceled
- Completed
- Failed
type: string
progress:
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.
properties:
bytesDone:
format: int64
type: integer
totalBytes:
format: int64
type: integer
type: object
snapshotID:
description: SnapshotID is the identifier for the snapshot in the
backup repository.
type: string
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
type: object
type: object
served: true
storage: true
subresources: {}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,4 @@
// Package crds embeds the controller-tools generated CRD manifests
package crds
//go:generate go run ../../../../hack/crd-gen/v1/main.go

View File

@@ -82,6 +82,46 @@ rules:
- get
- patch
- update
- apiGroups:
- velero.io
resources:
- datadownloads
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- velero.io
resources:
- datadownloads/status
verbs:
- get
- patch
- update
- apiGroups:
- velero.io
resources:
- datauploads
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- velero.io
resources:
- datauploads/status
verbs:
- get
- patch
- update
- apiGroups:
- velero.io
resources:

View File

@@ -57,7 +57,7 @@ spec:
- emptyDir: {}
name: scratch
---
apiVersion: rbac.authorization.k8s.io/v1beta1
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:

View File

@@ -14,8 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// This code embeds the CRD manifests in config/crd/v1/bases in
// config/crd/v1/crds/crds.go.
// This code embeds the CRD manifests in ../bases in ../crds/crds.go
package main

View File

@@ -35,13 +35,11 @@ fi
files="$(find . -type f -name '*.go' -not -path './.go/*' -not -path './vendor/*' -not -path './site/*' -not -path '*/generated/*' -not -name 'zz_generated*' -not -path '*/mocks/*')"
echo "${ACTION} gofmt"
for file in ${files}; do
output=$(gofmt "${MODE}" -s "${file}")
if [[ -n "${output}" ]]; then
VERIFY_FMT_FAILED=1
echo "${output}"
fi
done
output=$(printf '%s\n' "${files}" | xargs gofmt "${MODE}" -s)
if [[ -n "${output}" ]]; then
VERIFY_FMT_FAILED=1
echo "${output}"
fi
if [[ -n "${VERIFY_FMT_FAILED:-}" ]]; then
echo "${ACTION} gofmt - failed! Please run 'make update'."
else
@@ -49,13 +47,11 @@ else
fi
echo "${ACTION} goimports"
for file in ${files}; do
output=$(goimports "${MODE}" -local github.com/vmware-tanzu/velero "${file}")
if [[ -n "${output}" ]]; then
VERIFY_IMPORTS_FAILED=1
echo "${output}"
fi
done
output=$(printf '%s\n' "${files}" | xargs goimports "${MODE}" -local github.com/vmware-tanzu/velero)
if [[ -n "${output}" ]]; then
VERIFY_IMPORTS_FAILED=1
echo "${output}"
fi
if [[ -n "${VERIFY_IMPORTS_FAILED:-}" ]]; then
echo "${ACTION} goimports - failed! Please run 'make update'."
else

View File

@@ -40,20 +40,38 @@ ${GOPATH}/src/k8s.io/code-generator/generate-groups.sh \
all \
github.com/vmware-tanzu/velero/pkg/generated \
github.com/vmware-tanzu/velero/pkg/apis \
"velero:v1" \
"velero:v1,v2alpha1" \
--go-header-file ./hack/boilerplate.go.txt \
--output-base ../../.. \
$@
# Generate apiextensions.k8s.io/v1
# Generate manifests e.g. CRD, RBAC etc.
# Generate CRD for v1.
controller-gen \
crd:crdVersions=v1 \
paths=./pkg/apis/velero/v1/... \
rbac:roleName=velero-perms \
paths=./pkg/controller/... \
output:crd:artifacts:config=config/crd/v1/bases \
object \
paths=./pkg/apis/velero/v1/...
# Generate CRD for v2alpha1.
controller-gen \
crd:crdVersions=v1 \
paths=./pkg/apis/velero/v2alpha1/... \
paths=./pkg/controller/... \
output:crd:artifacts:config=config/crd/v2alpha1/bases \
object \
paths=./pkg/apis/velero/v2alpha1/...
# Generate RBAC.
controller-gen \
paths=./pkg/apis/velero/v1/... \
paths=./pkg/apis/velero/v2alpha1/... \
paths=./pkg/controller/... \
rbac:roleName=velero-perms
go generate ./config/crd/v1/crds
go generate ./config/crd/v2alpha1/crds

View File

@@ -19,7 +19,7 @@ HACK_DIR=$(dirname "${BASH_SOURCE}")
${HACK_DIR}/update-3generated-crd-code.sh
# ensure no changes to generated CRDs
if ! git diff --exit-code config/crd/v1/crds/crds.go >/dev/null; then
if [! git diff --exit-code config/crd/v1/crds/crds.go config/crd/v2alpha1/crds/crds.go >/dev/null]; then
# revert changes to state before running CRD generation to stay consistent
# with code-generator `--verify-only` option which discards generated changes
git checkout config/crd

View File

@@ -14,11 +14,13 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package v1
package shared
// PodVolumeOperationProgress represents the progress of a
// PodVolumeBackup/Restore operation
type PodVolumeOperationProgress struct {
// DataMoveOperationProgress represents the progress of a
// data movement operation
// +k8s:deepcopy-gen=true
type DataMoveOperationProgress struct {
// +optional
TotalBytes int64 `json:"totalBytes,omitempty"`

View File

@@ -165,6 +165,16 @@ type BackupSpec struct {
// ResourcePolicy specifies the referenced resource policies that backup should follow
// +optional
ResourcePolicy *v1.TypedLocalObjectReference `json:"resourcePolicy,omitempty"`
// SnapshotMoveData specifies whether snapshot data should be moved
// +optional
// +nullable
SnapshotMoveData *bool `json:"snapshotMoveData,omitempty"`
// DataMover specifies the data mover to be used by the backup.
// If DataMover is "" or "velero", the built-in data mover will be used.
// +optional
DataMover string `json:"datamover,omitempty"`
}
// BackupHooks contains custom behaviors that should be executed at different phases of the backup.

View File

@@ -19,6 +19,8 @@ package v1
import (
corev1api "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/vmware-tanzu/velero/pkg/apis/velero/shared"
)
// PodVolumeBackupSpec is the specification for a PodVolumeBackup.
@@ -100,7 +102,7 @@ type PodVolumeBackupStatus struct {
// number of backed up bytes. This can be used to display progress information
// about the backup operation.
// +optional
Progress PodVolumeOperationProgress `json:"progress,omitempty"`
Progress shared.DataMoveOperationProgress `json:"progress,omitempty"`
}
// TODO(2.0) After converting all resources to use the runttime-controller client,

View File

@@ -19,6 +19,8 @@ package v1
import (
corev1api "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/vmware-tanzu/velero/pkg/apis/velero/shared"
)
// PodVolumeRestoreSpec is the specification for a PodVolumeRestore.
@@ -86,7 +88,7 @@ type PodVolumeRestoreStatus struct {
// number of restored bytes. This can be used to display progress information
// about the restore operation.
// +optional
Progress PodVolumeOperationProgress `json:"progress,omitempty"`
Progress shared.DataMoveOperationProgress `json:"progress,omitempty"`
}
// TODO(2.0) After converting all resources to use the runtime-controller client, the genclient and k8s:deepcopy markers will no longer be needed and should be removed.

View File

@@ -376,6 +376,11 @@ func (in *BackupSpec) DeepCopyInto(out *BackupSpec) {
*out = new(corev1.TypedLocalObjectReference)
(*in).DeepCopyInto(*out)
}
if in.SnapshotMoveData != nil {
in, out := &in.SnapshotMoveData, &out.SnapshotMoveData
*out = new(bool)
**out = **in
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackupSpec.
@@ -977,21 +982,6 @@ func (in *PodVolumeBackupStatus) DeepCopy() *PodVolumeBackupStatus {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PodVolumeOperationProgress) DeepCopyInto(out *PodVolumeOperationProgress) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodVolumeOperationProgress.
func (in *PodVolumeOperationProgress) DeepCopy() *PodVolumeOperationProgress {
if in == nil {
return nil
}
out := new(PodVolumeOperationProgress)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PodVolumeRestore) DeepCopyInto(out *PodVolumeRestore) {
*out = *in

View File

@@ -0,0 +1,156 @@
/*
Copyright the Velero contributors.
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 v2alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/vmware-tanzu/velero/pkg/apis/velero/shared"
)
// DataDownloadSpec is the specification for a DataDownload.
type DataDownloadSpec struct {
// TargetVolume is the information of the target PVC and PV.
TargetVolume TargetVolumeSpec `json:"targetVolume"`
// BackupStorageLocation is the name of the backup storage location
// where the backup repository is stored.
BackupStorageLocation string `json:"backupStorageLocation"`
// DataMover specifies the data mover to be used by the backup.
// If DataMover is "" or "velero", the built-in data mover will be used.
// +optional
DataMover string `json:"datamover,omitempty"`
// SnapshotID is the ID of the Velero backup snapshot to be restored from.
SnapshotID string `json:"snapshotID"`
// SourceNamespace is the original namespace where the volume is backed up from.
// It may be different from SourcePVC's namespace if namespace is remapped during restore.
SourceNamespace string `json:"sourceNamespace"`
// DataMoverConfig is for data-mover-specific configuration fields.
// +optional
DataMoverConfig map[string]string `json:"dataMoverConfig,omitempty"`
// Cancel indicates request to cancel the ongoing DataDownload. It can be set
// when the DataDownload is in InProgress phase
Cancel bool `json:"cancel,omitempty"`
// OperationTimeout specifies the time used to wait internal operations,
// before returning error as timeout.
OperationTimeout metav1.Duration `json:"operationTimeout"`
}
// TargetPVCSpec is the specification for a target PVC.
type TargetVolumeSpec struct {
// PVC is the name of the target PVC that is created by Velero restore
PVC string `json:"pvc"`
// PV is the name of the target PV that is created by Velero restore
PV string `json:"pv"`
// Namespace is the target namespace
Namespace string `json:"namespace"`
}
// DataDownloadPhase represents the lifecycle phase of a DataDownload.
// +kubebuilder:validation:Enum=New;Accepted;Prepared;InProgress;Canceling;Canceled;Completed;Failed
type DataDownloadPhase string
const (
DataDownloadPhaseNew DataDownloadPhase = "New"
DataDownloadPhaseAccepted DataDownloadPhase = "Accepted"
DataDownloadPhasePrepared DataDownloadPhase = "Prepared"
DataDownloadPhaseInProgress DataDownloadPhase = "InProgress"
DataDownloadPhaseCanceling DataDownloadPhase = "Canceling"
DataDownloadPhaseCanceled DataDownloadPhase = "Canceled"
DataDownloadPhaseCompleted DataDownloadPhase = "Completed"
DataDownloadPhaseFailed DataDownloadPhase = "Failed"
)
// DataDownloadStatus is the current status of a DataDownload.
type DataDownloadStatus struct {
// Phase is the current state of the DataDownload.
// +optional
Phase DataDownloadPhase `json:"phase,omitempty"`
// Message is a message about the DataDownload's status.
// +optional
Message string `json:"message,omitempty"`
// StartTimestamp records the time a restore was started.
// The server's time is used for StartTimestamps
// +optional
// +nullable
StartTimestamp *metav1.Time `json:"startTimestamp,omitempty"`
// CompletionTimestamp records the time a restore was completed.
// Completion time is recorded even on failed restores.
// The server's time is used for CompletionTimestamps
// +optional
// +nullable
CompletionTimestamp *metav1.Time `json:"completionTimestamp,omitempty"`
// 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.
// +optional
Progress shared.DataMoveOperationProgress `json:"progress,omitempty"`
}
// TODO(2.0) After converting all resources to use the runtime-controller client, the genclient and k8s:deepcopy markers will no longer be needed and should be removed.
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +kubebuilder:object:generate=true
// +kubebuilder:object:root=true
// +kubebuilder:storageversion
// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.phase",description="DataDownload status such as New/InProgress"
// +kubebuilder:printcolumn:name="Started",type="date",JSONPath=".status.startTimestamp",description="Time duration since this DataDownload was started"
// +kubebuilder:printcolumn:name="Bytes Done",type="integer",format="int64",JSONPath=".status.progress.bytesDone",description="Completed bytes"
// +kubebuilder:printcolumn:name="Total Bytes",type="integer",format="int64",JSONPath=".status.progress.totalBytes",description="Total bytes"
// +kubebuilder:printcolumn:name="Storage Location",type="string",JSONPath=".spec.backupStorageLocation",description="Name of the Backup Storage Location where the backup data is stored"
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Time duration since this DataDownload was created"
type DataDownload struct {
metav1.TypeMeta `json:",inline"`
// +optional
metav1.ObjectMeta `json:"metadata,omitempty"`
// +optional
Spec DataDownloadSpec `json:"spec,omitempty"`
// +optional
Status DataDownloadStatus `json:"status,omitempty"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +kubebuilder:object:generate=true
// +kubebuilder:object:root=true
// +kubebuilder:rbac:groups=velero.io,resources=datadownloads,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=velero.io,resources=datadownloads/status,verbs=get;update;patch
// DataDownloadList is a list of DataDownloads.
type DataDownloadList struct {
metav1.TypeMeta `json:",inline"`
// +optional
metav1.ListMeta `json:"metadata,omitempty"`
Items []DataDownload `json:"items"`
}

View File

@@ -0,0 +1,209 @@
/*
Copyright the Velero contributors.
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 v2alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/vmware-tanzu/velero/pkg/apis/velero/shared"
)
// DataUploadSpec is the specification for a DataUpload.
type DataUploadSpec struct {
// SnapshotType is the type of the snapshot to be backed up.
SnapshotType SnapshotType `json:"snapshotType"`
// If SnapshotType is CSI, CSISnapshot provides the information of the CSI snapshot.
// +optional
// +nullable
CSISnapshot *CSISnapshotSpec `json:"csiSnapshot"`
// SourcePVC is the name of the PVC which the snapshot is taken for.
SourcePVC string `json:"sourcePVC"`
// DataMover specifies the data mover to be used by the backup.
// If DataMover is "" or "velero", the built-in data mover will be used.
// +optional
DataMover string `json:"datamover,omitempty"`
// BackupStorageLocation is the name of the backup storage location
// where the backup repository is stored.
BackupStorageLocation string `json:"backupStorageLocation"`
// SourceNamespace is the original namespace where the volume is backed up from.
// It is the same namespace for SourcePVC and CSI namespaced objects.
SourceNamespace string `json:"sourceNamespace"`
// DataMoverConfig is for data-mover-specific configuration fields.
// +optional
// +nullable
DataMoverConfig *map[string]string `json:"dataMoverConfig,omitempty"`
// Cancel indicates request to cancel the ongoing DataUpload. It can be set
// when the DataUpload is in InProgress phase
Cancel bool `json:"cancel,omitempty"`
// OperationTimeout specifies the time used to wait internal operations,
// before returning error as timeout.
OperationTimeout metav1.Duration `json:"operationTimeout"`
}
type SnapshotType string
const (
SnapshotTypeCSI SnapshotType = "CSI"
)
// CSISnapshotSpec is the specification for a CSI snapshot.
type CSISnapshotSpec struct {
// VolumeSnapshot is the name of the volume snapshot to be backed up
VolumeSnapshot string `json:"volumeSnapshot"`
// StorageClass is the name of the storage class of the PVC that the volume snapshot is created from
StorageClass string `json:"storageClass"`
// StorageClass is the name of the snapshot class that the volume snapshot is created with
// +optional
SnapshotClass string `json:"snapshotClass"`
}
// DataUploadPhase represents the lifecycle phase of a DataUpload.
// +kubebuilder:validation:Enum=New;Accepted;Prepared;InProgress;Canceling;Canceled;Completed;Failed
type DataUploadPhase string
const (
DataUploadPhaseNew DataUploadPhase = "New"
DataUploadPhaseAccepted DataUploadPhase = "Accepted"
DataUploadPhasePrepared DataUploadPhase = "Prepared"
DataUploadPhaseInProgress DataUploadPhase = "InProgress"
DataUploadPhaseCanceling DataUploadPhase = "Canceling"
DataUploadPhaseCanceled DataUploadPhase = "Canceled"
DataUploadPhaseCompleted DataUploadPhase = "Completed"
DataUploadPhaseFailed DataUploadPhase = "Failed"
)
// DataUploadStatus is the current status of a DataUpload.
type DataUploadStatus struct {
// Phase is the current state of the DataUpload.
// +optional
Phase DataUploadPhase `json:"phase,omitempty"`
// Path is the full path of the snapshot volume being backed up.
// +optional
Path string `json:"path,omitempty"`
// SnapshotID is the identifier for the snapshot in the backup repository.
// +optional
SnapshotID string `json:"snapshotID,omitempty"`
// DataMoverResult stores data-mover-specific information as a result of the DataUpload.
// +optional
// +nullable
DataMoverResult *map[string]string `json:"dataMoverResult,omitempty"`
// Message is a message about the DataUpload's status.
// +optional
Message string `json:"message,omitempty"`
// 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
// +optional
// +nullable
StartTimestamp *metav1.Time `json:"startTimestamp,omitempty"`
// 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
// +optional
// +nullable
CompletionTimestamp *metav1.Time `json:"completionTimestamp,omitempty"`
// 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.
// +optional
Progress shared.DataMoveOperationProgress `json:"progress,omitempty"`
}
// TODO(2.0) After converting all resources to use the runttime-controller client,
// the genclient and k8s:deepcopy markers will no longer be needed and should be removed.
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +kubebuilder:object:root=true
// +kubebuilder:object:generate=true
// +kubebuilder:storageversion
// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.phase",description="DataUpload status such as New/InProgress"
// +kubebuilder:printcolumn:name="Started",type="date",JSONPath=".status.startTimestamp",description="Time duration since this DataUpload was started"
// +kubebuilder:printcolumn:name="Bytes Done",type="integer",format="int64",JSONPath=".status.progress.bytesDone",description="Completed bytes"
// +kubebuilder:printcolumn:name="Total Bytes",type="integer",format="int64",JSONPath=".status.progress.totalBytes",description="Total bytes"
// +kubebuilder:printcolumn:name="Storage Location",type="string",JSONPath=".spec.backupStorageLocation",description="Name of the Backup Storage Location where this backup should be stored"
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Time duration since this DataUpload was created"
type DataUpload struct {
metav1.TypeMeta `json:",inline"`
// +optional
metav1.ObjectMeta `json:"metadata,omitempty"`
// +optional
Spec DataUploadSpec `json:"spec,omitempty"`
// +optional
Status DataUploadStatus `json:"status,omitempty"`
}
// TODO(2.0) After converting all resources to use the runtime-controller client,
// the k8s:deepcopy marker will no longer be needed and should be removed.
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +kubebuilder:object:root=true
// +kubebuilder:rbac:groups=velero.io,resources=datauploads,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=velero.io,resources=datauploads/status,verbs=get;update;patch
// DataUploadList is a list of DataUploads.
type DataUploadList struct {
metav1.TypeMeta `json:",inline"`
// +optional
metav1.ListMeta `json:"metadata,omitempty"`
Items []DataUpload `json:"items"`
}
// DataUploadResult represents the SnasphotBackup result to be used by DataDownload.
type DataUploadResult struct {
// BackupStorageLocation is the name of the backup storage location
// where the backup repository is stored.
BackupStorageLocation string `json:"backupStorageLocation"`
// DataMover specifies the data mover used by the DataUpload
// +optional
DataMover string `json:"datamover,omitempty"`
// SnapshotID is the identifier for the snapshot in the backup repository.
SnapshotID string `json:"snapshotID,omitempty"`
// SourceNamespace is the original namespace where the volume is backed up from.
SourceNamespace string `json:"sourceNamespace"`
// DataMoverResult stores data-mover-specific information as a result of the DataUpload.
// +optional
// +nullable
DataMoverResult *map[string]string `json:"dataMoverResult,omitempty"`
}

View File

@@ -0,0 +1,21 @@
/*
Copyright the Velero contributors.
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.
*/
// +k8s:deepcopy-gen=package
// Package v2alpha1 is the v2alpha1 version of the API.
// +groupName=velero.io
package v2alpha1

View File

@@ -0,0 +1,36 @@
/*
Copyright 2020 the Velero contributors.
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 v2alpha1 contains API Schema definitions for the velero v2alpha1 API group
// +kubebuilder:object:generate=true
// +groupName=velero.io
package v2alpha1
import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)
var (
// SchemeGroupVersion is group version used to register these objects
SchemeGroupVersion = schema.GroupVersion{Group: "velero.io", Version: "v2alpha1"}
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
// AddToScheme adds the types in this group-version to the given scheme.
AddToScheme = SchemeBuilder.AddToScheme
)

View File

@@ -0,0 +1,60 @@
/*
Copyright 2017 the Velero contributors.
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 v2alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)
// Resource gets a Velero GroupResource for a specified resource
func Resource(resource string) schema.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}
type typeInfo struct {
PluralName string
ItemType runtime.Object
ItemListType runtime.Object
}
func newTypeInfo(pluralName string, itemType, itemListType runtime.Object) typeInfo {
return typeInfo{
PluralName: pluralName,
ItemType: itemType,
ItemListType: itemListType,
}
}
// CustomResources returns a map of all custom resources within the Velero
// API group, keyed on Kind.
func CustomResources() map[string]typeInfo {
return map[string]typeInfo{
"DataUpload": newTypeInfo("datauploads", &DataUpload{}, &DataUploadList{}),
"DataDownload": newTypeInfo("datadownloads", &DataDownload{}, &DataDownloadList{}),
}
}
func addKnownTypes(scheme *runtime.Scheme) error {
for _, typeInfo := range CustomResources() {
scheme.AddKnownTypes(SchemeGroupVersion, typeInfo.ItemType, typeInfo.ItemListType)
}
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
}

View File

@@ -0,0 +1,299 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
// Code generated by controller-gen. DO NOT EDIT.
package v2alpha1
import (
"k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CSISnapshotSpec) DeepCopyInto(out *CSISnapshotSpec) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CSISnapshotSpec.
func (in *CSISnapshotSpec) DeepCopy() *CSISnapshotSpec {
if in == nil {
return nil
}
out := new(CSISnapshotSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DataDownload) DeepCopyInto(out *DataDownload) {
*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 DataDownload.
func (in *DataDownload) DeepCopy() *DataDownload {
if in == nil {
return nil
}
out := new(DataDownload)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *DataDownload) 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 *DataDownloadList) DeepCopyInto(out *DataDownloadList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]DataDownload, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataDownloadList.
func (in *DataDownloadList) DeepCopy() *DataDownloadList {
if in == nil {
return nil
}
out := new(DataDownloadList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *DataDownloadList) 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 *DataDownloadSpec) DeepCopyInto(out *DataDownloadSpec) {
*out = *in
out.TargetVolume = in.TargetVolume
if in.DataMoverConfig != nil {
in, out := &in.DataMoverConfig, &out.DataMoverConfig
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
out.OperationTimeout = in.OperationTimeout
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataDownloadSpec.
func (in *DataDownloadSpec) DeepCopy() *DataDownloadSpec {
if in == nil {
return nil
}
out := new(DataDownloadSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DataDownloadStatus) DeepCopyInto(out *DataDownloadStatus) {
*out = *in
if in.StartTimestamp != nil {
in, out := &in.StartTimestamp, &out.StartTimestamp
*out = (*in).DeepCopy()
}
if in.CompletionTimestamp != nil {
in, out := &in.CompletionTimestamp, &out.CompletionTimestamp
*out = (*in).DeepCopy()
}
out.Progress = in.Progress
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataDownloadStatus.
func (in *DataDownloadStatus) DeepCopy() *DataDownloadStatus {
if in == nil {
return nil
}
out := new(DataDownloadStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DataUpload) DeepCopyInto(out *DataUpload) {
*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 DataUpload.
func (in *DataUpload) DeepCopy() *DataUpload {
if in == nil {
return nil
}
out := new(DataUpload)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *DataUpload) 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 *DataUploadList) DeepCopyInto(out *DataUploadList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]DataUpload, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataUploadList.
func (in *DataUploadList) DeepCopy() *DataUploadList {
if in == nil {
return nil
}
out := new(DataUploadList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *DataUploadList) 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 *DataUploadResult) DeepCopyInto(out *DataUploadResult) {
*out = *in
if in.DataMoverResult != nil {
in, out := &in.DataMoverResult, &out.DataMoverResult
*out = new(map[string]string)
if **in != nil {
in, out := *in, *out
*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 DataUploadResult.
func (in *DataUploadResult) DeepCopy() *DataUploadResult {
if in == nil {
return nil
}
out := new(DataUploadResult)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DataUploadSpec) DeepCopyInto(out *DataUploadSpec) {
*out = *in
if in.CSISnapshot != nil {
in, out := &in.CSISnapshot, &out.CSISnapshot
*out = new(CSISnapshotSpec)
**out = **in
}
if in.DataMoverConfig != nil {
in, out := &in.DataMoverConfig, &out.DataMoverConfig
*out = new(map[string]string)
if **in != nil {
in, out := *in, *out
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
}
out.OperationTimeout = in.OperationTimeout
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataUploadSpec.
func (in *DataUploadSpec) DeepCopy() *DataUploadSpec {
if in == nil {
return nil
}
out := new(DataUploadSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DataUploadStatus) DeepCopyInto(out *DataUploadStatus) {
*out = *in
if in.DataMoverResult != nil {
in, out := &in.DataMoverResult, &out.DataMoverResult
*out = new(map[string]string)
if **in != nil {
in, out := *in, *out
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
}
if in.StartTimestamp != nil {
in, out := &in.StartTimestamp, &out.StartTimestamp
*out = (*in).DeepCopy()
}
if in.CompletionTimestamp != nil {
in, out := &in.CompletionTimestamp, &out.CompletionTimestamp
*out = (*in).DeepCopy()
}
out.Progress = in.Progress
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataUploadStatus.
func (in *DataUploadStatus) DeepCopy() *DataUploadStatus {
if in == nil {
return nil
}
out := new(DataUploadStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *TargetVolumeSpec) DeepCopyInto(out *TargetVolumeSpec) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TargetVolumeSpec.
func (in *TargetVolumeSpec) DeepCopy() *TargetVolumeSpec {
if in == nil {
return nil
}
out := new(TargetVolumeSpec)
in.DeepCopyInto(out)
return out
}

View File

@@ -20,6 +20,7 @@ import (
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
corev1api "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
v1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
@@ -61,5 +62,18 @@ func (a *PVCAction) Execute(item runtime.Unstructured, backup *v1.Backup) (runti
GroupResource: kuberesource.PersistentVolumes,
Name: pvc.Spec.VolumeName,
}
return item, []velero.ResourceIdentifier{pv}, nil
// remove dataSource if exists from prior restored CSI volumes
if pvc.Spec.DataSource != nil {
pvc.Spec.DataSource = nil
}
if pvc.Spec.DataSourceRef != nil {
pvc.Spec.DataSourceRef = nil
}
pvcMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&pvc)
if err != nil {
return nil, nil, errors.Wrap(err, "unable to convert pvc to unstructured item")
}
return &unstructured.Unstructured{Object: pvcMap}, []velero.ResourceIdentifier{pv}, nil
}

View File

@@ -32,6 +32,7 @@ import (
"k8s.io/client-go/rest"
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
velerov2alpha1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v2alpha1"
clientset "github.com/vmware-tanzu/velero/pkg/generated/clientset/versioned"
)
@@ -156,6 +157,9 @@ func (f *factory) KubebuilderClient() (kbclient.Client, error) {
if err := velerov1api.AddToScheme(scheme); err != nil {
return nil, err
}
if err := velerov2alpha1api.AddToScheme(scheme); err != nil {
return nil, err
}
if err := k8scheme.AddToScheme(scheme); err != nil {
return nil, err
}

View File

@@ -45,6 +45,7 @@ import (
"github.com/vmware-tanzu/velero/internal/credentials"
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
velerov2alpha1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v2alpha1"
"github.com/vmware-tanzu/velero/pkg/buildinfo"
"github.com/vmware-tanzu/velero/pkg/client"
"github.com/vmware-tanzu/velero/pkg/cmd"
@@ -125,6 +126,10 @@ func newNodeAgentServer(logger logrus.FieldLogger, factory client.Factory, metri
cancelFunc()
return nil, err
}
if err := velerov2alpha1api.AddToScheme(scheme); err != nil {
cancelFunc()
return nil, err
}
if err := v1.AddToScheme(scheme); err != nil {
cancelFunc()
return nil, err

View File

@@ -55,6 +55,7 @@ import (
"github.com/vmware-tanzu/velero/internal/credentials"
"github.com/vmware-tanzu/velero/internal/storage"
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
velerov2alpha1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v2alpha1"
"github.com/vmware-tanzu/velero/pkg/backup"
"github.com/vmware-tanzu/velero/pkg/buildinfo"
"github.com/vmware-tanzu/velero/pkg/client"
@@ -317,6 +318,10 @@ func newServer(f client.Factory, config serverConfig, logger *logrus.Logger) (*s
cancelFunc()
return nil, err
}
if err := velerov2alpha1api.AddToScheme(scheme); err != nil {
cancelFunc()
return nil, err
}
if err := corev1api.AddToScheme(scheme); err != nil {
cancelFunc()
return nil, err

View File

@@ -32,6 +32,7 @@ import (
"github.com/fatih/color"
kbclient "sigs.k8s.io/controller-runtime/pkg/client"
veleroapishared "github.com/vmware-tanzu/velero/pkg/apis/velero/shared"
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
"github.com/vmware-tanzu/velero/pkg/cmd/util/downloadrequest"
"github.com/vmware-tanzu/velero/pkg/features"
@@ -597,7 +598,7 @@ type volumesByPod struct {
// Add adds a pod volume with the specified pod namespace, name
// and volume to the appropriate group.
func (v *volumesByPod) Add(namespace, name, volume, phase string, progress velerov1api.PodVolumeOperationProgress) {
func (v *volumesByPod) Add(namespace, name, volume, phase string, progress veleroapishared.DataMoveOperationProgress) {
if v.volumesByPodMap == nil {
v.volumesByPodMap = make(map[string]*podVolumeGroup)
}

View File

@@ -32,6 +32,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/vmware-tanzu/velero/internal/credentials"
veleroapishared "github.com/vmware-tanzu/velero/pkg/apis/velero/shared"
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
"github.com/vmware-tanzu/velero/pkg/metrics"
"github.com/vmware-tanzu/velero/pkg/podvolume"
@@ -303,7 +304,7 @@ func (r *PodVolumeBackupReconciler) NewBackupProgressUpdater(ctx context.Context
// UpdateProgress which implement ProgressUpdater interface to update pvb progress status
func (b *BackupProgressUpdater) UpdateProgress(p *uploader.Progress) {
original := b.PodVolumeBackup.DeepCopy()
b.PodVolumeBackup.Status.Progress = velerov1api.PodVolumeOperationProgress{TotalBytes: p.TotalBytes, BytesDone: p.BytesDone}
b.PodVolumeBackup.Status.Progress = veleroapishared.DataMoveOperationProgress{TotalBytes: p.TotalBytes, BytesDone: p.BytesDone}
if b.Cli == nil {
b.Log.Errorf("failed to update backup pod %s volume %s progress with uninitailize client", b.PodVolumeBackup.Spec.Pod.Name, b.PodVolumeBackup.Spec.Volume)
return

View File

@@ -38,6 +38,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/source"
"github.com/vmware-tanzu/velero/internal/credentials"
veleroapishared "github.com/vmware-tanzu/velero/pkg/apis/velero/shared"
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
"github.com/vmware-tanzu/velero/pkg/podvolume"
"github.com/vmware-tanzu/velero/pkg/repository"
@@ -321,7 +322,7 @@ func (c *PodVolumeRestoreReconciler) NewRestoreProgressUpdater(ctx context.Conte
// UpdateProgress which implement ProgressUpdater interface to update pvr progress status
func (c *RestoreProgressUpdater) UpdateProgress(p *uploader.Progress) {
original := c.PodVolumeRestore.DeepCopy()
c.PodVolumeRestore.Status.Progress = velerov1api.PodVolumeOperationProgress{TotalBytes: p.TotalBytes, BytesDone: p.BytesDone}
c.PodVolumeRestore.Status.Progress = veleroapishared.DataMoveOperationProgress{TotalBytes: p.TotalBytes, BytesDone: p.BytesDone}
if c.Cli == nil {
c.Log.Errorf("failed to update restore pod %s volume %s progress with uninitailize client", c.PodVolumeRestore.Spec.Pod.Name, c.PodVolumeRestore.Spec.Volume)
return

View File

@@ -36,6 +36,7 @@ import (
. "github.com/onsi/gomega"
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
velerov2alpha1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v2alpha1"
"k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/rest"
@@ -98,6 +99,9 @@ func newTestEnvironment() *testEnvironment {
err := velerov1api.AddToScheme(scheme.Scheme)
Expect(err).NotTo(HaveOccurred())
err = velerov2alpha1api.AddToScheme(scheme.Scheme)
Expect(err).NotTo(HaveOccurred())
env = &envtest.Environment{
CRDDirectoryPaths: []string{filepath.Join("..", "config", "crd", "bases")},
}

View File

@@ -22,6 +22,7 @@ import (
"fmt"
velerov1 "github.com/vmware-tanzu/velero/pkg/generated/clientset/versioned/typed/velero/v1"
velerov2alpha1 "github.com/vmware-tanzu/velero/pkg/generated/clientset/versioned/typed/velero/v2alpha1"
discovery "k8s.io/client-go/discovery"
rest "k8s.io/client-go/rest"
flowcontrol "k8s.io/client-go/util/flowcontrol"
@@ -30,13 +31,15 @@ import (
type Interface interface {
Discovery() discovery.DiscoveryInterface
VeleroV1() velerov1.VeleroV1Interface
VeleroV2alpha1() velerov2alpha1.VeleroV2alpha1Interface
}
// Clientset contains the clients for groups. Each group has exactly one
// version included in a Clientset.
type Clientset struct {
*discovery.DiscoveryClient
veleroV1 *velerov1.VeleroV1Client
veleroV1 *velerov1.VeleroV1Client
veleroV2alpha1 *velerov2alpha1.VeleroV2alpha1Client
}
// VeleroV1 retrieves the VeleroV1Client
@@ -44,6 +47,11 @@ func (c *Clientset) VeleroV1() velerov1.VeleroV1Interface {
return c.veleroV1
}
// VeleroV2alpha1 retrieves the VeleroV2alpha1Client
func (c *Clientset) VeleroV2alpha1() velerov2alpha1.VeleroV2alpha1Interface {
return c.veleroV2alpha1
}
// Discovery retrieves the DiscoveryClient
func (c *Clientset) Discovery() discovery.DiscoveryInterface {
if c == nil {
@@ -69,6 +77,10 @@ func NewForConfig(c *rest.Config) (*Clientset, error) {
if err != nil {
return nil, err
}
cs.veleroV2alpha1, err = velerov2alpha1.NewForConfig(&configShallowCopy)
if err != nil {
return nil, err
}
cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy)
if err != nil {
@@ -82,6 +94,7 @@ func NewForConfig(c *rest.Config) (*Clientset, error) {
func NewForConfigOrDie(c *rest.Config) *Clientset {
var cs Clientset
cs.veleroV1 = velerov1.NewForConfigOrDie(c)
cs.veleroV2alpha1 = velerov2alpha1.NewForConfigOrDie(c)
cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c)
return &cs
@@ -91,6 +104,7 @@ func NewForConfigOrDie(c *rest.Config) *Clientset {
func New(c rest.Interface) *Clientset {
var cs Clientset
cs.veleroV1 = velerov1.New(c)
cs.veleroV2alpha1 = velerov2alpha1.New(c)
cs.DiscoveryClient = discovery.NewDiscoveryClient(c)
return &cs

View File

@@ -22,6 +22,8 @@ import (
clientset "github.com/vmware-tanzu/velero/pkg/generated/clientset/versioned"
velerov1 "github.com/vmware-tanzu/velero/pkg/generated/clientset/versioned/typed/velero/v1"
fakevelerov1 "github.com/vmware-tanzu/velero/pkg/generated/clientset/versioned/typed/velero/v1/fake"
velerov2alpha1 "github.com/vmware-tanzu/velero/pkg/generated/clientset/versioned/typed/velero/v2alpha1"
fakevelerov2alpha1 "github.com/vmware-tanzu/velero/pkg/generated/clientset/versioned/typed/velero/v2alpha1/fake"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/discovery"
@@ -83,3 +85,8 @@ var (
func (c *Clientset) VeleroV1() velerov1.VeleroV1Interface {
return &fakevelerov1.FakeVeleroV1{Fake: &c.Fake}
}
// VeleroV2alpha1 retrieves the VeleroV2alpha1Client
func (c *Clientset) VeleroV2alpha1() velerov2alpha1.VeleroV2alpha1Interface {
return &fakevelerov2alpha1.FakeVeleroV2alpha1{Fake: &c.Fake}
}

View File

@@ -20,6 +20,7 @@ package fake
import (
velerov1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
velerov2alpha1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v2alpha1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema"
@@ -32,6 +33,7 @@ var codecs = serializer.NewCodecFactory(scheme)
var localSchemeBuilder = runtime.SchemeBuilder{
velerov1.AddToScheme,
velerov2alpha1.AddToScheme,
}
// AddToScheme adds all types of this clientset into the given scheme. This allows composition

View File

@@ -20,6 +20,7 @@ package scheme
import (
velerov1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
velerov2alpha1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v2alpha1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema"
@@ -32,6 +33,7 @@ var Codecs = serializer.NewCodecFactory(Scheme)
var ParameterCodec = runtime.NewParameterCodec(Scheme)
var localSchemeBuilder = runtime.SchemeBuilder{
velerov1.AddToScheme,
velerov2alpha1.AddToScheme,
}
// AddToScheme adds all types of this clientset into the given scheme. This allows composition

View File

@@ -0,0 +1,195 @@
/*
Copyright the Velero contributors.
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.
*/
// Code generated by client-gen. DO NOT EDIT.
package v2alpha1
import (
"context"
"time"
v2alpha1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v2alpha1"
scheme "github.com/vmware-tanzu/velero/pkg/generated/clientset/versioned/scheme"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
rest "k8s.io/client-go/rest"
)
// DataDownloadsGetter has a method to return a DataDownloadInterface.
// A group's client should implement this interface.
type DataDownloadsGetter interface {
DataDownloads(namespace string) DataDownloadInterface
}
// DataDownloadInterface has methods to work with DataDownload resources.
type DataDownloadInterface interface {
Create(ctx context.Context, dataDownload *v2alpha1.DataDownload, opts v1.CreateOptions) (*v2alpha1.DataDownload, error)
Update(ctx context.Context, dataDownload *v2alpha1.DataDownload, opts v1.UpdateOptions) (*v2alpha1.DataDownload, error)
UpdateStatus(ctx context.Context, dataDownload *v2alpha1.DataDownload, opts v1.UpdateOptions) (*v2alpha1.DataDownload, error)
Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
Get(ctx context.Context, name string, opts v1.GetOptions) (*v2alpha1.DataDownload, error)
List(ctx context.Context, opts v1.ListOptions) (*v2alpha1.DataDownloadList, error)
Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v2alpha1.DataDownload, err error)
DataDownloadExpansion
}
// dataDownloads implements DataDownloadInterface
type dataDownloads struct {
client rest.Interface
ns string
}
// newDataDownloads returns a DataDownloads
func newDataDownloads(c *VeleroV2alpha1Client, namespace string) *dataDownloads {
return &dataDownloads{
client: c.RESTClient(),
ns: namespace,
}
}
// Get takes name of the dataDownload, and returns the corresponding dataDownload object, and an error if there is any.
func (c *dataDownloads) Get(ctx context.Context, name string, options v1.GetOptions) (result *v2alpha1.DataDownload, err error) {
result = &v2alpha1.DataDownload{}
err = c.client.Get().
Namespace(c.ns).
Resource("datadownloads").
Name(name).
VersionedParams(&options, scheme.ParameterCodec).
Do(ctx).
Into(result)
return
}
// List takes label and field selectors, and returns the list of DataDownloads that match those selectors.
func (c *dataDownloads) List(ctx context.Context, opts v1.ListOptions) (result *v2alpha1.DataDownloadList, err error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
result = &v2alpha1.DataDownloadList{}
err = c.client.Get().
Namespace(c.ns).
Resource("datadownloads").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Do(ctx).
Into(result)
return
}
// Watch returns a watch.Interface that watches the requested dataDownloads.
func (c *dataDownloads) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
opts.Watch = true
return c.client.Get().
Namespace(c.ns).
Resource("datadownloads").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Watch(ctx)
}
// Create takes the representation of a dataDownload and creates it. Returns the server's representation of the dataDownload, and an error, if there is any.
func (c *dataDownloads) Create(ctx context.Context, dataDownload *v2alpha1.DataDownload, opts v1.CreateOptions) (result *v2alpha1.DataDownload, err error) {
result = &v2alpha1.DataDownload{}
err = c.client.Post().
Namespace(c.ns).
Resource("datadownloads").
VersionedParams(&opts, scheme.ParameterCodec).
Body(dataDownload).
Do(ctx).
Into(result)
return
}
// Update takes the representation of a dataDownload and updates it. Returns the server's representation of the dataDownload, and an error, if there is any.
func (c *dataDownloads) Update(ctx context.Context, dataDownload *v2alpha1.DataDownload, opts v1.UpdateOptions) (result *v2alpha1.DataDownload, err error) {
result = &v2alpha1.DataDownload{}
err = c.client.Put().
Namespace(c.ns).
Resource("datadownloads").
Name(dataDownload.Name).
VersionedParams(&opts, scheme.ParameterCodec).
Body(dataDownload).
Do(ctx).
Into(result)
return
}
// UpdateStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
func (c *dataDownloads) UpdateStatus(ctx context.Context, dataDownload *v2alpha1.DataDownload, opts v1.UpdateOptions) (result *v2alpha1.DataDownload, err error) {
result = &v2alpha1.DataDownload{}
err = c.client.Put().
Namespace(c.ns).
Resource("datadownloads").
Name(dataDownload.Name).
SubResource("status").
VersionedParams(&opts, scheme.ParameterCodec).
Body(dataDownload).
Do(ctx).
Into(result)
return
}
// Delete takes name of the dataDownload and deletes it. Returns an error if one occurs.
func (c *dataDownloads) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
return c.client.Delete().
Namespace(c.ns).
Resource("datadownloads").
Name(name).
Body(&opts).
Do(ctx).
Error()
}
// DeleteCollection deletes a collection of objects.
func (c *dataDownloads) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
var timeout time.Duration
if listOpts.TimeoutSeconds != nil {
timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
}
return c.client.Delete().
Namespace(c.ns).
Resource("datadownloads").
VersionedParams(&listOpts, scheme.ParameterCodec).
Timeout(timeout).
Body(&opts).
Do(ctx).
Error()
}
// Patch applies the patch and returns the patched dataDownload.
func (c *dataDownloads) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v2alpha1.DataDownload, err error) {
result = &v2alpha1.DataDownload{}
err = c.client.Patch(pt).
Namespace(c.ns).
Resource("datadownloads").
Name(name).
SubResource(subresources...).
VersionedParams(&opts, scheme.ParameterCodec).
Body(data).
Do(ctx).
Into(result)
return
}

View File

@@ -0,0 +1,195 @@
/*
Copyright the Velero contributors.
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.
*/
// Code generated by client-gen. DO NOT EDIT.
package v2alpha1
import (
"context"
"time"
v2alpha1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v2alpha1"
scheme "github.com/vmware-tanzu/velero/pkg/generated/clientset/versioned/scheme"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
rest "k8s.io/client-go/rest"
)
// DataUploadsGetter has a method to return a DataUploadInterface.
// A group's client should implement this interface.
type DataUploadsGetter interface {
DataUploads(namespace string) DataUploadInterface
}
// DataUploadInterface has methods to work with DataUpload resources.
type DataUploadInterface interface {
Create(ctx context.Context, dataUpload *v2alpha1.DataUpload, opts v1.CreateOptions) (*v2alpha1.DataUpload, error)
Update(ctx context.Context, dataUpload *v2alpha1.DataUpload, opts v1.UpdateOptions) (*v2alpha1.DataUpload, error)
UpdateStatus(ctx context.Context, dataUpload *v2alpha1.DataUpload, opts v1.UpdateOptions) (*v2alpha1.DataUpload, error)
Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
Get(ctx context.Context, name string, opts v1.GetOptions) (*v2alpha1.DataUpload, error)
List(ctx context.Context, opts v1.ListOptions) (*v2alpha1.DataUploadList, error)
Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v2alpha1.DataUpload, err error)
DataUploadExpansion
}
// dataUploads implements DataUploadInterface
type dataUploads struct {
client rest.Interface
ns string
}
// newDataUploads returns a DataUploads
func newDataUploads(c *VeleroV2alpha1Client, namespace string) *dataUploads {
return &dataUploads{
client: c.RESTClient(),
ns: namespace,
}
}
// Get takes name of the dataUpload, and returns the corresponding dataUpload object, and an error if there is any.
func (c *dataUploads) Get(ctx context.Context, name string, options v1.GetOptions) (result *v2alpha1.DataUpload, err error) {
result = &v2alpha1.DataUpload{}
err = c.client.Get().
Namespace(c.ns).
Resource("datauploads").
Name(name).
VersionedParams(&options, scheme.ParameterCodec).
Do(ctx).
Into(result)
return
}
// List takes label and field selectors, and returns the list of DataUploads that match those selectors.
func (c *dataUploads) List(ctx context.Context, opts v1.ListOptions) (result *v2alpha1.DataUploadList, err error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
result = &v2alpha1.DataUploadList{}
err = c.client.Get().
Namespace(c.ns).
Resource("datauploads").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Do(ctx).
Into(result)
return
}
// Watch returns a watch.Interface that watches the requested dataUploads.
func (c *dataUploads) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
opts.Watch = true
return c.client.Get().
Namespace(c.ns).
Resource("datauploads").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Watch(ctx)
}
// Create takes the representation of a dataUpload and creates it. Returns the server's representation of the dataUpload, and an error, if there is any.
func (c *dataUploads) Create(ctx context.Context, dataUpload *v2alpha1.DataUpload, opts v1.CreateOptions) (result *v2alpha1.DataUpload, err error) {
result = &v2alpha1.DataUpload{}
err = c.client.Post().
Namespace(c.ns).
Resource("datauploads").
VersionedParams(&opts, scheme.ParameterCodec).
Body(dataUpload).
Do(ctx).
Into(result)
return
}
// Update takes the representation of a dataUpload and updates it. Returns the server's representation of the dataUpload, and an error, if there is any.
func (c *dataUploads) Update(ctx context.Context, dataUpload *v2alpha1.DataUpload, opts v1.UpdateOptions) (result *v2alpha1.DataUpload, err error) {
result = &v2alpha1.DataUpload{}
err = c.client.Put().
Namespace(c.ns).
Resource("datauploads").
Name(dataUpload.Name).
VersionedParams(&opts, scheme.ParameterCodec).
Body(dataUpload).
Do(ctx).
Into(result)
return
}
// UpdateStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
func (c *dataUploads) UpdateStatus(ctx context.Context, dataUpload *v2alpha1.DataUpload, opts v1.UpdateOptions) (result *v2alpha1.DataUpload, err error) {
result = &v2alpha1.DataUpload{}
err = c.client.Put().
Namespace(c.ns).
Resource("datauploads").
Name(dataUpload.Name).
SubResource("status").
VersionedParams(&opts, scheme.ParameterCodec).
Body(dataUpload).
Do(ctx).
Into(result)
return
}
// Delete takes name of the dataUpload and deletes it. Returns an error if one occurs.
func (c *dataUploads) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
return c.client.Delete().
Namespace(c.ns).
Resource("datauploads").
Name(name).
Body(&opts).
Do(ctx).
Error()
}
// DeleteCollection deletes a collection of objects.
func (c *dataUploads) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
var timeout time.Duration
if listOpts.TimeoutSeconds != nil {
timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
}
return c.client.Delete().
Namespace(c.ns).
Resource("datauploads").
VersionedParams(&listOpts, scheme.ParameterCodec).
Timeout(timeout).
Body(&opts).
Do(ctx).
Error()
}
// Patch applies the patch and returns the patched dataUpload.
func (c *dataUploads) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v2alpha1.DataUpload, err error) {
result = &v2alpha1.DataUpload{}
err = c.client.Patch(pt).
Namespace(c.ns).
Resource("datauploads").
Name(name).
SubResource(subresources...).
VersionedParams(&opts, scheme.ParameterCodec).
Body(data).
Do(ctx).
Into(result)
return
}

View File

@@ -0,0 +1,20 @@
/*
Copyright the Velero contributors.
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.
*/
// Code generated by client-gen. DO NOT EDIT.
// This package has the automatically generated typed clients.
package v2alpha1

View File

@@ -0,0 +1,20 @@
/*
Copyright the Velero contributors.
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.
*/
// Code generated by client-gen. DO NOT EDIT.
// Package fake has the automatically generated clients.
package fake

View File

@@ -0,0 +1,142 @@
/*
Copyright the Velero contributors.
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.
*/
// Code generated by client-gen. DO NOT EDIT.
package fake
import (
"context"
v2alpha1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v2alpha1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
schema "k8s.io/apimachinery/pkg/runtime/schema"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
testing "k8s.io/client-go/testing"
)
// FakeDataDownloads implements DataDownloadInterface
type FakeDataDownloads struct {
Fake *FakeVeleroV2alpha1
ns string
}
var datadownloadsResource = schema.GroupVersionResource{Group: "velero.io", Version: "v2alpha1", Resource: "datadownloads"}
var datadownloadsKind = schema.GroupVersionKind{Group: "velero.io", Version: "v2alpha1", Kind: "DataDownload"}
// Get takes name of the dataDownload, and returns the corresponding dataDownload object, and an error if there is any.
func (c *FakeDataDownloads) Get(ctx context.Context, name string, options v1.GetOptions) (result *v2alpha1.DataDownload, err error) {
obj, err := c.Fake.
Invokes(testing.NewGetAction(datadownloadsResource, c.ns, name), &v2alpha1.DataDownload{})
if obj == nil {
return nil, err
}
return obj.(*v2alpha1.DataDownload), err
}
// List takes label and field selectors, and returns the list of DataDownloads that match those selectors.
func (c *FakeDataDownloads) List(ctx context.Context, opts v1.ListOptions) (result *v2alpha1.DataDownloadList, err error) {
obj, err := c.Fake.
Invokes(testing.NewListAction(datadownloadsResource, datadownloadsKind, c.ns, opts), &v2alpha1.DataDownloadList{})
if obj == nil {
return nil, err
}
label, _, _ := testing.ExtractFromListOptions(opts)
if label == nil {
label = labels.Everything()
}
list := &v2alpha1.DataDownloadList{ListMeta: obj.(*v2alpha1.DataDownloadList).ListMeta}
for _, item := range obj.(*v2alpha1.DataDownloadList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)
}
}
return list, err
}
// Watch returns a watch.Interface that watches the requested dataDownloads.
func (c *FakeDataDownloads) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
return c.Fake.
InvokesWatch(testing.NewWatchAction(datadownloadsResource, c.ns, opts))
}
// Create takes the representation of a dataDownload and creates it. Returns the server's representation of the dataDownload, and an error, if there is any.
func (c *FakeDataDownloads) Create(ctx context.Context, dataDownload *v2alpha1.DataDownload, opts v1.CreateOptions) (result *v2alpha1.DataDownload, err error) {
obj, err := c.Fake.
Invokes(testing.NewCreateAction(datadownloadsResource, c.ns, dataDownload), &v2alpha1.DataDownload{})
if obj == nil {
return nil, err
}
return obj.(*v2alpha1.DataDownload), err
}
// Update takes the representation of a dataDownload and updates it. Returns the server's representation of the dataDownload, and an error, if there is any.
func (c *FakeDataDownloads) Update(ctx context.Context, dataDownload *v2alpha1.DataDownload, opts v1.UpdateOptions) (result *v2alpha1.DataDownload, err error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateAction(datadownloadsResource, c.ns, dataDownload), &v2alpha1.DataDownload{})
if obj == nil {
return nil, err
}
return obj.(*v2alpha1.DataDownload), err
}
// UpdateStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
func (c *FakeDataDownloads) UpdateStatus(ctx context.Context, dataDownload *v2alpha1.DataDownload, opts v1.UpdateOptions) (*v2alpha1.DataDownload, error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateSubresourceAction(datadownloadsResource, "status", c.ns, dataDownload), &v2alpha1.DataDownload{})
if obj == nil {
return nil, err
}
return obj.(*v2alpha1.DataDownload), err
}
// Delete takes name of the dataDownload and deletes it. Returns an error if one occurs.
func (c *FakeDataDownloads) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewDeleteAction(datadownloadsResource, c.ns, name), &v2alpha1.DataDownload{})
return err
}
// DeleteCollection deletes a collection of objects.
func (c *FakeDataDownloads) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
action := testing.NewDeleteCollectionAction(datadownloadsResource, c.ns, listOpts)
_, err := c.Fake.Invokes(action, &v2alpha1.DataDownloadList{})
return err
}
// Patch applies the patch and returns the patched dataDownload.
func (c *FakeDataDownloads) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v2alpha1.DataDownload, err error) {
obj, err := c.Fake.
Invokes(testing.NewPatchSubresourceAction(datadownloadsResource, c.ns, name, pt, data, subresources...), &v2alpha1.DataDownload{})
if obj == nil {
return nil, err
}
return obj.(*v2alpha1.DataDownload), err
}

View File

@@ -0,0 +1,142 @@
/*
Copyright the Velero contributors.
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.
*/
// Code generated by client-gen. DO NOT EDIT.
package fake
import (
"context"
v2alpha1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v2alpha1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
schema "k8s.io/apimachinery/pkg/runtime/schema"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
testing "k8s.io/client-go/testing"
)
// FakeDataUploads implements DataUploadInterface
type FakeDataUploads struct {
Fake *FakeVeleroV2alpha1
ns string
}
var datauploadsResource = schema.GroupVersionResource{Group: "velero.io", Version: "v2alpha1", Resource: "datauploads"}
var datauploadsKind = schema.GroupVersionKind{Group: "velero.io", Version: "v2alpha1", Kind: "DataUpload"}
// Get takes name of the dataUpload, and returns the corresponding dataUpload object, and an error if there is any.
func (c *FakeDataUploads) Get(ctx context.Context, name string, options v1.GetOptions) (result *v2alpha1.DataUpload, err error) {
obj, err := c.Fake.
Invokes(testing.NewGetAction(datauploadsResource, c.ns, name), &v2alpha1.DataUpload{})
if obj == nil {
return nil, err
}
return obj.(*v2alpha1.DataUpload), err
}
// List takes label and field selectors, and returns the list of DataUploads that match those selectors.
func (c *FakeDataUploads) List(ctx context.Context, opts v1.ListOptions) (result *v2alpha1.DataUploadList, err error) {
obj, err := c.Fake.
Invokes(testing.NewListAction(datauploadsResource, datauploadsKind, c.ns, opts), &v2alpha1.DataUploadList{})
if obj == nil {
return nil, err
}
label, _, _ := testing.ExtractFromListOptions(opts)
if label == nil {
label = labels.Everything()
}
list := &v2alpha1.DataUploadList{ListMeta: obj.(*v2alpha1.DataUploadList).ListMeta}
for _, item := range obj.(*v2alpha1.DataUploadList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)
}
}
return list, err
}
// Watch returns a watch.Interface that watches the requested dataUploads.
func (c *FakeDataUploads) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
return c.Fake.
InvokesWatch(testing.NewWatchAction(datauploadsResource, c.ns, opts))
}
// Create takes the representation of a dataUpload and creates it. Returns the server's representation of the dataUpload, and an error, if there is any.
func (c *FakeDataUploads) Create(ctx context.Context, dataUpload *v2alpha1.DataUpload, opts v1.CreateOptions) (result *v2alpha1.DataUpload, err error) {
obj, err := c.Fake.
Invokes(testing.NewCreateAction(datauploadsResource, c.ns, dataUpload), &v2alpha1.DataUpload{})
if obj == nil {
return nil, err
}
return obj.(*v2alpha1.DataUpload), err
}
// Update takes the representation of a dataUpload and updates it. Returns the server's representation of the dataUpload, and an error, if there is any.
func (c *FakeDataUploads) Update(ctx context.Context, dataUpload *v2alpha1.DataUpload, opts v1.UpdateOptions) (result *v2alpha1.DataUpload, err error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateAction(datauploadsResource, c.ns, dataUpload), &v2alpha1.DataUpload{})
if obj == nil {
return nil, err
}
return obj.(*v2alpha1.DataUpload), err
}
// UpdateStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
func (c *FakeDataUploads) UpdateStatus(ctx context.Context, dataUpload *v2alpha1.DataUpload, opts v1.UpdateOptions) (*v2alpha1.DataUpload, error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateSubresourceAction(datauploadsResource, "status", c.ns, dataUpload), &v2alpha1.DataUpload{})
if obj == nil {
return nil, err
}
return obj.(*v2alpha1.DataUpload), err
}
// Delete takes name of the dataUpload and deletes it. Returns an error if one occurs.
func (c *FakeDataUploads) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewDeleteAction(datauploadsResource, c.ns, name), &v2alpha1.DataUpload{})
return err
}
// DeleteCollection deletes a collection of objects.
func (c *FakeDataUploads) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
action := testing.NewDeleteCollectionAction(datauploadsResource, c.ns, listOpts)
_, err := c.Fake.Invokes(action, &v2alpha1.DataUploadList{})
return err
}
// Patch applies the patch and returns the patched dataUpload.
func (c *FakeDataUploads) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v2alpha1.DataUpload, err error) {
obj, err := c.Fake.
Invokes(testing.NewPatchSubresourceAction(datauploadsResource, c.ns, name, pt, data, subresources...), &v2alpha1.DataUpload{})
if obj == nil {
return nil, err
}
return obj.(*v2alpha1.DataUpload), err
}

View File

@@ -0,0 +1,44 @@
/*
Copyright the Velero contributors.
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.
*/
// Code generated by client-gen. DO NOT EDIT.
package fake
import (
v2alpha1 "github.com/vmware-tanzu/velero/pkg/generated/clientset/versioned/typed/velero/v2alpha1"
rest "k8s.io/client-go/rest"
testing "k8s.io/client-go/testing"
)
type FakeVeleroV2alpha1 struct {
*testing.Fake
}
func (c *FakeVeleroV2alpha1) DataDownloads(namespace string) v2alpha1.DataDownloadInterface {
return &FakeDataDownloads{c, namespace}
}
func (c *FakeVeleroV2alpha1) DataUploads(namespace string) v2alpha1.DataUploadInterface {
return &FakeDataUploads{c, namespace}
}
// RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation.
func (c *FakeVeleroV2alpha1) RESTClient() rest.Interface {
var ret *rest.RESTClient
return ret
}

View File

@@ -0,0 +1,23 @@
/*
Copyright the Velero contributors.
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.
*/
// Code generated by client-gen. DO NOT EDIT.
package v2alpha1
type DataDownloadExpansion interface{}
type DataUploadExpansion interface{}

View File

@@ -0,0 +1,94 @@
/*
Copyright the Velero contributors.
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.
*/
// Code generated by client-gen. DO NOT EDIT.
package v2alpha1
import (
v2alpha1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v2alpha1"
"github.com/vmware-tanzu/velero/pkg/generated/clientset/versioned/scheme"
rest "k8s.io/client-go/rest"
)
type VeleroV2alpha1Interface interface {
RESTClient() rest.Interface
DataDownloadsGetter
DataUploadsGetter
}
// VeleroV2alpha1Client is used to interact with features provided by the velero.io group.
type VeleroV2alpha1Client struct {
restClient rest.Interface
}
func (c *VeleroV2alpha1Client) DataDownloads(namespace string) DataDownloadInterface {
return newDataDownloads(c, namespace)
}
func (c *VeleroV2alpha1Client) DataUploads(namespace string) DataUploadInterface {
return newDataUploads(c, namespace)
}
// NewForConfig creates a new VeleroV2alpha1Client for the given config.
func NewForConfig(c *rest.Config) (*VeleroV2alpha1Client, error) {
config := *c
if err := setConfigDefaults(&config); err != nil {
return nil, err
}
client, err := rest.RESTClientFor(&config)
if err != nil {
return nil, err
}
return &VeleroV2alpha1Client{client}, nil
}
// NewForConfigOrDie creates a new VeleroV2alpha1Client for the given config and
// panics if there is an error in the config.
func NewForConfigOrDie(c *rest.Config) *VeleroV2alpha1Client {
client, err := NewForConfig(c)
if err != nil {
panic(err)
}
return client
}
// New creates a new VeleroV2alpha1Client for the given RESTClient.
func New(c rest.Interface) *VeleroV2alpha1Client {
return &VeleroV2alpha1Client{c}
}
func setConfigDefaults(config *rest.Config) error {
gv := v2alpha1.SchemeGroupVersion
config.GroupVersion = &gv
config.APIPath = "/apis"
config.NegotiatedSerializer = scheme.Codecs.WithoutConversion()
if config.UserAgent == "" {
config.UserAgent = rest.DefaultKubernetesUserAgent()
}
return nil
}
// RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation.
func (c *VeleroV2alpha1Client) RESTClient() rest.Interface {
if c == nil {
return nil
}
return c.restClient
}

View File

@@ -22,6 +22,7 @@ import (
"fmt"
v1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
v2alpha1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v2alpha1"
schema "k8s.io/apimachinery/pkg/runtime/schema"
cache "k8s.io/client-go/tools/cache"
)
@@ -76,6 +77,12 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource
case v1.SchemeGroupVersion.WithResource("volumesnapshotlocations"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Velero().V1().VolumeSnapshotLocations().Informer()}, nil
// Group=velero.io, Version=v2alpha1
case v2alpha1.SchemeGroupVersion.WithResource("datadownloads"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Velero().V2alpha1().DataDownloads().Informer()}, nil
case v2alpha1.SchemeGroupVersion.WithResource("datauploads"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Velero().V2alpha1().DataUploads().Informer()}, nil
}
return nil, fmt.Errorf("no informer found for %v", resource)

View File

@@ -21,12 +21,15 @@ package velero
import (
internalinterfaces "github.com/vmware-tanzu/velero/pkg/generated/informers/externalversions/internalinterfaces"
v1 "github.com/vmware-tanzu/velero/pkg/generated/informers/externalversions/velero/v1"
v2alpha1 "github.com/vmware-tanzu/velero/pkg/generated/informers/externalversions/velero/v2alpha1"
)
// Interface provides access to each of this group's versions.
type Interface interface {
// V1 provides access to shared informers for resources in V1.
V1() v1.Interface
// V2alpha1 provides access to shared informers for resources in V2alpha1.
V2alpha1() v2alpha1.Interface
}
type group struct {
@@ -44,3 +47,8 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList
func (g *group) V1() v1.Interface {
return v1.New(g.factory, g.namespace, g.tweakListOptions)
}
// V2alpha1 returns a new v2alpha1.Interface.
func (g *group) V2alpha1() v2alpha1.Interface {
return v2alpha1.New(g.factory, g.namespace, g.tweakListOptions)
}

View File

@@ -0,0 +1,90 @@
/*
Copyright the Velero contributors.
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.
*/
// Code generated by informer-gen. DO NOT EDIT.
package v2alpha1
import (
"context"
time "time"
velerov2alpha1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v2alpha1"
versioned "github.com/vmware-tanzu/velero/pkg/generated/clientset/versioned"
internalinterfaces "github.com/vmware-tanzu/velero/pkg/generated/informers/externalversions/internalinterfaces"
v2alpha1 "github.com/vmware-tanzu/velero/pkg/generated/listers/velero/v2alpha1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
watch "k8s.io/apimachinery/pkg/watch"
cache "k8s.io/client-go/tools/cache"
)
// DataDownloadInformer provides access to a shared informer and lister for
// DataDownloads.
type DataDownloadInformer interface {
Informer() cache.SharedIndexInformer
Lister() v2alpha1.DataDownloadLister
}
type dataDownloadInformer struct {
factory internalinterfaces.SharedInformerFactory
tweakListOptions internalinterfaces.TweakListOptionsFunc
namespace string
}
// NewDataDownloadInformer constructs a new informer for DataDownload type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewDataDownloadInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredDataDownloadInformer(client, namespace, resyncPeriod, indexers, nil)
}
// NewFilteredDataDownloadInformer constructs a new informer for DataDownload type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewFilteredDataDownloadInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return cache.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.VeleroV2alpha1().DataDownloads(namespace).List(context.TODO(), options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.VeleroV2alpha1().DataDownloads(namespace).Watch(context.TODO(), options)
},
},
&velerov2alpha1.DataDownload{},
resyncPeriod,
indexers,
)
}
func (f *dataDownloadInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredDataDownloadInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
}
func (f *dataDownloadInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&velerov2alpha1.DataDownload{}, f.defaultInformer)
}
func (f *dataDownloadInformer) Lister() v2alpha1.DataDownloadLister {
return v2alpha1.NewDataDownloadLister(f.Informer().GetIndexer())
}

View File

@@ -0,0 +1,90 @@
/*
Copyright the Velero contributors.
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.
*/
// Code generated by informer-gen. DO NOT EDIT.
package v2alpha1
import (
"context"
time "time"
velerov2alpha1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v2alpha1"
versioned "github.com/vmware-tanzu/velero/pkg/generated/clientset/versioned"
internalinterfaces "github.com/vmware-tanzu/velero/pkg/generated/informers/externalversions/internalinterfaces"
v2alpha1 "github.com/vmware-tanzu/velero/pkg/generated/listers/velero/v2alpha1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
watch "k8s.io/apimachinery/pkg/watch"
cache "k8s.io/client-go/tools/cache"
)
// DataUploadInformer provides access to a shared informer and lister for
// DataUploads.
type DataUploadInformer interface {
Informer() cache.SharedIndexInformer
Lister() v2alpha1.DataUploadLister
}
type dataUploadInformer struct {
factory internalinterfaces.SharedInformerFactory
tweakListOptions internalinterfaces.TweakListOptionsFunc
namespace string
}
// NewDataUploadInformer constructs a new informer for DataUpload type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewDataUploadInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredDataUploadInformer(client, namespace, resyncPeriod, indexers, nil)
}
// NewFilteredDataUploadInformer constructs a new informer for DataUpload type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewFilteredDataUploadInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return cache.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.VeleroV2alpha1().DataUploads(namespace).List(context.TODO(), options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.VeleroV2alpha1().DataUploads(namespace).Watch(context.TODO(), options)
},
},
&velerov2alpha1.DataUpload{},
resyncPeriod,
indexers,
)
}
func (f *dataUploadInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredDataUploadInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
}
func (f *dataUploadInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&velerov2alpha1.DataUpload{}, f.defaultInformer)
}
func (f *dataUploadInformer) Lister() v2alpha1.DataUploadLister {
return v2alpha1.NewDataUploadLister(f.Informer().GetIndexer())
}

View File

@@ -0,0 +1,52 @@
/*
Copyright the Velero contributors.
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.
*/
// Code generated by informer-gen. DO NOT EDIT.
package v2alpha1
import (
internalinterfaces "github.com/vmware-tanzu/velero/pkg/generated/informers/externalversions/internalinterfaces"
)
// Interface provides access to all the informers in this group version.
type Interface interface {
// DataDownloads returns a DataDownloadInformer.
DataDownloads() DataDownloadInformer
// DataUploads returns a DataUploadInformer.
DataUploads() DataUploadInformer
}
type version struct {
factory internalinterfaces.SharedInformerFactory
namespace string
tweakListOptions internalinterfaces.TweakListOptionsFunc
}
// New returns a new Interface.
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
}
// DataDownloads returns a DataDownloadInformer.
func (v *version) DataDownloads() DataDownloadInformer {
return &dataDownloadInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
}
// DataUploads returns a DataUploadInformer.
func (v *version) DataUploads() DataUploadInformer {
return &dataUploadInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
}

View File

@@ -0,0 +1,99 @@
/*
Copyright the Velero contributors.
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.
*/
// Code generated by lister-gen. DO NOT EDIT.
package v2alpha1
import (
v2alpha1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v2alpha1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/tools/cache"
)
// DataDownloadLister helps list DataDownloads.
// All objects returned here must be treated as read-only.
type DataDownloadLister interface {
// List lists all DataDownloads in the indexer.
// Objects returned here must be treated as read-only.
List(selector labels.Selector) (ret []*v2alpha1.DataDownload, err error)
// DataDownloads returns an object that can list and get DataDownloads.
DataDownloads(namespace string) DataDownloadNamespaceLister
DataDownloadListerExpansion
}
// dataDownloadLister implements the DataDownloadLister interface.
type dataDownloadLister struct {
indexer cache.Indexer
}
// NewDataDownloadLister returns a new DataDownloadLister.
func NewDataDownloadLister(indexer cache.Indexer) DataDownloadLister {
return &dataDownloadLister{indexer: indexer}
}
// List lists all DataDownloads in the indexer.
func (s *dataDownloadLister) List(selector labels.Selector) (ret []*v2alpha1.DataDownload, err error) {
err = cache.ListAll(s.indexer, selector, func(m interface{}) {
ret = append(ret, m.(*v2alpha1.DataDownload))
})
return ret, err
}
// DataDownloads returns an object that can list and get DataDownloads.
func (s *dataDownloadLister) DataDownloads(namespace string) DataDownloadNamespaceLister {
return dataDownloadNamespaceLister{indexer: s.indexer, namespace: namespace}
}
// DataDownloadNamespaceLister helps list and get DataDownloads.
// All objects returned here must be treated as read-only.
type DataDownloadNamespaceLister interface {
// List lists all DataDownloads in the indexer for a given namespace.
// Objects returned here must be treated as read-only.
List(selector labels.Selector) (ret []*v2alpha1.DataDownload, err error)
// Get retrieves the DataDownload from the indexer for a given namespace and name.
// Objects returned here must be treated as read-only.
Get(name string) (*v2alpha1.DataDownload, error)
DataDownloadNamespaceListerExpansion
}
// dataDownloadNamespaceLister implements the DataDownloadNamespaceLister
// interface.
type dataDownloadNamespaceLister struct {
indexer cache.Indexer
namespace string
}
// List lists all DataDownloads in the indexer for a given namespace.
func (s dataDownloadNamespaceLister) List(selector labels.Selector) (ret []*v2alpha1.DataDownload, err error) {
err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
ret = append(ret, m.(*v2alpha1.DataDownload))
})
return ret, err
}
// Get retrieves the DataDownload from the indexer for a given namespace and name.
func (s dataDownloadNamespaceLister) Get(name string) (*v2alpha1.DataDownload, error) {
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
if err != nil {
return nil, err
}
if !exists {
return nil, errors.NewNotFound(v2alpha1.Resource("datadownload"), name)
}
return obj.(*v2alpha1.DataDownload), nil
}

View File

@@ -0,0 +1,99 @@
/*
Copyright the Velero contributors.
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.
*/
// Code generated by lister-gen. DO NOT EDIT.
package v2alpha1
import (
v2alpha1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v2alpha1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/tools/cache"
)
// DataUploadLister helps list DataUploads.
// All objects returned here must be treated as read-only.
type DataUploadLister interface {
// List lists all DataUploads in the indexer.
// Objects returned here must be treated as read-only.
List(selector labels.Selector) (ret []*v2alpha1.DataUpload, err error)
// DataUploads returns an object that can list and get DataUploads.
DataUploads(namespace string) DataUploadNamespaceLister
DataUploadListerExpansion
}
// dataUploadLister implements the DataUploadLister interface.
type dataUploadLister struct {
indexer cache.Indexer
}
// NewDataUploadLister returns a new DataUploadLister.
func NewDataUploadLister(indexer cache.Indexer) DataUploadLister {
return &dataUploadLister{indexer: indexer}
}
// List lists all DataUploads in the indexer.
func (s *dataUploadLister) List(selector labels.Selector) (ret []*v2alpha1.DataUpload, err error) {
err = cache.ListAll(s.indexer, selector, func(m interface{}) {
ret = append(ret, m.(*v2alpha1.DataUpload))
})
return ret, err
}
// DataUploads returns an object that can list and get DataUploads.
func (s *dataUploadLister) DataUploads(namespace string) DataUploadNamespaceLister {
return dataUploadNamespaceLister{indexer: s.indexer, namespace: namespace}
}
// DataUploadNamespaceLister helps list and get DataUploads.
// All objects returned here must be treated as read-only.
type DataUploadNamespaceLister interface {
// List lists all DataUploads in the indexer for a given namespace.
// Objects returned here must be treated as read-only.
List(selector labels.Selector) (ret []*v2alpha1.DataUpload, err error)
// Get retrieves the DataUpload from the indexer for a given namespace and name.
// Objects returned here must be treated as read-only.
Get(name string) (*v2alpha1.DataUpload, error)
DataUploadNamespaceListerExpansion
}
// dataUploadNamespaceLister implements the DataUploadNamespaceLister
// interface.
type dataUploadNamespaceLister struct {
indexer cache.Indexer
namespace string
}
// List lists all DataUploads in the indexer for a given namespace.
func (s dataUploadNamespaceLister) List(selector labels.Selector) (ret []*v2alpha1.DataUpload, err error) {
err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
ret = append(ret, m.(*v2alpha1.DataUpload))
})
return ret, err
}
// Get retrieves the DataUpload from the indexer for a given namespace and name.
func (s dataUploadNamespaceLister) Get(name string) (*v2alpha1.DataUpload, error) {
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
if err != nil {
return nil, err
}
if !exists {
return nil, errors.NewNotFound(v2alpha1.Resource("dataupload"), name)
}
return obj.(*v2alpha1.DataUpload), nil
}

View File

@@ -0,0 +1,35 @@
/*
Copyright the Velero contributors.
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.
*/
// Code generated by lister-gen. DO NOT EDIT.
package v2alpha1
// DataDownloadListerExpansion allows custom methods to be added to
// DataDownloadLister.
type DataDownloadListerExpansion interface{}
// DataDownloadNamespaceListerExpansion allows custom methods to be added to
// DataDownloadNamespaceLister.
type DataDownloadNamespaceListerExpansion interface{}
// DataUploadListerExpansion allows custom methods to be added to
// DataUploadLister.
type DataUploadListerExpansion interface{}
// DataUploadNamespaceListerExpansion allows custom methods to be added to
// DataUploadNamespaceLister.
type DataUploadNamespaceListerExpansion interface{}

View File

@@ -28,6 +28,7 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema"
v1crds "github.com/vmware-tanzu/velero/config/crd/v1/crds"
v2alpha1crds "github.com/vmware-tanzu/velero/config/crd/v2alpha1/crds"
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
)
@@ -252,7 +253,14 @@ func AllCRDs() *unstructured.UnstructuredList {
for _, crd := range v1crds.CRDs {
crd.SetLabels(Labels())
if err := appendUnstructured(resources, crd); err != nil {
fmt.Printf("error appending CRD %s: %s\n", crd.GetName(), err.Error())
fmt.Printf("error appending v1 CRD %s: %s\n", crd.GetName(), err.Error())
}
}
for _, crd := range v2alpha1crds.CRDs {
crd.SetLabels(Labels())
if err := appendUnstructured(resources, crd); err != nil {
fmt.Printf("error appending v2alpha1 CRD %s: %s\n", crd.GetName(), err.Error())
}
}

View File

@@ -27,7 +27,7 @@ import (
)
func PluginConfigLabelSelector(kind PluginKind, name string) string {
return fmt.Sprintf("velero.io/plugin-config=true,%s=%s", name, kind)
return fmt.Sprintf("velero.io/plugin-config,%s=%s", name, kind)
}
func GetPluginConfig(kind PluginKind, name string, client corev1client.ConfigMapInterface) (*corev1.ConfigMap, error) {

View File

@@ -22,7 +22,6 @@ import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/kubernetes/fake"
@@ -35,7 +34,7 @@ func TestGetPluginConfig(t *testing.T) {
name string
objects []runtime.Object
}
pluginLabelsSet, _ := labels.ConvertSelectorToLabelsMap(PluginConfigLabelSelector(PluginKindRestoreItemAction, "foo"))
pluginLabelsMap := map[string]string{"velero.io/plugin-config": "", "foo": "RestoreItemAction"}
testConfigMap := &corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{
Kind: "ConfigMap",
@@ -43,7 +42,7 @@ func TestGetPluginConfig(t *testing.T) {
ObjectMeta: metav1.ObjectMeta{
Name: "foo-config",
Namespace: velerov1.DefaultNamespace,
Labels: pluginLabelsSet,
Labels: pluginLabelsMap,
},
}
tests := []struct {
@@ -75,7 +74,7 @@ func TestGetPluginConfig(t *testing.T) {
ObjectMeta: metav1.ObjectMeta{
Name: "foo-config",
Namespace: velerov1.DefaultNamespace,
Labels: pluginLabelsSet,
Labels: pluginLabelsMap,
},
},
&corev1.ConfigMap{
@@ -85,7 +84,7 @@ func TestGetPluginConfig(t *testing.T) {
ObjectMeta: metav1.ObjectMeta{
Name: "foo-config-duplicate",
Namespace: velerov1.DefaultNamespace,
Labels: pluginLabelsSet,
Labels: pluginLabelsMap,
},
},
},

View File

@@ -131,7 +131,7 @@ func (b *backupper) BackupPodVolumes(backup *velerov1api.Backup, pod *corev1api.
if len(volumesToBackup) == 0 {
return nil, nil
}
log.Infof("pod %s/%s has volumes to backup: %v", pod.Namespace, pod.Name, volumesToBackup)
err := kube.IsPodRunning(pod)
if err != nil {
for _, volumeName := range volumesToBackup {

View File

@@ -17,13 +17,19 @@ limitations under the License.
package podvolume
import (
"bytes"
"context"
"fmt"
"testing"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
corev1api "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/vmware-tanzu/velero/internal/resourcepolicies"
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
)
func TestIsHostPathVolume(t *testing.T) {
@@ -139,3 +145,62 @@ func (g *fakePVGetter) Get(ctx context.Context, name string, opts metav1.GetOpti
return nil, errors.New("item not found")
}
func Test_backupper_BackupPodVolumes_log_test(t *testing.T) {
type args struct {
backup *velerov1api.Backup
pod *corev1api.Pod
volumesToBackup []string
resPolicies *resourcepolicies.Policies
}
tests := []struct {
name string
args args
wantLog string
}{
{
name: "backup pod volumes should log volume names",
args: args{
backup: &velerov1api.Backup{
ObjectMeta: metav1.ObjectMeta{
Name: "backup-1",
Namespace: "ns-1",
},
},
pod: &corev1api.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "pod-1",
Namespace: "ns-1",
},
Spec: corev1api.PodSpec{
Volumes: []corev1api.Volume{
{
Name: "vol-1",
},
{
Name: "vol-2",
},
},
},
},
volumesToBackup: []string{"vol-1", "vol-2"},
resPolicies: nil,
},
wantLog: "pod ns-1/pod-1 has volumes to backup: [vol-1 vol-2]",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
b := &backupper{
ctx: context.Background(),
}
logOutput := bytes.Buffer{}
var log = logrus.New()
log.SetOutput(&logOutput)
b.BackupPodVolumes(tt.args.backup, tt.args.pod, tt.args.volumesToBackup, tt.args.resPolicies, log)
fmt.Println(logOutput.String())
assert.Contains(t, logOutput.String(), tt.wantLog)
})
}
}

View File

@@ -18,6 +18,7 @@ package provider
import (
"context"
"encoding/base64"
"fmt"
"net/url"
"path"
@@ -498,6 +499,10 @@ func getStorageVariables(backupLocation *velerov1api.BackupStorageLocation, repo
result[udmrepo.StoreOptionS3Endpoint] = strings.Trim(s3URL, "/")
result[udmrepo.StoreOptionS3DisableTLSVerify] = config["insecureSkipTLSVerify"]
result[udmrepo.StoreOptionS3DisableTLS] = strconv.FormatBool(disableTLS)
if backupLocation.Spec.ObjectStorage != nil && backupLocation.Spec.ObjectStorage.CACert != nil {
result[udmrepo.StoreOptionS3CustomCA] = base64.StdEncoding.EncodeToString(backupLocation.Spec.ObjectStorage.CACert)
}
} else if backendType == repoconfig.AzureBackend {
domain, err := getAzureStorageDomain(config)
if err != nil {

View File

@@ -18,6 +18,7 @@ package provider
import (
"context"
"encoding/base64"
"errors"
"testing"
@@ -380,6 +381,42 @@ func TestGetStorageVariables(t *testing.T) {
"skipTLSVerify": "false",
},
},
{
name: "aws, ObjectStorage section exists in BSL, s3Url exist, https, custom CA exist",
backupLocation: velerov1api.BackupStorageLocation{
Spec: velerov1api.BackupStorageLocationSpec{
Provider: "velero.io/aws",
Config: map[string]string{
"bucket": "fake-bucket-config",
"prefix": "fake-prefix-config",
"region": "fake-region",
"s3Url": "https://fake-url/",
"insecureSkipTLSVerify": "false",
},
StorageType: velerov1api.StorageType{
ObjectStorage: &velerov1api.ObjectStorageLocation{
Bucket: "fake-bucket-object-store",
Prefix: "fake-prefix-object-store",
CACert: []byte{0x01, 0x02, 0x03, 0x04, 0x05},
},
},
},
},
getS3BucketRegion: func(bucket string) (string, error) {
return "region from bucket: " + bucket, nil
},
repoBackend: "fake-repo-type",
expected: map[string]string{
"bucket": "fake-bucket-object-store",
"prefix": "fake-prefix-object-store/fake-repo-type/",
"region": "fake-region",
"fspath": "",
"endpoint": "fake-url",
"doNotUseTLS": "false",
"skipTLSVerify": "false",
"customCA": base64.StdEncoding.EncodeToString([]byte{0x01, 0x02, 0x03, 0x04, 0x05}),
},
},
{
name: "azure, getAzureStorageDomain fail",
backupLocation: velerov1api.BackupStorageLocation{

View File

@@ -44,6 +44,7 @@ func (c *S3Backend) Setup(ctx context.Context, flags map[string]string) error {
c.options.DoNotUseTLS = optionalHaveBool(ctx, udmrepo.StoreOptionS3DisableTLS, flags)
c.options.DoNotVerifyTLS = optionalHaveBool(ctx, udmrepo.StoreOptionS3DisableTLSVerify, flags)
c.options.SessionToken = optionalHaveString(udmrepo.StoreOptionS3Token, flags)
c.options.RootCA = optionalHaveBase64(ctx, udmrepo.StoreOptionS3CustomCA, flags)
c.options.Limits = setupLimits(ctx, flags)

View File

@@ -18,6 +18,7 @@ package backend
import (
"context"
"encoding/base64"
"strconv"
"time"
@@ -84,6 +85,19 @@ func optionalHaveDuration(ctx context.Context, key string, flags map[string]stri
return 0
}
func optionalHaveBase64(ctx context.Context, key string, flags map[string]string) []byte {
if value, exist := flags[key]; exist {
ret, err := base64.StdEncoding.DecodeString(value)
if err == nil {
return ret
}
backendLog()(ctx).Errorf("Ignore %s, value [%s] is invalid, err %v", key, value, err)
}
return nil
}
func backendLog() func(ctx context.Context) logging.Logger {
return logging.Module("kopialib-bd")
}

View File

@@ -42,6 +42,7 @@ const (
StoreOptionS3Endpoint = "endpoint"
StoreOptionS3DisableTLS = "doNotUseTLS"
StoreOptionS3DisableTLSVerify = "skipTLSVerify"
StoreOptionS3CustomCA = "customCA"
StoreOptionAzureKey = "storageKey"
StoreOptionAzureDomain = "storageDomain"

View File

@@ -55,7 +55,7 @@ func TestChangeImageRepositoryActionExecute(t *testing.T) {
Image: "1.1.1.1:5000/abc:test",
}).Result(),
configMap: builder.ForConfigMap("velero", "change-image-name").
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "true", "velero.io/change-image-name", "RestoreItemAction")).
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "", "velero.io/change-image-name", "RestoreItemAction")).
Data("case1", "1.1.1.1:5000 , 2.2.2.2:3000").
Result(),
freshedImageName: "2.2.2.2:3000/abc:test",
@@ -70,7 +70,7 @@ func TestChangeImageRepositoryActionExecute(t *testing.T) {
Image: "1.1.1.1:5000/abc:test",
}).Result(),
configMap: builder.ForConfigMap("velero", "change-image-name").
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "true", "velero.io/change-image-name", "RestoreItemAction")).
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "", "velero.io/change-image-name", "RestoreItemAction")).
Data("specific", "1.1.1.1:5000,2.2.2.2:3000").
Result(),
freshedImageName: "2.2.2.2:3000/abc:test",
@@ -85,7 +85,7 @@ func TestChangeImageRepositoryActionExecute(t *testing.T) {
Image: "1.1.1.1:5000/abc:test",
}).Result(),
configMap: builder.ForConfigMap("velero", "change-image-name").
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "true", "velero.io/change-image-name", "RestoreItemAction")).
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "", "velero.io/change-image-name", "RestoreItemAction")).
Data("specific", "abc:test,myproject:latest").
Result(),
freshedImageName: "1.1.1.1:5000/myproject:latest",
@@ -100,7 +100,7 @@ func TestChangeImageRepositoryActionExecute(t *testing.T) {
Image: "1.1.1.1:5000/abc:test",
}).Result(),
configMap: builder.ForConfigMap("velero", "change-image-name").
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "true", "velero.io/change-image-name", "RestoreItemAction")).
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "", "velero.io/change-image-name", "RestoreItemAction")).
Data("specific", "5000,3333").
Result(),
freshedImageName: "1.1.1.1:5000/abc:test",
@@ -115,7 +115,7 @@ func TestChangeImageRepositoryActionExecute(t *testing.T) {
Image: "1.1.1.1:5000/abc:test",
}).Result(),
configMap: builder.ForConfigMap("velero", "change-image-name").
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "true", "velero.io/change-image-name", "RestoreItemAction")).
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "", "velero.io/change-image-name", "RestoreItemAction")).
Data("specific", "test,latest").
Result(),
freshedImageName: "1.1.1.1:5000/abc:test",
@@ -130,7 +130,7 @@ func TestChangeImageRepositoryActionExecute(t *testing.T) {
Image: "dev/image1:dev",
}).Result(),
configMap: builder.ForConfigMap("velero", "change-image-name").
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "true", "velero.io/change-image-name", "RestoreItemAction")).
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "", "velero.io/change-image-name", "RestoreItemAction")).
Data("specific", "dev/,test/").
Result(),
freshedImageName: "dev/image1:dev",

View File

@@ -57,7 +57,7 @@ func TestChangePVCNodeSelectorActionExecute(t *testing.T) {
builder.WithAnnotations("volume.kubernetes.io/selected-node", "source-node"),
).Result(),
configMap: builder.ForConfigMap("velero", "change-pvc-node").
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "true", "velero.io/change-pvc-node-selector", "RestoreItemAction")).
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "", "velero.io/change-pvc-node-selector", "RestoreItemAction")).
Data("source-node", "dest-node").
Result(),
newNode: builder.ForNode("dest-node").Result(),
@@ -73,7 +73,7 @@ func TestChangePVCNodeSelectorActionExecute(t *testing.T) {
builder.WithAnnotations("volume.kubernetes.io/selected-node", "source-node"),
).Result(),
configMap: builder.ForConfigMap("velero", "change-pvc-node").
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "true", "velero.io/some-other-plugin", "RestoreItemAction")).
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "", "velero.io/some-other-plugin", "RestoreItemAction")).
Data("source-noed", "dest-node").
Result(),
want: builder.ForPersistentVolumeClaim("source-ns", "pvc-1").Result(),
@@ -85,7 +85,7 @@ func TestChangePVCNodeSelectorActionExecute(t *testing.T) {
builder.WithAnnotations("volume.kubernetes.io/selected-node", "source-node"),
).Result(),
configMap: builder.ForConfigMap("velero", "change-pvc-node").
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "true", "velero.io/change-pvc-node-selector", "RestoreItemAction")).
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "", "velero.io/change-pvc-node-selector", "RestoreItemAction")).
Result(),
want: builder.ForPersistentVolumeClaim("source-ns", "pvc-1").Result(),
},
@@ -96,7 +96,7 @@ func TestChangePVCNodeSelectorActionExecute(t *testing.T) {
builder.WithAnnotations("volume.kubernetes.io/selected-node", "source-node"),
).Result(),
configMap: builder.ForConfigMap("velero", "change-pvc-node").
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "true", "velero.io/change-pvc-node-selector", "RestoreItemAction")).
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "", "velero.io/change-pvc-node-selector", "RestoreItemAction")).
Result(),
// MAYANK TODO
node: builder.ForNode("source-node").Result(),
@@ -109,7 +109,7 @@ func TestChangePVCNodeSelectorActionExecute(t *testing.T) {
name: "when persistent volume claim has no node selector, the item is returned as-is",
pvc: builder.ForPersistentVolumeClaim("source-ns", "pvc-1").Result(),
configMap: builder.ForConfigMap("velero", "change-pvc-node").
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "true", "velero.io/change-pvc-node-selector", "RestoreItemAction")).
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "", "velero.io/change-pvc-node-selector", "RestoreItemAction")).
Data("source-node", "dest-node").
Result(),
want: builder.ForPersistentVolumeClaim("source-ns", "pvc-1").Result(),
@@ -121,7 +121,7 @@ func TestChangePVCNodeSelectorActionExecute(t *testing.T) {
builder.WithAnnotations("volume.kubernetes.io/selected-node", "source-node"),
).Result(),
configMap: builder.ForConfigMap("velero", "change-pvc-node").
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "true", "velero.io/change-pvc-node-selector", "RestoreItemAction")).
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "", "velero.io/change-pvc-node-selector", "RestoreItemAction")).
Data("source-node-1", "dest-node").
Result(),
want: builder.ForPersistentVolumeClaim("source-ns", "pvc-1").Result(),

View File

@@ -53,7 +53,7 @@ func TestChangeStorageClassActionExecute(t *testing.T) {
name: "a valid mapping for a persistent volume is applied correctly",
pvOrPvcOrSTS: builder.ForPersistentVolume("pv-1").StorageClass("storageclass-1").Result(),
configMap: builder.ForConfigMap("velero", "change-storage-classs").
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "true", "velero.io/change-storage-class", "RestoreItemAction")).
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "", "velero.io/change-storage-class", "RestoreItemAction")).
Data("storageclass-1", "storageclass-2").
Result(),
storageClass: builder.ForStorageClass("storageclass-2").Result(),
@@ -63,7 +63,7 @@ func TestChangeStorageClassActionExecute(t *testing.T) {
name: "a valid mapping for a persistent volume claim is applied correctly",
pvOrPvcOrSTS: builder.ForPersistentVolumeClaim("velero", "pvc-1").StorageClass("storageclass-1").Result(),
configMap: builder.ForConfigMap("velero", "change-storage-classs").
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "true", "velero.io/change-storage-class", "RestoreItemAction")).
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "", "velero.io/change-storage-class", "RestoreItemAction")).
Data("storageclass-1", "storageclass-2").
Result(),
storageClass: builder.ForStorageClass("storageclass-2").Result(),
@@ -73,7 +73,7 @@ func TestChangeStorageClassActionExecute(t *testing.T) {
name: "when no config map exists for the plugin, the item is returned as-is",
pvOrPvcOrSTS: builder.ForPersistentVolume("pv-1").StorageClass("storageclass-1").Result(),
configMap: builder.ForConfigMap("velero", "change-storage-classs").
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "true", "velero.io/some-other-plugin", "RestoreItemAction")).
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "", "velero.io/some-other-plugin", "RestoreItemAction")).
Data("storageclass-1", "storageclass-2").
Result(),
want: builder.ForPersistentVolume("pv-1").StorageClass("storageclass-1").Result(),
@@ -82,7 +82,7 @@ func TestChangeStorageClassActionExecute(t *testing.T) {
name: "when no storage class mappings exist in the plugin config map, the item is returned as-is",
pvOrPvcOrSTS: builder.ForPersistentVolume("pv-1").StorageClass("storageclass-1").Result(),
configMap: builder.ForConfigMap("velero", "change-storage-classs").
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "true", "velero.io/change-storage-class", "RestoreItemAction")).
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "", "velero.io/change-storage-class", "RestoreItemAction")).
Result(),
want: builder.ForPersistentVolume("pv-1").StorageClass("storageclass-1").Result(),
},
@@ -90,7 +90,7 @@ func TestChangeStorageClassActionExecute(t *testing.T) {
name: "when persistent volume has no storage class, the item is returned as-is",
pvOrPvcOrSTS: builder.ForPersistentVolume("pv-1").Result(),
configMap: builder.ForConfigMap("velero", "change-storage-classs").
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "true", "velero.io/change-storage-class", "RestoreItemAction")).
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "", "velero.io/change-storage-class", "RestoreItemAction")).
Data("storageclass-1", "storageclass-2").
Result(),
want: builder.ForPersistentVolume("pv-1").Result(),
@@ -99,7 +99,7 @@ func TestChangeStorageClassActionExecute(t *testing.T) {
name: "when persistent volume claim has no storage class, the item is returned as-is",
pvOrPvcOrSTS: builder.ForPersistentVolumeClaim("velero", "pvc-1").Result(),
configMap: builder.ForConfigMap("velero", "change-storage-classs").
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "true", "velero.io/change-storage-class", "RestoreItemAction")).
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "", "velero.io/change-storage-class", "RestoreItemAction")).
Data("storageclass-1", "storageclass-2").
Result(),
want: builder.ForPersistentVolumeClaim("velero", "pvc-1").Result(),
@@ -108,7 +108,7 @@ func TestChangeStorageClassActionExecute(t *testing.T) {
name: "when persistent volume's storage class has no mapping in the config map, the item is returned as-is",
pvOrPvcOrSTS: builder.ForPersistentVolume("pv-1").StorageClass("storageclass-1").Result(),
configMap: builder.ForConfigMap("velero", "change-storage-classs").
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "true", "velero.io/change-storage-class", "RestoreItemAction")).
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "", "velero.io/change-storage-class", "RestoreItemAction")).
Data("storageclass-3", "storageclass-4").
Result(),
want: builder.ForPersistentVolume("pv-1").StorageClass("storageclass-1").Result(),
@@ -117,7 +117,7 @@ func TestChangeStorageClassActionExecute(t *testing.T) {
name: "when persistent volume claim's storage class has no mapping in the config map, the item is returned as-is",
pvOrPvcOrSTS: builder.ForPersistentVolumeClaim("velero", "pvc-1").StorageClass("storageclass-1").Result(),
configMap: builder.ForConfigMap("velero", "change-storage-classs").
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "true", "velero.io/change-storage-class", "RestoreItemAction")).
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "", "velero.io/change-storage-class", "RestoreItemAction")).
Data("storageclass-3", "storageclass-4").
Result(),
want: builder.ForPersistentVolumeClaim("velero", "pvc-1").StorageClass("storageclass-1").Result(),
@@ -126,7 +126,7 @@ func TestChangeStorageClassActionExecute(t *testing.T) {
name: "when persistent volume's storage class is mapped to a nonexistent storage class, an error is returned",
pvOrPvcOrSTS: builder.ForPersistentVolume("pv-1").StorageClass("storageclass-1").Result(),
configMap: builder.ForConfigMap("velero", "change-storage-classs").
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "true", "velero.io/change-storage-class", "RestoreItemAction")).
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "", "velero.io/change-storage-class", "RestoreItemAction")).
Data("storageclass-1", "nonexistent-storage-class").
Result(),
wantErr: errors.New("error getting storage class nonexistent-storage-class from API: storageclasses.storage.k8s.io \"nonexistent-storage-class\" not found"),
@@ -135,7 +135,7 @@ func TestChangeStorageClassActionExecute(t *testing.T) {
name: "when persistent volume claim's storage class is mapped to a nonexistent storage class, an error is returned",
pvOrPvcOrSTS: builder.ForPersistentVolumeClaim("velero", "pvc-1").StorageClass("storageclass-1").Result(),
configMap: builder.ForConfigMap("velero", "change-storage-classs").
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "true", "velero.io/change-storage-class", "RestoreItemAction")).
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "", "velero.io/change-storage-class", "RestoreItemAction")).
Data("storageclass-1", "nonexistent-storage-class").
Result(),
wantErr: errors.New("error getting storage class nonexistent-storage-class from API: storageclasses.storage.k8s.io \"nonexistent-storage-class\" not found"),
@@ -144,7 +144,7 @@ func TestChangeStorageClassActionExecute(t *testing.T) {
name: "when statefulset's VolumeClaimTemplates has only one pvc, a valid mapping for a statefulset is applied correctly",
pvOrPvcOrSTS: builder.ForStatefulSet("velero", "sts-1").StorageClass("storageclass-1").Result(),
configMap: builder.ForConfigMap("velero", "change-storage-classs").
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "true", "velero.io/change-storage-class", "RestoreItemAction")).
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "", "velero.io/change-storage-class", "RestoreItemAction")).
Data("storageclass-1", "storageclass-2").
Result(),
storageClass: builder.ForStorageClass("storageclass-2").Result(),
@@ -154,7 +154,7 @@ func TestChangeStorageClassActionExecute(t *testing.T) {
name: "when statefulset's VolumeClaimTemplates has more than one same pvc's storageClassName, a valid mapping for a statefulset is applied correctly",
pvOrPvcOrSTS: builder.ForStatefulSet("velero", "sts-1").StorageClass("storageclass-1", "storageclass-1").Result(),
configMap: builder.ForConfigMap("velero", "change-storage-classs").
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "true", "velero.io/change-storage-class", "RestoreItemAction")).
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "", "velero.io/change-storage-class", "RestoreItemAction")).
Data("storageclass-1", "storageclass-2", "storageclass-3", "storageclass-4").
Result(),
storageClass: builder.ForStorageClass("storageclass-2").Result(),
@@ -164,7 +164,7 @@ func TestChangeStorageClassActionExecute(t *testing.T) {
name: "when statefulset's VolumeClaimTemplates has more than one different pvc's storageClassName, a valid mapping for a statefulset is applied correctly",
pvOrPvcOrSTS: builder.ForStatefulSet("velero", "sts-1").StorageClass("storageclass-1", "storageclass-2", "storageclass-3").Result(),
configMap: builder.ForConfigMap("velero", "change-storage-classs").
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "true", "velero.io/change-storage-class", "RestoreItemAction")).
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "", "velero.io/change-storage-class", "RestoreItemAction")).
Data("storageclass-1", "storageclass-a", "storageclass-2", "storageclass-b", "storageclass-3", "storageclass-c").
Result(),
storageClassSlice: builder.ForStorageClassSlice("storageclass-a", "storageclass-b", "storageclass-c").SliceResult(),
@@ -174,7 +174,7 @@ func TestChangeStorageClassActionExecute(t *testing.T) {
name: "when no config map exists for the plugin, the statefulset item is returned as-is",
pvOrPvcOrSTS: builder.ForStatefulSet("velero", "sts-1").StorageClass("storageclass-1").Result(),
configMap: builder.ForConfigMap("velero", "change-storage-classs").
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "true", "velero.io/some-other-plugin", "RestoreItemAction")).
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "", "velero.io/some-other-plugin", "RestoreItemAction")).
Data("storageclass-1", "storageclass-2").
Result(),
want: builder.ForStatefulSet("velero", "sts-1").StorageClass("storageclass-1").Result(),
@@ -183,7 +183,7 @@ func TestChangeStorageClassActionExecute(t *testing.T) {
name: "when no storage class mappings exist in the plugin config map, the statefulset item is returned as-is",
pvOrPvcOrSTS: builder.ForStatefulSet("velero", "sts-1").StorageClass("storageclass-1").Result(),
configMap: builder.ForConfigMap("velero", "change-storage-classs").
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "true", "velero.io/change-storage-class", "RestoreItemAction")).
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "", "velero.io/change-storage-class", "RestoreItemAction")).
Result(),
want: builder.ForStatefulSet("velero", "sts-1").StorageClass("storageclass-1").Result(),
},
@@ -191,7 +191,7 @@ func TestChangeStorageClassActionExecute(t *testing.T) {
name: "when persistent volume claim has no storage class, the statefulset item is returned as-is",
pvOrPvcOrSTS: builder.ForStatefulSet("velero", "sts-1").Result(),
configMap: builder.ForConfigMap("velero", "change-storage-classs").
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "true", "velero.io/change-storage-class", "RestoreItemAction")).
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "", "velero.io/change-storage-class", "RestoreItemAction")).
Result(),
want: builder.ForStatefulSet("velero", "sts-1").Result(),
},
@@ -199,7 +199,7 @@ func TestChangeStorageClassActionExecute(t *testing.T) {
name: "when statefulset's storage class has no mapping in the config map, the item is returned as-is",
pvOrPvcOrSTS: builder.ForStatefulSet("velero", "sts-1").StorageClass("storageclass-1").Result(),
configMap: builder.ForConfigMap("velero", "change-storage-classs").
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "true", "velero.io/change-storage-class", "RestoreItemAction")).
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "", "velero.io/change-storage-class", "RestoreItemAction")).
Data("storageclass-3", "storageclass-4").
Result(),
want: builder.ForStatefulSet("velero", "sts-1").StorageClass("storageclass-1").Result(),
@@ -208,7 +208,7 @@ func TestChangeStorageClassActionExecute(t *testing.T) {
name: "when statefulset's storage class is mapped to a nonexistent storage class, an error is returned",
pvOrPvcOrSTS: builder.ForStatefulSet("velero", "sts-1").StorageClass("storageclass-1").Result(),
configMap: builder.ForConfigMap("velero", "change-storage-classs").
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "true", "velero.io/change-storage-class", "RestoreItemAction")).
ObjectMeta(builder.WithLabels("velero.io/plugin-config", "", "velero.io/change-storage-class", "RestoreItemAction")).
Data("storageclass-1", "nonexistent-storage-class").
Result(),
wantErr: errors.New("error getting storage class nonexistent-storage-class from API: storageclasses.storage.k8s.io \"nonexistent-storage-class\" not found"),

View File

@@ -27,12 +27,15 @@ import (
k8sfake "sigs.k8s.io/controller-runtime/pkg/client/fake"
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
velerov2alpha1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v2alpha1"
)
func NewFakeControllerRuntimeClientBuilder(t *testing.T) *k8sfake.ClientBuilder {
scheme := runtime.NewScheme()
err := velerov1api.AddToScheme(scheme)
require.NoError(t, err)
err = velerov2alpha1api.AddToScheme(scheme)
require.NoError(t, err)
err = corev1api.AddToScheme(scheme)
require.NoError(t, err)
err = snapshotv1api.AddToScheme(scheme)
@@ -44,6 +47,8 @@ func NewFakeControllerRuntimeClient(t *testing.T, initObjs ...runtime.Object) cl
scheme := runtime.NewScheme()
err := velerov1api.AddToScheme(scheme)
require.NoError(t, err)
err = velerov2alpha1api.AddToScheme(scheme)
require.NoError(t, err)
err = corev1api.AddToScheme(scheme)
require.NoError(t, err)
err = snapshotv1api.AddToScheme(scheme)

View File

@@ -174,6 +174,7 @@ func (sr *shimRepository) NewObjectWriter(ctx context.Context, option object.Wri
opt.Prefix = udmrepo.ID(option.Prefix)
opt.FullPath = ""
opt.AccessMode = udmrepo.ObjectDataAccessModeFile
opt.AsyncWrites = option.AsyncWrites
if strings.HasPrefix(option.Description, "DIR:") {
opt.DataType = udmrepo.ObjectDataTypeMetadata

View File

@@ -94,6 +94,13 @@ spec:
matchLabels:
app: velero
component: server
# Individual object when matched with any of the label selector specified in the set are to be included in the backup. Optional.
# orLabelSelectors as well as labelSelector cannot co-exist, only one of them can be specified in the backup request
orLabelSelectors:
- matchLabels:
app: velero
- matchLabels:
app: data-protection
# Whether to snapshot volumes. Valid values are true, false, and null/unset. If unset, Velero performs snapshots as long as
# a persistent volume provider is configured for Velero.
snapshotVolumes: null

View File

@@ -0,0 +1,109 @@
---
title: "Velero 1.11: New Actions, New Horizons"
excerpt: In this release, we've grown the team and continue to welcome new members to our community.We're thrilled to have such significant contributions from the community and we're proud to deliver Velero 1.11.
author_name: Orlin Vasilev
slug: Velero-1.11
categories: ['velero','release']
image: /img/posts/post-1.11.jpg
# Tag should match author to drive author pages
tags: ['Velero Team', 'Orlin Vasilev', 'Velero Release']
---
We haven't posted for while, but this deserves your attention!
Last week during KubeCon Europe in Amsterdam we released [Velero v1.11](https://github.com/vmware-tanzu/velero/releases/tag/v1.11.0), which brings significant improvements in its functionality, flexibility, and performance. In this blog post, we will discuss the new features and changes that come with Velero v1.11 and how they can benefit users.
The theme of the v1.11 release is most definitely more flexibility, not only with the features added, but also in terms of the Velero contribution, development, and quality assurance processes.
In case you missed it we have new Product Manager - [Pradeep Kumar Chaturvedi](https://github.com/pradeepkchaturvedi) and few new contributors from companies like DELL and Microsoft.
### Full list of changes can be found [here](https://github.com/vmware-tanzu/velero/releases/tag/v1.11.0)
## Release Highlights
### BackupItemAction v2
This feature implements the BackupItemAction v2. BIA v2 has two new methods: Progress() and Cancel() and modifies the Execute() return value.
The API change is needed to facilitate long-running BackupItemAction plugin actions that may not be complete when the Execute() method returns. This will allow long-running BackupItemAction plugin actions to continue in the background while the Velero moves to the following plugin or the next item.
[https://github.com/vmware-tanzu/velero/pull/5442](https://github.com/vmware-tanzu/velero/pull/5442)
### RestoreItemAction v2
This feature implemented the RestoreItemAction v2. RIA v2 has three new methods: Progress(), Cancel(), and AreAdditionalItemsReady(), and it modifies RestoreItemActionExecuteOutput() structure in the RIA return value.
The Progress() and Cancel() methods are needed to facilitate long-running RestoreItemAction plugin actions that may not be complete when the Execute() method returns. This will allow long-running RestoreItemAction plugin actions to continue in the background while the Velero moves to the following plugin or the next item. The AreAdditionalItemsReady() method is needed to allow plugins to tell Velero to wait until the returned additional items have been restored and are ready for use in the cluster before restoring the current item.
[https://github.com/vmware-tanzu/velero/pull/5569](https://github.com/vmware-tanzu/velero/pull/5569)
### Plugin Progress Monitoring
This is intended as a replacement for the previously-approved Upload Progress Monitoring design ([Upload Progress Monitoring](https://github.com/vmware-tanzu/velero/blob/main/design/upload-progress.md)) to expand the supported use cases beyond snapshot upload to include what was previously called Async Backup/Restore Item Actions.
### Flexible resource policy that can filter volumes to skip in the backup
This feature provides a flexible policy to filter volumes in the backup without requiring patching any labels or annotations to the pods or volumes. This policy is configured as k8s ConfigMap and maintained by the users themselves, and it can be extended to more scenarios in the future. By now, the policy rules out volumes from backup depending on the CSI driver, NFS setting, volume size, and StorageClass setting. Please refer to [Resource policies rules](https://velero.io/docs/v1.11/resource-filtering/#resource-policies) for the policy's ConifgMap format. It is not guaranteed to work on unofficial third-party plugins as it may not follow the existing backup workflow code logic of Velero.
### Resource Filters that can distinguish cluster scope and namespace scope resources
This feature adds four new resource filters for backup. The new filters are separated into cluster scope and namespace scope. Before this feature, Velero could not filter cluster scope resources precisely. This feature provides the ability and refactors existing resource filter parameters.
### New parameter in installation to customize the ServiceAccount name
The `velero install` sub-command now includes a new parameter,`--service-account-name`, which allows users to specify the ServiceAccountName for the Velero and node-agent pods. This feature may be particularly useful for users who utilize IRSA (IAM Roles for Service Accounts) in Amazon EKS (Elastic Kubernetes Service)."
### Add a parameter for setting the Velero server connection with the k8s API server's timeout
In Velero, some code pieces need to communicate with the k8s API server. Before v1.11, these code pieces used hard-code timeout settings. This feature adds a resource-timeout parameter in the velero server binary to make it configurable.
### Add resource list in the output of the restore describe command
Before this feature, Velero restore didn't have a restored resources list as the Velero backup. It's not convenient for users to learn what is restored. This feature adds the resources list and the handling result of the resources (including created, updated, failed, and skipped).
### Support JSON format output of backup describe command
Before the Velero v1.11 release, users could not choose Velero's backup describe command's output format. The command output format is friendly for human reading, but it's not a structured output, and it's not easy for other programs to get information from it. Velero v1.11 adds a JSON format output for the backup describe command.
### Refactor controllers with controller-runtime
In v1.11, Backup Controller and Restore controller are refactored with controller-runtime. Till v1.11, all Velero controllers use the controller-runtime framework.
### Runtime and dependencies
To fix CVEs and keep pace with Golang, Velero made changes as follows:
* Bump Golang runtime to v1.19.8.
* Bump several dependent libraries to new versions.
* Compile Restic (v0.15.0) with Golang v1.19.8 instead of packaging the official binary.
## Breaking changes
* The Velero CSI plugin now determines whether to restore Volume's data from snapshots on the restore's restorePVs setting. Before v1.11, the CSI plugin doesn't check the restorePVs parameter setting.
## Limitations/Known issues
* The Flexible resource policy that can filter volumes to skip in the backup is not guaranteed to work on unofficial third-party plugins because the plugins may not follow the existing backup workflow code logic of Velero. The ConfigMap used as the policy is supposed to be maintained by users.
### Improving Developer Experience
As we continue to grow our community of contributors, we want to lower the barrier to entry for making contributions to the Velero project.
Weve made huge improvements to the developer experience during this release cycle by introducing Tilt to the developer workflow.
Using Tilt enables developers to make changes to Velero and its plugins, and have those changes automatically built and deployed to your cluster.
This removes the need for any manual building or pushing of images, and provides a faster and much simpler workflow.
Our Tilt configuration also enables contributors to more easily debug the Velero process using Delve, which has integrations with many editors and IDEs.
If you would like to try it out, please see our [documentation](https://velero.io/docs/v1.11/tilt/).
### Looking Forward
We have more exciting additions and improvements to Velero earmarked for future releases.
For v1.12, we would like to have your input again [here](https://github.com/vmware-tanzu/velero/discussions/6217)
See our [1.12 RoadMap](https://github.com/vmware-tanzu/velero/wiki/1.12-Roadmap) for the complete list.
### Join the Community and Make Velero Better
Velero is better because of our contributors and maintainers.
It is because of you that we can bring great software to the community.
Please join us during our online [community meetings every Tuesday](https://hackmd.io/Jq6F5zqZR7S80CeDWUklkA?view) and catch up with past meetings on YouTube on the [Velero Community Meetings playlist](https://www.youtube.com/watch?v=nc48ocI-6go&list=PL7bmigfV0EqQRysvqvqOtRNk4L5S7uqwM).
You can always find the latest project information at [velero.io](https://velero.io).
Look for issues on GitHub marked ["Good first issue"](https://github.com/vmware-tanzu/velero/issues?q=is%3Aopen+is%3Aissue+label%3A%22Good+first+issue%22) or ["Help wanted"](https://github.com/vmware-tanzu/velero/issues?q=is%3Aopen+is%3Aissue+label%3A%22Help+wanted%22+) if you want to roll up your sleeves and write some code with us.
For opportunities to help and be helped, visit our [Community Support Q&A on GitHub](https://github.com/vmware-tanzu/velero/discussions/categories/community-support-q-a).
You can chat with us on [Kubernetes Slack in the #velero channel](https://kubernetes.slack.com/messages/C6VCGP4MT) and follow us on Twitter at [@projectvelero](https://twitter.com/projectvelero).
Orlin Vasilev
Velero Community Lead
Photo by [Markus Spiske on Unsplash](https://unsplash.com/@markusspiske?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 MiB

View File

@@ -150,7 +150,7 @@ func runBackupDeletionTests(client TestClient, veleroCfg VeleroConfig, backupNam
}
var snapshotCheckPoint SnapshotCheckPoint
if useVolumeSnapshots {
snapshotCheckPoint, err = GetSnapshotCheckPoint(client, veleroCfg, 2, deletionTest, backupName, KibishiiPodNameList)
snapshotCheckPoint, err = GetSnapshotCheckPoint(client, veleroCfg, 2, deletionTest, backupName, KibishiiPVCNameList)
Expect(err).NotTo(HaveOccurred(), "Fail to get Azure CSI snapshot checkpoint")
err = SnapshotsShouldBeCreatedInCloud(veleroCfg.CloudProvider,
veleroCfg.CloudCredentialsFile, veleroCfg.BSLBucket, bslConfig,

View File

@@ -51,7 +51,7 @@ func (b *TTL) Init() {
b.testNS = "backup-ttl-test-" + UUIDgen.String()
b.backupName = "backup-ttl-test-" + UUIDgen.String()
b.restoreName = "restore-ttl-test-" + UUIDgen.String()
b.ttl = 20 * time.Minute
b.ttl = 10 * time.Minute
}
@@ -128,7 +128,7 @@ func TTLTest() {
test.testNS, 2)).To(Succeed())
})
}
snapshotCheckPoint, err = GetSnapshotCheckPoint(client, veleroCfg, 2, test.testNS, test.backupName, KibishiiPodNameList)
snapshotCheckPoint, err = GetSnapshotCheckPoint(client, veleroCfg, 2, test.testNS, test.backupName, KibishiiPVCNameList)
Expect(err).NotTo(HaveOccurred(), "Fail to get Azure CSI snapshot checkpoint")
Expect(SnapshotsShouldBeCreatedInCloud(veleroCfg.CloudProvider,

View File

@@ -100,7 +100,7 @@ func APIGropuVersionsTest() {
DeleteBackups(context.Background(), *veleroCfg.ClientToInstallVelero)
})
if veleroCfg.InstallVelero {
By("Uninstall Velero", func() {
By("Uninstall Velero in api group version case", func() {
Expect(VeleroUninstall(ctx, veleroCfg.VeleroCLI, veleroCfg.VeleroNamespace)).NotTo(HaveOccurred())
})
}

View File

@@ -23,12 +23,16 @@ type NamespaceMapping struct {
const NamespaceBaseName string = "ns-mp-"
var OneNamespaceMappingResticTest func() = TestFunc(&NamespaceMapping{TestCase: TestCase{NSBaseName: NamespaceBaseName, NSIncluded: &[]string{NamespaceBaseName + "1"}, UseVolumeSnapshots: false}})
var MultiNamespacesMappingResticTest func() = TestFunc(&NamespaceMapping{TestCase: TestCase{NSBaseName: NamespaceBaseName, NSIncluded: &[]string{NamespaceBaseName + "2", NamespaceBaseName + "3"}, UseVolumeSnapshots: false}})
var OneNamespaceMappingSnapshotTest func() = TestFunc(&NamespaceMapping{TestCase: TestCase{NSBaseName: NamespaceBaseName, NSIncluded: &[]string{NamespaceBaseName + "4"}, UseVolumeSnapshots: true}})
var MultiNamespacesMappingSnapshotTest func() = TestFunc(&NamespaceMapping{TestCase: TestCase{NSBaseName: NamespaceBaseName, NSIncluded: &[]string{NamespaceBaseName + "5", NamespaceBaseName + "6"}, UseVolumeSnapshots: true}})
var OneNamespaceMappingResticTest func() = TestFunc(&NamespaceMapping{TestCase: TestCase{NamespacesTotal: 1, UseVolumeSnapshots: false}})
var MultiNamespacesMappingResticTest func() = TestFunc(&NamespaceMapping{TestCase: TestCase{NamespacesTotal: 2, UseVolumeSnapshots: false}})
var OneNamespaceMappingSnapshotTest func() = TestFunc(&NamespaceMapping{TestCase: TestCase{NamespacesTotal: 1, UseVolumeSnapshots: true}})
var MultiNamespacesMappingSnapshotTest func() = TestFunc(&NamespaceMapping{TestCase: TestCase{NamespacesTotal: 2, UseVolumeSnapshots: true}})
func (n *NamespaceMapping) Init() error {
n.TestCase.Init()
n.CaseBaseName = "ns-mp-" + n.UUIDgen
n.BackupName = "backup-" + n.CaseBaseName
n.RestoreName = "restore-" + n.CaseBaseName
n.VeleroCfg = VeleroCfg
n.Client = *n.VeleroCfg.ClientToInstallVelero
n.VeleroCfg.UseVolumeSnapshots = n.UseVolumeSnapshots
@@ -38,30 +42,25 @@ func (n *NamespaceMapping) Init() error {
if n.UseVolumeSnapshots {
backupType = "snapshot"
}
var mappedNS string
var mappedNSList []string
n.NSIncluded = &[]string{}
for nsNum := 0; nsNum < n.NamespacesTotal; nsNum++ {
createNSName := fmt.Sprintf("%s-%00000d", n.CaseBaseName, nsNum)
*n.NSIncluded = append(*n.NSIncluded, createNSName)
mappedNS = mappedNS + createNSName + ":" + createNSName + "-mapped"
mappedNSList = append(mappedNSList, createNSName+"-mapped")
mappedNS = mappedNS + ","
}
mappedNS = strings.TrimRightFunc(mappedNS, func(r rune) bool {
return r == ','
})
n.TestMsg = &TestMSG{
Desc: fmt.Sprintf("Restore namespace %s with namespace mapping by %s test", *n.NSIncluded, backupType),
FailedMSG: "Failed to restore with namespace mapping",
Text: fmt.Sprintf("should restore namespace %s with namespace mapping by %s", *n.NSIncluded, backupType),
}
return nil
}
func (n *NamespaceMapping) StartRun() error {
var mappedNS string
var mappedNSList []string
for index, ns := range *n.NSIncluded {
mappedNS = mappedNS + ns + ":" + ns + UUIDgen.String()
mappedNSList = append(mappedNSList, ns+UUIDgen.String())
if index+1 != len(*n.NSIncluded) {
mappedNS = mappedNS + ","
}
n.BackupName = n.BackupName + ns
n.RestoreName = n.RestoreName + ns
}
n.BackupName = n.BackupName + UUIDgen.String()
n.RestoreName = n.RestoreName + UUIDgen.String()
n.MappedNamespaceList = mappedNSList
fmt.Println(mappedNSList)
n.BackupArgs = []string{
@@ -81,16 +80,16 @@ func (n *NamespaceMapping) StartRun() error {
}
return nil
}
func (n *NamespaceMapping) CreateResources() error {
ctx, ctxCancel := context.WithTimeout(context.Background(), 60*time.Minute)
defer ctxCancel()
n.Ctx, n.CtxCancel = context.WithTimeout(context.Background(), 60*time.Minute)
for index, ns := range *n.NSIncluded {
n.kibishiiData.Levels = len(*n.NSIncluded) + index
By(fmt.Sprintf("Creating namespaces ...%s\n", ns), func() {
Expect(CreateNamespace(ctx, n.Client, ns)).To(Succeed(), fmt.Sprintf("Failed to create namespace %s", ns))
Expect(CreateNamespace(n.Ctx, n.Client, ns)).To(Succeed(), fmt.Sprintf("Failed to create namespace %s", ns))
})
By("Deploy sample workload of Kibishii", func() {
Expect(KibishiiPrepareBeforeBackup(ctx, n.Client, VeleroCfg.CloudProvider,
Expect(KibishiiPrepareBeforeBackup(n.Ctx, n.Client, VeleroCfg.CloudProvider,
ns, VeleroCfg.RegistryCredentialFile, VeleroCfg.Features,
VeleroCfg.KibishiiDirectory, false, n.kibishiiData)).To(Succeed())
})
@@ -99,19 +98,33 @@ func (n *NamespaceMapping) CreateResources() error {
}
func (n *NamespaceMapping) Verify() error {
ctx, ctxCancel := context.WithTimeout(context.Background(), 60*time.Minute)
defer ctxCancel()
for index, ns := range n.MappedNamespaceList {
n.kibishiiData.Levels = len(*n.NSIncluded) + index
By(fmt.Sprintf("Verify workload %s after restore ", ns), func() {
Expect(KibishiiVerifyAfterRestore(n.Client, ns,
ctx, n.kibishiiData)).To(Succeed(), "Fail to verify workload after restore")
n.Ctx, n.kibishiiData)).To(Succeed(), "Fail to verify workload after restore")
})
}
for _, ns := range *n.NSIncluded {
By(fmt.Sprintf("Verify namespace %s for backup is no longer exist after restore with namespace mapping", ns), func() {
Expect(NamespaceShouldNotExist(ctx, n.Client, ns)).To(Succeed())
Expect(NamespaceShouldNotExist(n.Ctx, n.Client, ns)).To(Succeed())
})
}
return nil
}
func (n *NamespaceMapping) Clean() error {
if !n.VeleroCfg.Debug {
if err := DeleteStorageClass(context.Background(), n.Client, "kibishii-storage-class"); err != nil {
return err
}
for _, ns := range n.MappedNamespaceList {
if err := DeleteNamespace(context.Background(), n.Client, ns, false); err != nil {
return err
}
}
return n.GetTestCase().Clean()
}
return nil
}

View File

@@ -3,6 +3,7 @@ package basic
import (
"context"
"fmt"
"strings"
"time"
. "github.com/onsi/ginkgo"
@@ -20,40 +21,42 @@ import (
type NodePort struct {
TestCase
replica int32
labels map[string]string
containers *[]v1.Container
serviceName string
serviceSpec *v1.ServiceSpec
namespaceToCollision []string
nodePort int32
namespaceToCollision string
namespace string
}
const NodeportBaseName string = "nodeport-"
var NodePortTest func() = TestFunc(&NodePort{namespace: NodeportBaseName + "1", TestCase: TestCase{NSBaseName: NodeportBaseName}})
var NodePortTest func() = TestFunc(&NodePort{})
func (n *NodePort) Init() error {
n.TestCase.Init()
n.CaseBaseName = NodeportBaseName + n.UUIDgen
n.BackupName = "backup-" + n.CaseBaseName
n.RestoreName = "restore-" + n.CaseBaseName
n.serviceName = "nginx-service-" + n.CaseBaseName
n.VeleroCfg = VeleroCfg
n.Client = *n.VeleroCfg.ClientToInstallVelero
n.NSBaseName = NodeportBaseName
n.NamespacesTotal = 1
n.TestMsg = &TestMSG{
Desc: fmt.Sprintf("Nodeport preservation"),
Desc: "Nodeport preservation",
FailedMSG: "Failed to restore with nodeport preservation",
Text: fmt.Sprintf("Nodeport can be preserved or omit during restore"),
Text: "Nodeport can be preserved or omit during restore",
}
n.labels = map[string]string{"app": "nginx"}
n.NSIncluded = &[]string{}
for nsNum := 0; nsNum < n.NamespacesTotal; nsNum++ {
createNSName := fmt.Sprintf("%s-%00000d", n.CaseBaseName, nsNum)
n.namespaceToCollision = append(n.namespaceToCollision, createNSName+"tmp")
*n.NSIncluded = append(*n.NSIncluded, createNSName)
}
n.BackupName = "backup-nodeport-" + UUIDgen.String()
n.RestoreName = "restore-" + UUIDgen.String()
n.serviceName = "nginx-service-" + UUIDgen.String()
n.labels = map[string]string{"app": "nginx"}
return nil
}
func (n *NodePort) StartRun() error {
n.BackupArgs = []string{
"create", "--namespace", VeleroCfg.VeleroNamespace, "backup", n.BackupName,
"--include-namespaces", n.namespace, "--wait",
"--include-namespaces", strings.Join(*n.NSIncluded, ","), "--wait",
}
n.RestoreArgs = []string{
"create", "--namespace", VeleroCfg.VeleroNamespace, "restore",
@@ -63,47 +66,45 @@ func (n *NodePort) StartRun() error {
return nil
}
func (n *NodePort) CreateResources() error {
ctx, ctxCancel := context.WithTimeout(context.Background(), 60*time.Minute)
defer ctxCancel()
n.Ctx, n.CtxCancel = context.WithTimeout(context.Background(), 60*time.Minute)
By(fmt.Sprintf("Creating service %s in namespaces %s ......\n", n.serviceName, n.namespace), func() {
Expect(CreateNamespace(ctx, n.Client, n.namespace)).To(Succeed(), fmt.Sprintf("Failed to create namespace %s", n.namespace))
Expect(createServiceWithNodeport(ctx, n.Client, n.namespace, n.serviceName, n.labels, 0)).To(Succeed(), fmt.Sprintf("Failed to create service %s", n.serviceName))
service, err := GetService(ctx, n.Client, n.namespace, n.serviceName)
Expect(err).To(Succeed())
Expect(len(service.Spec.Ports)).To(Equal(1))
n.nodePort = service.Spec.Ports[0].NodePort
_, err = GetAllService(ctx)
Expect(err).To(Succeed(), "fail to get service")
})
for _, ns := range *n.NSIncluded {
By(fmt.Sprintf("Creating service %s in namespaces %s ......\n", n.serviceName, ns), func() {
Expect(CreateNamespace(n.Ctx, n.Client, ns)).To(Succeed(), fmt.Sprintf("Failed to create namespace %s", ns))
Expect(createServiceWithNodeport(n.Ctx, n.Client, ns, n.serviceName, n.labels, 0)).To(Succeed(), fmt.Sprintf("Failed to create service %s", n.serviceName))
service, err := GetService(n.Ctx, n.Client, ns, n.serviceName)
Expect(err).To(Succeed())
Expect(len(service.Spec.Ports)).To(Equal(1))
n.nodePort = service.Spec.Ports[0].NodePort
_, err = GetAllService(n.Ctx)
Expect(err).To(Succeed(), "fail to get service")
})
}
return nil
}
func (n *NodePort) Destroy() error {
ctx, ctxCancel := context.WithTimeout(context.Background(), 60*time.Minute)
defer ctxCancel()
By(fmt.Sprintf("Start to destroy namespace %s......", n.NSBaseName), func() {
Expect(CleanupNamespacesWithPoll(ctx, n.Client, NodeportBaseName)).To(Succeed(),
fmt.Sprintf("Failed to delete namespace %s", n.NSBaseName))
Expect(WaitForServiceDelete(n.Client, n.namespace, n.serviceName, false)).To(Succeed(), "fail to delete service")
_, err := GetAllService(ctx)
Expect(err).To(Succeed(), "fail to get service")
})
for i, ns := range *n.NSIncluded {
By(fmt.Sprintf("Start to destroy namespace %s......", n.CaseBaseName), func() {
Expect(CleanupNamespacesWithPoll(n.Ctx, n.Client, NodeportBaseName)).To(Succeed(),
fmt.Sprintf("Failed to delete namespace %s", n.CaseBaseName))
Expect(WaitForServiceDelete(n.Client, ns, n.serviceName, false)).To(Succeed(), "fail to delete service")
_, err := GetAllService(n.Ctx)
Expect(err).To(Succeed(), "fail to get service")
})
n.namespaceToCollision = NodeportBaseName + "tmp"
By(fmt.Sprintf("Creating a new service which has the same nodeport as backed up service has in a new namespaces for nodeport collision ...%s\n", n.namespaceToCollision), func() {
Expect(CreateNamespace(ctx, n.Client, n.namespaceToCollision)).To(Succeed(), fmt.Sprintf("Failed to create namespace %s", n.namespaceToCollision))
Expect(createServiceWithNodeport(ctx, n.Client, n.namespaceToCollision, n.serviceName, n.labels, n.nodePort)).To(Succeed(), fmt.Sprintf("Failed to create service %s", n.serviceName))
_, err := GetAllService(ctx)
Expect(err).To(Succeed(), "fail to get service")
})
By(fmt.Sprintf("Creating a new service which has the same nodeport as backed up service has in a new namespaces for nodeport collision ...%s\n", n.namespaceToCollision[i]), func() {
Expect(CreateNamespace(n.Ctx, n.Client, n.namespaceToCollision[i])).To(Succeed(), fmt.Sprintf("Failed to create namespace %s", n.namespaceToCollision[i]))
Expect(createServiceWithNodeport(n.Ctx, n.Client, n.namespaceToCollision[i], n.serviceName, n.labels, n.nodePort)).To(Succeed(), fmt.Sprintf("Failed to create service %s", n.serviceName))
_, err := GetAllService(n.Ctx)
Expect(err).To(Succeed(), "fail to get service")
})
}
return nil
}
func (n *NodePort) Restore() error {
ctx, ctxCancel := context.WithTimeout(context.Background(), 60*time.Minute)
defer ctxCancel()
index := 4
restoreName1 := n.RestoreName + "-1"
restoreName2 := restoreName1 + "-1"
@@ -112,7 +113,7 @@ func (n *NodePort) Restore() error {
args = append(args[:index], append([]string{n.RestoreName}, args[index:]...)...)
args = append(args, "--preserve-nodeports=true")
By(fmt.Sprintf("Start to restore %s with nodeports preservation when port %d is already occupied by other service", n.RestoreName, n.nodePort), func() {
Expect(VeleroRestoreExec(ctx, n.VeleroCfg.VeleroCLI,
Expect(VeleroRestoreExec(n.Ctx, n.VeleroCfg.VeleroCLI,
n.VeleroCfg.VeleroNamespace, n.RestoreName,
args, velerov1api.RestorePhasePartiallyFailed)).To(
Succeed(),
@@ -127,44 +128,45 @@ func (n *NodePort) Restore() error {
args = append(args[:index], append([]string{restoreName1}, args[index:]...)...)
args = append(args, "--preserve-nodeports=false")
By(fmt.Sprintf("Start to restore %s without nodeports preservation ......", restoreName1), func() {
Expect(VeleroRestoreExec(ctx, n.VeleroCfg.VeleroCLI, n.VeleroCfg.VeleroNamespace,
Expect(VeleroRestoreExec(n.Ctx, n.VeleroCfg.VeleroCLI, n.VeleroCfg.VeleroNamespace,
restoreName1, args, velerov1api.RestorePhaseCompleted)).To(Succeed(), func() string {
RunDebug(context.Background(), n.VeleroCfg.VeleroCLI, n.VeleroCfg.VeleroNamespace, "", restoreName1)
return "Fail to restore workload"
})
})
By(fmt.Sprintf("Delete service %s by deleting namespace %s", n.serviceName, n.namespace), func() {
service, err := GetService(ctx, n.Client, n.namespace, n.serviceName)
Expect(err).To(Succeed())
Expect(len(service.Spec.Ports)).To(Equal(1))
fmt.Println(service.Spec.Ports)
Expect(DeleteNamespace(ctx, n.Client, n.namespace, true)).To(Succeed())
})
By(fmt.Sprintf("Start to delete service %s in namespace %s ......", n.serviceName, n.namespaceToCollision), func() {
Expect(WaitForServiceDelete(n.Client, n.namespaceToCollision, n.serviceName, true)).To(Succeed(), "fail to delete service")
_, err := GetAllService(ctx)
Expect(err).To(Succeed(), "fail to get service")
})
args = n.RestoreArgs
args = append(args[:index], append([]string{restoreName2}, args[index:]...)...)
args = append(args, "--preserve-nodeports=true")
By(fmt.Sprintf("Start to restore %s with nodeports preservation ......", restoreName2), func() {
Expect(VeleroRestoreExec(ctx, n.VeleroCfg.VeleroCLI, n.VeleroCfg.VeleroNamespace,
restoreName2, args, velerov1api.RestorePhaseCompleted)).To(Succeed(), func() string {
RunDebug(context.Background(), n.VeleroCfg.VeleroCLI, n.VeleroCfg.VeleroNamespace, "", restoreName2)
return "Fail to restore workload"
for i, ns := range *n.NSIncluded {
By(fmt.Sprintf("Delete service %s by deleting namespace %s", n.serviceName, ns), func() {
service, err := GetService(n.Ctx, n.Client, ns, n.serviceName)
Expect(err).To(Succeed())
Expect(len(service.Spec.Ports)).To(Equal(1))
fmt.Println(service.Spec.Ports)
Expect(DeleteNamespace(n.Ctx, n.Client, ns, true)).To(Succeed())
})
})
By(fmt.Sprintf("Verify service %s was restore successfully with the origin nodeport.", n.namespace), func() {
service, err := GetService(ctx, n.Client, n.namespace, n.serviceName)
Expect(err).To(Succeed())
Expect(len(service.Spec.Ports)).To(Equal(1))
Expect(service.Spec.Ports[0].NodePort).To(Equal(n.nodePort))
})
By(fmt.Sprintf("Start to delete service %s in namespace %s ......", n.serviceName, n.namespaceToCollision[i]), func() {
Expect(WaitForServiceDelete(n.Client, n.namespaceToCollision[i], n.serviceName, true)).To(Succeed(), "fail to delete service")
_, err := GetAllService(n.Ctx)
Expect(err).To(Succeed(), "fail to get service")
})
args = n.RestoreArgs
args = append(args[:index], append([]string{restoreName2}, args[index:]...)...)
args = append(args, "--preserve-nodeports=true")
By(fmt.Sprintf("Start to restore %s with nodeports preservation ......", restoreName2), func() {
Expect(VeleroRestoreExec(n.Ctx, n.VeleroCfg.VeleroCLI, n.VeleroCfg.VeleroNamespace,
restoreName2, args, velerov1api.RestorePhaseCompleted)).To(Succeed(), func() string {
RunDebug(context.Background(), n.VeleroCfg.VeleroCLI, n.VeleroCfg.VeleroNamespace, "", restoreName2)
return "Fail to restore workload"
})
})
By(fmt.Sprintf("Verify service %s was restore successfully with the origin nodeport.", ns), func() {
service, err := GetService(n.Ctx, n.Client, ns, n.serviceName)
Expect(err).To(Succeed())
Expect(len(service.Spec.Ports)).To(Equal(1))
Expect(service.Spec.Ports[0].NodePort).To(Equal(n.nodePort))
})
}
return nil
}

View File

@@ -31,24 +31,22 @@ type PVCSelectedNodeChanging struct {
ann string
}
const PSNCBaseName string = "psnc-"
var PVCSelectedNodeChangingTest func() = TestFunc(&PVCSelectedNodeChanging{
namespace: PSNCBaseName + "1", TestCase: TestCase{NSBaseName: PSNCBaseName}})
var PVCSelectedNodeChangingTest func() = TestFunc(&PVCSelectedNodeChanging{})
func (p *PVCSelectedNodeChanging) Init() error {
p.TestCase.Init()
p.CaseBaseName = "psnc-" + p.UUIDgen
p.namespace = p.CaseBaseName
p.mappedNS = p.namespace + "-mapped"
p.VeleroCfg = VeleroCfg
p.Client = *p.VeleroCfg.ClientToInstallVelero
p.NSBaseName = PSNCBaseName
p.namespace = p.NSBaseName + UUIDgen.String()
p.mappedNS = p.namespace + "-mapped"
p.TestMsg = &TestMSG{
Desc: "Changing PVC node selector",
FailedMSG: "Failed to changing PVC node selector",
Text: "Change node selectors of persistent volume claims during restores",
}
p.BackupName = "backup-sc-" + UUIDgen.String()
p.RestoreName = "restore-" + UUIDgen.String()
p.BackupName = "backup-" + p.CaseBaseName
p.RestoreName = "restore-" + p.CaseBaseName
p.labels = map[string]string{"velero.io/plugin-config": "",
"velero.io/change-pvc-node-selector": "RestoreItemAction"}
p.configmaptName = "change-pvc-node-selector-config"
@@ -56,12 +54,6 @@ func (p *PVCSelectedNodeChanging) Init() error {
p.podName = "pod-1"
p.pvcName = "pvc-1"
p.ann = "volume.kubernetes.io/selected-node"
return nil
}
func (p *PVCSelectedNodeChanging) StartRun() error {
p.BackupName = p.BackupName + "backup-" + UUIDgen.String()
p.RestoreName = p.RestoreName + "restore-" + UUIDgen.String()
p.BackupArgs = []string{
"create", "--namespace", VeleroCfg.VeleroNamespace, "backup", p.BackupName,
"--include-namespaces", p.namespace,
@@ -73,14 +65,16 @@ func (p *PVCSelectedNodeChanging) StartRun() error {
}
return nil
}
func (p *PVCSelectedNodeChanging) CreateResources() error {
p.Ctx, p.CtxCancel = context.WithTimeout(context.Background(), 60*time.Minute)
By(fmt.Sprintf("Create namespace %s", p.namespace), func() {
Expect(CreateNamespace(context.Background(), p.Client, p.namespace)).To(Succeed(),
Expect(CreateNamespace(p.Ctx, p.Client, p.namespace)).To(Succeed(),
fmt.Sprintf("Failed to create namespace %s", p.namespace))
})
By(fmt.Sprintf("Create pod %s in namespace %s", p.podName, p.namespace), func() {
nodeNameList, err := GetWorkerNodes(context.Background())
nodeNameList, err := GetWorkerNodes(p.Ctx)
Expect(err).To(Succeed())
for _, nodeName := range nodeNameList {
p.oldNodeName = nodeName
@@ -88,14 +82,14 @@ func (p *PVCSelectedNodeChanging) CreateResources() error {
pvcAnn := map[string]string{p.ann: nodeName}
_, err := CreatePod(p.Client, p.namespace, p.podName, "default", p.pvcName, []string{p.volume}, pvcAnn, nil)
Expect(err).To(Succeed())
err = WaitForPods(context.Background(), p.Client, p.namespace, []string{p.podName})
err = WaitForPods(p.Ctx, p.Client, p.namespace, []string{p.podName})
Expect(err).To(Succeed())
break
}
})
By("Prepare ConfigMap data", func() {
nodeNameList, err := GetWorkerNodes(context.Background())
nodeNameList, err := GetWorkerNodes(p.Ctx)
Expect(err).To(Succeed())
Expect(len(nodeNameList) > 2).To(Equal(true))
for _, nodeName := range nodeNameList {
@@ -116,18 +110,16 @@ func (p *PVCSelectedNodeChanging) CreateResources() error {
}
func (p *PVCSelectedNodeChanging) Destroy() error {
By(fmt.Sprintf("Start to destroy namespace %s......", p.NSBaseName), func() {
Expect(CleanupNamespacesWithPoll(context.Background(), p.Client, p.NSBaseName)).To(Succeed(),
fmt.Sprintf("Failed to delete namespace %s", p.NSBaseName))
By(fmt.Sprintf("Start to destroy namespace %s......", p.CaseBaseName), func() {
Expect(CleanupNamespacesWithPoll(p.Ctx, p.Client, p.CaseBaseName)).To(Succeed(),
fmt.Sprintf("Failed to delete namespace %s", p.CaseBaseName))
})
return nil
}
func (p *PVCSelectedNodeChanging) Restore() error {
ctx, ctxCancel := context.WithTimeout(context.Background(), 60*time.Minute)
defer ctxCancel()
By(fmt.Sprintf("Start to restore %s .....", p.RestoreName), func() {
Expect(VeleroRestoreExec(ctx, p.VeleroCfg.VeleroCLI,
Expect(VeleroRestoreExec(p.Ctx, p.VeleroCfg.VeleroCLI,
p.VeleroCfg.VeleroNamespace, p.RestoreName,
p.RestoreArgs, velerov1api.RestorePhaseCompleted)).To(
Succeed(),
@@ -136,19 +128,29 @@ func (p *PVCSelectedNodeChanging) Restore() error {
p.VeleroCfg.VeleroNamespace, "", p.RestoreName)
return "Fail to restore workload"
})
err := WaitForPods(ctx, p.Client, p.mappedNS, []string{p.podName})
err := WaitForPods(p.Ctx, p.Client, p.mappedNS, []string{p.podName})
Expect(err).To(Succeed())
})
return nil
}
func (p *PVCSelectedNodeChanging) Verify() error {
By(fmt.Sprintf("PVC selected node should be %s", p.newNodeName), func() {
pvcNameList, err := GetPvcByPodName(context.Background(), p.mappedNS, p.pvcName)
pvcNameList, err := GetPvcByPodName(p.Ctx, p.mappedNS, p.pvcName)
Expect(err).To(Succeed())
Expect(len(pvcNameList)).Should(Equal(1))
pvc, err := GetPVC(context.Background(), p.Client, p.mappedNS, pvcNameList[0])
pvc, err := GetPVC(p.Ctx, p.Client, p.mappedNS, pvcNameList[0])
Expect(err).To(Succeed())
Expect(pvc.Annotations[p.ann]).To(Equal(p.newNodeName))
})
return nil
}
func (p *PVCSelectedNodeChanging) Clean() error {
if !p.VeleroCfg.Debug {
p.TestCase.Clean()
By(fmt.Sprintf("Clean namespace with prefix %s after test", p.mappedNS), func() {
CleanupNamespaces(p.Ctx, p.Client, p.mappedNS)
})
}
return nil
}

View File

@@ -19,11 +19,9 @@ package basic
import (
"context"
"fmt"
"math/rand"
"strings"
"time"
"github.com/google/uuid"
"github.com/pkg/errors"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -40,11 +38,11 @@ type MultiNSBackup struct {
}
func (m *MultiNSBackup) Init() error {
rand.Seed(time.Now().UnixNano())
UUIDgen, _ = uuid.NewRandom()
m.BackupName = "backup-" + UUIDgen.String()
m.RestoreName = "restore-" + UUIDgen.String()
m.NSBaseName = "nstest-" + UUIDgen.String()
m.TestCase.Init()
m.CaseBaseName = "nstest-" + m.UUIDgen
m.BackupName = "backup-" + m.CaseBaseName
m.RestoreName = "restore-" + m.CaseBaseName
m.VeleroCfg = VeleroCfg
m.Client = *m.VeleroCfg.ClientToInstallVelero
m.NSExcluded = &[]string{}
@@ -64,10 +62,7 @@ func (m *MultiNSBackup) Init() error {
FailedMSG: "Failed to successfully backup and restore multiple namespaces",
}
}
return nil
}
func (m *MultiNSBackup) StartRun() error {
// Currently it's hard to build a large list of namespaces to include and wildcards do not work so instead
// we will exclude all of the namespaces that existed prior to the test from the backup
namespaces, err := m.Client.ClientGo.CoreV1().Namespaces().List(context.Background(), v1.ListOptions{})
@@ -93,15 +88,14 @@ func (m *MultiNSBackup) StartRun() error {
}
func (m *MultiNSBackup) CreateResources() error {
ctx, ctxCancel := context.WithTimeout(context.Background(), 60*time.Minute)
defer ctxCancel()
m.Ctx, m.CtxCancel = context.WithTimeout(context.Background(), m.TimeoutDuration)
fmt.Printf("Creating namespaces ...\n")
labels := map[string]string{
"ns-test": "true",
}
for nsNum := 0; nsNum < m.NamespacesTotal; nsNum++ {
createNSName := fmt.Sprintf("%s-%00000d", m.NSBaseName, nsNum)
if err := CreateNamespaceWithLabel(ctx, m.Client, createNSName, labels); err != nil {
createNSName := fmt.Sprintf("%s-%00000d", m.CaseBaseName, nsNum)
if err := CreateNamespaceWithLabel(m.Ctx, m.Client, createNSName, labels); err != nil {
return errors.Wrapf(err, "Failed to create namespace %s", createNSName)
}
}
@@ -109,12 +103,10 @@ func (m *MultiNSBackup) CreateResources() error {
}
func (m *MultiNSBackup) Verify() error {
ctx, ctxCancel := context.WithTimeout(context.Background(), m.TimeoutDuration)
defer ctxCancel()
// Verify that we got back all of the namespaces we created
for nsNum := 0; nsNum < m.NamespacesTotal; nsNum++ {
checkNSName := fmt.Sprintf("%s-%00000d", m.NSBaseName, nsNum)
checkNS, err := GetNamespace(ctx, m.Client, checkNSName)
checkNSName := fmt.Sprintf("%s-%00000d", m.CaseBaseName, nsNum)
checkNS, err := GetNamespace(m.Ctx, m.Client, checkNSName)
if err != nil {
return errors.Wrapf(err, "Could not retrieve test namespace %s", checkNSName)
} else if checkNS.Name != checkNSName {
@@ -125,11 +117,9 @@ func (m *MultiNSBackup) Verify() error {
}
func (m *MultiNSBackup) Destroy() error {
ctx, ctxCancel := context.WithTimeout(context.Background(), 60*time.Minute)
defer ctxCancel()
err := CleanupNamespaces(ctx, m.Client, m.NSBaseName)
err := CleanupNamespaces(m.Ctx, m.Client, m.CaseBaseName)
if err != nil {
return errors.Wrap(err, "Could cleanup retrieve namespaces")
}
return WaitAllSelectedNSDeleted(ctx, m.Client, "ns-test=true")
return WaitAllSelectedNSDeleted(m.Ctx, m.Client, "ns-test=true")
}

View File

@@ -19,11 +19,9 @@ package basic
import (
"context"
"fmt"
"math/rand"
"strings"
"time"
"github.com/google/uuid"
"github.com/pkg/errors"
. "github.com/vmware-tanzu/velero/test/e2e"
@@ -36,17 +34,17 @@ type NSAnnotationCase struct {
}
func (n *NSAnnotationCase) Init() error {
rand.Seed(time.Now().UnixNano())
UUIDgen, _ = uuid.NewRandom()
n.BackupName = "backup-namespace-annotations" + UUIDgen.String()
n.RestoreName = "restore-namespace-annotations" + UUIDgen.String()
n.NSBaseName = "namespace-annotations-" + UUIDgen.String()
n.TestCase.Init()
n.CaseBaseName = "namespace-annotations-" + n.UUIDgen
n.BackupName = "backup-" + n.CaseBaseName
n.RestoreName = "restore-" + n.CaseBaseName
n.NamespacesTotal = 1
n.NSIncluded = &[]string{}
n.VeleroCfg = VeleroCfg
n.Client = *n.VeleroCfg.ClientToInstallVelero
for nsNum := 0; nsNum < n.NamespacesTotal; nsNum++ {
createNSName := fmt.Sprintf("%s-%00000d", n.NSBaseName, nsNum)
createNSName := fmt.Sprintf("%s-%00000d", n.CaseBaseName, nsNum)
*n.NSIncluded = append(*n.NSIncluded, createNSName)
}
n.TestMsg = &TestMSG{
@@ -68,12 +66,11 @@ func (n *NSAnnotationCase) Init() error {
}
func (n *NSAnnotationCase) CreateResources() error {
ctx, ctxCancel := context.WithTimeout(context.Background(), 60*time.Minute)
defer ctxCancel()
n.Ctx, n.CtxCancel = context.WithTimeout(context.Background(), 60*time.Minute)
for nsNum := 0; nsNum < n.NamespacesTotal; nsNum++ {
createNSName := fmt.Sprintf("%s-%00000d", n.NSBaseName, nsNum)
createAnnotationName := fmt.Sprintf("annotation-%s-%00000d", n.NSBaseName, nsNum)
if err := CreateNamespaceWithAnnotation(ctx, n.Client, createNSName, map[string]string{"testAnnotation": createAnnotationName}); err != nil {
createNSName := fmt.Sprintf("%s-%00000d", n.CaseBaseName, nsNum)
createAnnotationName := fmt.Sprintf("annotation-%s-%00000d", n.CaseBaseName, nsNum)
if err := CreateNamespaceWithAnnotation(n.Ctx, n.Client, createNSName, map[string]string{"testAnnotation": createAnnotationName}); err != nil {
return errors.Wrapf(err, "Failed to create namespace %s", createNSName)
}
}
@@ -81,12 +78,10 @@ func (n *NSAnnotationCase) CreateResources() error {
}
func (n *NSAnnotationCase) Verify() error {
ctx, ctxCancel := context.WithTimeout(context.Background(), 60*time.Minute)
defer ctxCancel()
for nsNum := 0; nsNum < n.NamespacesTotal; nsNum++ {
checkNSName := fmt.Sprintf("%s-%00000d", n.NSBaseName, nsNum)
checkAnnoName := fmt.Sprintf("annotation-%s-%00000d", n.NSBaseName, nsNum)
checkNS, err := GetNamespace(ctx, n.Client, checkNSName)
checkNSName := fmt.Sprintf("%s-%00000d", n.CaseBaseName, nsNum)
checkAnnoName := fmt.Sprintf("annotation-%s-%00000d", n.CaseBaseName, nsNum)
checkNS, err := GetNamespace(n.Ctx, n.Client, checkNSName)
if err != nil {
return errors.Wrapf(err, "Could not retrieve test namespace %s", checkNSName)

View File

@@ -35,11 +35,9 @@ package basic
import (
"context"
"fmt"
"math/rand"
"strings"
"time"
"github.com/google/uuid"
"github.com/pkg/errors"
. "github.com/vmware-tanzu/velero/test/e2e"
@@ -52,15 +50,14 @@ type RBACCase struct {
}
func (r *RBACCase) Init() error {
rand.Seed(time.Now().UnixNano())
UUIDgen, _ = uuid.NewRandom()
r.BackupName = "backup-rbac" + UUIDgen.String()
r.RestoreName = "restore-rbac" + UUIDgen.String()
r.NSBaseName = "rabc-" + UUIDgen.String()
r.TestCase.Init()
r.CaseBaseName = "rabc-" + r.UUIDgen
r.BackupName = "backup-" + r.CaseBaseName
r.RestoreName = "restore-" + r.CaseBaseName
r.NamespacesTotal = 1
r.NSIncluded = &[]string{}
for nsNum := 0; nsNum < r.NamespacesTotal; nsNum++ {
createNSName := fmt.Sprintf("%s-%00000d", r.NSBaseName, nsNum)
createNSName := fmt.Sprintf("%s-%00000d", r.CaseBaseName, nsNum)
*r.NSIncluded = append(*r.NSIncluded, createNSName)
}
r.TestMsg = &TestMSG{
@@ -84,22 +81,21 @@ func (r *RBACCase) Init() error {
}
func (r *RBACCase) CreateResources() error {
ctx, ctxCancel := context.WithTimeout(context.Background(), 10*time.Minute)
defer ctxCancel()
r.Ctx, r.CtxCancel = context.WithTimeout(context.Background(), 10*time.Minute)
for nsNum := 0; nsNum < r.NamespacesTotal; nsNum++ {
createNSName := fmt.Sprintf("%s-%00000d", r.NSBaseName, nsNum)
createNSName := fmt.Sprintf("%s-%00000d", r.CaseBaseName, nsNum)
fmt.Printf("Creating namespaces ...%s\n", createNSName)
if err := CreateNamespace(ctx, r.Client, createNSName); err != nil {
if err := CreateNamespace(r.Ctx, r.Client, createNSName); err != nil {
return errors.Wrapf(err, "Failed to create namespace %s", createNSName)
}
serviceAccountName := fmt.Sprintf("service-account-%s-%00000d", r.NSBaseName, nsNum)
serviceAccountName := fmt.Sprintf("service-account-%s-%00000d", r.CaseBaseName, nsNum)
fmt.Printf("Creating service account ...%s\n", createNSName)
if err := CreateServiceAccount(ctx, r.Client, createNSName, serviceAccountName); err != nil {
if err := CreateServiceAccount(r.Ctx, r.Client, createNSName, serviceAccountName); err != nil {
return errors.Wrapf(err, "Failed to create service account %s", serviceAccountName)
}
clusterRoleName := fmt.Sprintf("clusterrole-%s-%00000d", r.NSBaseName, nsNum)
clusterRoleBindingName := fmt.Sprintf("clusterrolebinding-%s-%00000d", r.NSBaseName, nsNum)
if err := CreateRBACWithBindingSA(ctx, r.Client, createNSName, serviceAccountName, clusterRoleName, clusterRoleBindingName); err != nil {
clusterRoleName := fmt.Sprintf("clusterrole-%s-%00000d", r.CaseBaseName, nsNum)
clusterRoleBindingName := fmt.Sprintf("clusterrolebinding-%s-%00000d", r.CaseBaseName, nsNum)
if err := CreateRBACWithBindingSA(r.Ctx, r.Client, createNSName, serviceAccountName, clusterRoleName, clusterRoleBindingName); err != nil {
return errors.Wrapf(err, "Failed to create cluster role %s with role binding %s", clusterRoleName, clusterRoleBindingName)
}
}
@@ -107,14 +103,12 @@ func (r *RBACCase) CreateResources() error {
}
func (r *RBACCase) Verify() error {
ctx, ctxCancel := context.WithTimeout(context.Background(), 10*time.Minute)
defer ctxCancel()
for nsNum := 0; nsNum < r.NamespacesTotal; nsNum++ {
checkNSName := fmt.Sprintf("%s-%00000d", r.NSBaseName, nsNum)
checkServiceAccountName := fmt.Sprintf("service-account-%s-%00000d", r.NSBaseName, nsNum)
checkClusterRoleName := fmt.Sprintf("clusterrole-%s-%00000d", r.NSBaseName, nsNum)
checkClusterRoleBindingName := fmt.Sprintf("clusterrolebinding-%s-%00000d", r.NSBaseName, nsNum)
checkNS, err := GetNamespace(ctx, r.Client, checkNSName)
checkNSName := fmt.Sprintf("%s-%00000d", r.CaseBaseName, nsNum)
checkServiceAccountName := fmt.Sprintf("service-account-%s-%00000d", r.CaseBaseName, nsNum)
checkClusterRoleName := fmt.Sprintf("clusterrole-%s-%00000d", r.CaseBaseName, nsNum)
checkClusterRoleBindingName := fmt.Sprintf("clusterrolebinding-%s-%00000d", r.CaseBaseName, nsNum)
checkNS, err := GetNamespace(r.Ctx, r.Client, checkNSName)
if err != nil {
return errors.Wrapf(err, "Could not retrieve test namespace %s", checkNSName)
}
@@ -123,7 +117,7 @@ func (r *RBACCase) Verify() error {
}
//getting service account from the restore
checkSA, err := GetServiceAccount(ctx, r.Client, checkNSName, checkServiceAccountName)
checkSA, err := GetServiceAccount(r.Ctx, r.Client, checkNSName, checkServiceAccountName)
if err != nil {
return errors.Wrapf(err, "Could not retrieve test service account %s", checkSA)
@@ -134,7 +128,7 @@ func (r *RBACCase) Verify() error {
}
//getting cluster role from the restore
checkClusterRole, err := GetClusterRole(ctx, r.Client, checkClusterRoleName)
checkClusterRole, err := GetClusterRole(r.Ctx, r.Client, checkClusterRoleName)
if err != nil {
return errors.Wrapf(err, "Could not retrieve test cluster role %s", checkClusterRole)
@@ -145,7 +139,7 @@ func (r *RBACCase) Verify() error {
}
//getting cluster role binding from the restore
checkClusterRoleBinding, err := GetClusterRoleBinding(ctx, r.Client, checkClusterRoleBindingName)
checkClusterRoleBinding, err := GetClusterRoleBinding(r.Ctx, r.Client, checkClusterRoleBindingName)
if err != nil {
return errors.Wrapf(err, "Could not retrieve test cluster role binding %s", checkClusterRoleBinding)
@@ -166,21 +160,19 @@ func (r *RBACCase) Verify() error {
}
func (r *RBACCase) Destroy() error {
ctx, ctxCancel := context.WithTimeout(context.Background(), 10*time.Minute)
defer ctxCancel()
//cleanup clusterrole
err := CleanupClusterRole(ctx, r.Client, r.NSBaseName)
err := CleanupClusterRole(r.Ctx, r.Client, r.CaseBaseName)
if err != nil {
return errors.Wrap(err, "Could not cleanup clusterroles")
}
//cleanup cluster rolebinding
err = CleanupClusterRoleBinding(ctx, r.Client, r.NSBaseName)
err = CleanupClusterRoleBinding(r.Ctx, r.Client, r.CaseBaseName)
if err != nil {
return errors.Wrap(err, "Could not cleanup clusterrolebindings")
}
err = CleanupNamespacesWithPoll(ctx, r.Client, r.NSBaseName)
err = CleanupNamespacesWithPoll(r.Ctx, r.Client, r.CaseBaseName)
if err != nil {
return errors.Wrap(err, "Could cleanup retrieve namespaces")
}
@@ -189,5 +181,8 @@ func (r *RBACCase) Destroy() error {
}
func (r *RBACCase) Clean() error {
return r.Destroy()
if !r.VeleroCfg.Debug {
return r.Destroy()
}
return nil
}

View File

@@ -33,15 +33,14 @@ limitations under the License.
package basic
import (
. "github.com/vmware-tanzu/velero/test/e2e"
. "github.com/vmware-tanzu/velero/test/e2e/test"
)
func GetResourcesCheckTestCases() []VeleroBackupRestoreTest {
return []VeleroBackupRestoreTest{
&NSAnnotationCase{TestCase{VeleroCfg: VeleroCfg}},
&MultiNSBackup{IsScalTest: false, TestCase: TestCase{VeleroCfg: VeleroCfg}},
&RBACCase{TestCase{VeleroCfg: VeleroCfg}},
&NSAnnotationCase{},
&MultiNSBackup{IsScalTest: false},
&RBACCase{},
}
}

View File

@@ -31,15 +31,17 @@ type StorageClasssChanging struct {
const SCCBaseName string = "scc-"
var StorageClasssChangingTest func() = TestFunc(&StorageClasssChanging{
namespace: SCCBaseName + "1", TestCase: TestCase{NSBaseName: SCCBaseName}})
var StorageClasssChangingTest func() = TestFunc(&StorageClasssChanging{})
func (s *StorageClasssChanging) Init() error {
s.TestCase.Init()
s.CaseBaseName = SCCBaseName + s.UUIDgen
s.namespace = s.CaseBaseName
s.BackupName = "backup-" + s.CaseBaseName
s.RestoreName = "restore-" + s.CaseBaseName
s.mappedNS = s.namespace + "-mapped"
s.VeleroCfg = VeleroCfg
s.Client = *s.VeleroCfg.ClientToInstallVelero
s.NSBaseName = SCCBaseName
s.namespace = s.NSBaseName + UUIDgen.String()
s.mappedNS = s.namespace + "-mapped"
s.TestMsg = &TestMSG{
Desc: "Changing PV/PVC Storage Classes",
FailedMSG: "Failed to changing PV/PVC Storage Classes",
@@ -56,10 +58,7 @@ func (s *StorageClasssChanging) Init() error {
s.configmaptName = "change-storage-class-config"
s.volume = "volume-1"
s.podName = "pod-1"
return nil
}
func (s *StorageClasssChanging) StartRun() error {
s.BackupName = s.BackupName + "backup-" + UUIDgen.String()
s.RestoreName = s.RestoreName + "restore-" + UUIDgen.String()
s.BackupArgs = []string{
@@ -74,14 +73,13 @@ func (s *StorageClasssChanging) StartRun() error {
return nil
}
func (s *StorageClasssChanging) CreateResources() error {
ctx, ctxCancel := context.WithTimeout(context.Background(), 10*time.Minute)
defer ctxCancel()
s.Ctx, s.CtxCancel = context.WithTimeout(context.Background(), 10*time.Minute)
By(fmt.Sprintf("Create a storage class %s", s.desStorageClass), func() {
Expect(InstallStorageClass(context.Background(), fmt.Sprintf("testdata/storage-class/%s.yaml",
Expect(InstallStorageClass(s.Ctx, fmt.Sprintf("testdata/storage-class/%s.yaml",
s.VeleroCfg.CloudProvider))).To(Succeed())
})
By(fmt.Sprintf("Create namespace %s", s.namespace), func() {
Expect(CreateNamespace(ctx, s.Client, s.namespace)).To(Succeed(),
Expect(CreateNamespace(s.Ctx, s.Client, s.namespace)).To(Succeed(),
fmt.Sprintf("Failed to create namespace %s", s.namespace))
})
@@ -97,30 +95,26 @@ func (s *StorageClasssChanging) CreateResources() error {
}
func (s *StorageClasssChanging) Destroy() error {
ctx, ctxCancel := context.WithTimeout(context.Background(), 10*time.Minute)
defer ctxCancel()
By(fmt.Sprintf("Expect storage class of PV %s to be %s ", s.volume, s.srcStorageClass), func() {
pvName, err := GetPVByPodName(s.Client, s.namespace, s.volume)
Expect(err).To(Succeed(), fmt.Sprintf("Failed to get PV name by pod name %s", s.podName))
pv, err := GetPersistentVolume(ctx, s.Client, s.namespace, pvName)
pv, err := GetPersistentVolume(s.Ctx, s.Client, s.namespace, pvName)
Expect(err).To(Succeed(), fmt.Sprintf("Failed to get PV by pod name %s", s.podName))
fmt.Println(pv)
Expect(pv.Spec.StorageClassName).To(Equal(s.srcStorageClass),
fmt.Sprintf("PV storage %s is not as expected %s", pv.Spec.StorageClassName, s.srcStorageClass))
})
By(fmt.Sprintf("Start to destroy namespace %s......", s.NSBaseName), func() {
Expect(CleanupNamespacesWithPoll(ctx, s.Client, s.NSBaseName)).To(Succeed(),
fmt.Sprintf("Failed to delete namespace %s", s.NSBaseName))
By(fmt.Sprintf("Start to destroy namespace %s......", s.CaseBaseName), func() {
Expect(CleanupNamespacesWithPoll(s.Ctx, s.Client, s.CaseBaseName)).To(Succeed(),
fmt.Sprintf("Failed to delete namespace %s", s.CaseBaseName))
})
return nil
}
func (s *StorageClasssChanging) Restore() error {
ctx, ctxCancel := context.WithTimeout(context.Background(), 10*time.Minute)
defer ctxCancel()
By(fmt.Sprintf("Start to restore %s .....", s.RestoreName), func() {
Expect(VeleroRestoreExec(ctx, s.VeleroCfg.VeleroCLI,
Expect(VeleroRestoreExec(s.Ctx, s.VeleroCfg.VeleroCLI,
s.VeleroCfg.VeleroNamespace, s.RestoreName,
s.RestoreArgs, velerov1api.RestorePhaseCompleted)).To(
Succeed(),
@@ -133,13 +127,11 @@ func (s *StorageClasssChanging) Restore() error {
return nil
}
func (s *StorageClasssChanging) Verify() error {
ctx, ctxCancel := context.WithTimeout(context.Background(), 10*time.Minute)
defer ctxCancel()
By(fmt.Sprintf("Expect storage class of PV %s to be %s ", s.volume, s.desStorageClass), func() {
time.Sleep(1 * time.Minute)
Expect(WaitForPods(s.Ctx, s.Client, s.mappedNS, []string{s.podName})).To(Succeed(), fmt.Sprintf("Failed to wait pod ready %s", s.podName))
pvName, err := GetPVByPodName(s.Client, s.mappedNS, s.volume)
Expect(err).To(Succeed(), fmt.Sprintf("Failed to get PV name by pod name %s", s.podName))
pv, err := GetPersistentVolume(ctx, s.Client, s.mappedNS, pvName)
pv, err := GetPersistentVolume(s.Ctx, s.Client, s.mappedNS, pvName)
Expect(err).To(Succeed(), fmt.Sprintf("Failed to get PV by pod name %s", s.podName))
fmt.Println(pv)
Expect(pv.Spec.StorageClassName).To(Equal(s.desStorageClass),
@@ -147,3 +139,12 @@ func (s *StorageClasssChanging) Verify() error {
})
return nil
}
func (s *StorageClasssChanging) Clean() error {
if !s.VeleroCfg.Debug {
DeleteConfigmap(s.Client.ClientGo, s.VeleroCfg.VeleroNamespace, s.configmaptName)
DeleteStorageClass(s.Ctx, s.Client, s.desStorageClass)
s.TestCase.Clean()
}
return nil
}

View File

@@ -84,7 +84,7 @@ func init() {
}
var _ = Describe("[APIGroup][Common] Velero tests with various CRD API group versions", APIGropuVersionsTest)
var _ = Describe("[APIGroup][APIVersion] Velero tests with various CRD API group versions", APIGropuVersionsTest)
var _ = Describe("[APIGroup][APIExtensions] CRD of apiextentions v1beta1 should be B/R successfully from cluster(k8s version < 1.22) to cluster(k8s version >= 1.22)", APIExtensionsVersionsTest)
// Test backup and restore of Kibishi using restic

View File

@@ -208,7 +208,7 @@ func MigrationTest(useVolumeSnapshots bool, veleroCLI2Version VeleroCLI2Version)
snapshotCheckPoint.NamespaceBackedUp = migrationNamespace
By("Snapshot should be created in cloud object store", func() {
snapshotCheckPoint, err := GetSnapshotCheckPoint(*veleroCfg.DefaultClient, veleroCfg, 2,
migrationNamespace, backupName, KibishiiPodNameList)
migrationNamespace, backupName, KibishiiPVCNameList)
Expect(err).NotTo(HaveOccurred(), "Fail to get snapshot checkpoint")
Expect(SnapshotsShouldBeCreatedInCloud(veleroCfg.CloudProvider,
veleroCfg.CloudCredentialsFile, veleroCfg.BSLBucket,
@@ -226,7 +226,7 @@ func MigrationTest(useVolumeSnapshots bool, veleroCLI2Version VeleroCLI2Version)
// the snapshots of AWS may be still in pending status when do the restore, wait for a while
// to avoid this https://github.com/vmware-tanzu/velero/issues/1799
// TODO remove this after https://github.com/vmware-tanzu/velero/issues/3533 is fixed
if (veleroCfg.CloudProvider == "aws" || veleroCfg.CloudProvider == "vsphere") && useVolumeSnapshots {
if veleroCfg.CloudProvider == "aws" && useVolumeSnapshots {
fmt.Println("Waiting 5 minutes to make sure the snapshots are ready...")
time.Sleep(5 * time.Minute)
}

View File

@@ -32,6 +32,7 @@ import (
"k8s.io/client-go/rest"
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
velerov2alpha1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v2alpha1"
clientset "github.com/vmware-tanzu/velero/pkg/generated/clientset/versioned"
)
@@ -154,6 +155,7 @@ func (f *factory) KubebuilderClient() (kbclient.Client, error) {
scheme := runtime.NewScheme()
velerov1api.AddToScheme(scheme)
velerov2alpha1api.AddToScheme(scheme)
k8scheme.AddToScheme(scheme)
apiextv1beta1.AddToScheme(scheme)
apiextv1.AddToScheme(scheme)

View File

@@ -31,30 +31,22 @@ var OptInPVBackupTest func() = TestFunc(&PVBackupFiltering{annotation: OPT_IN_AN
var OptOutPVBackupTest func() = TestFunc(&PVBackupFiltering{annotation: OPT_OUT_ANN, id: "opt-out"})
func (p *PVBackupFiltering) Init() error {
p.TestCase.Init()
p.CaseBaseName = "pv-filter-" + p.UUIDgen
p.BackupName = "backup-" + p.CaseBaseName + p.id
p.RestoreName = "restore-" + p.CaseBaseName + p.id
p.VeleroCfg = VeleroCfg
p.Client = *p.VeleroCfg.ClientToInstallVelero
p.VeleroCfg.UseVolumeSnapshots = false
p.VeleroCfg.UseNodeAgent = true
p.NSBaseName = "ns"
p.NSIncluded = &[]string{fmt.Sprintf("%s-%s-%d", p.NSBaseName, p.id, 1), fmt.Sprintf("%s-%s-%d", p.NSBaseName, p.id, 2)}
p.NSIncluded = &[]string{fmt.Sprintf("%s-%s-%d", p.CaseBaseName, p.id, 1), fmt.Sprintf("%s-%s-%d", p.CaseBaseName, p.id, 2)}
p.TestMsg = &TestMSG{
Desc: "Backup PVs filtering by opt-in/opt-out annotation",
FailedMSG: "Failed to PVs filtering by opt-in/opt-out annotation",
Text: fmt.Sprintf("Should backup PVs in namespace %s according to annotation %s", *p.NSIncluded, p.annotation),
}
return nil
}
func (p *PVBackupFiltering) StartRun() error {
ctx, ctxCancel := context.WithTimeout(context.Background(), 10*time.Minute)
defer ctxCancel()
err := InstallStorageClass(ctx, fmt.Sprintf("testdata/storage-class/%s.yaml", VeleroCfg.CloudProvider))
if err != nil {
return err
}
p.BackupName = p.BackupName + "backup-" + p.id + "-" + UUIDgen.String()
p.RestoreName = p.RestoreName + "restore-" + p.id + "-" + UUIDgen.String()
p.BackupArgs = []string{
"create", "--namespace", VeleroCfg.VeleroNamespace, "backup", p.BackupName,
"--include-namespaces", strings.Join(*p.NSIncluded, ","),
@@ -72,12 +64,17 @@ func (p *PVBackupFiltering) StartRun() error {
}
return nil
}
func (p *PVBackupFiltering) CreateResources() error {
ctx, ctxCancel := context.WithTimeout(context.Background(), 10*time.Minute)
defer ctxCancel()
p.Ctx, p.CtxCancel = context.WithTimeout(context.Background(), 10*time.Minute)
err := InstallStorageClass(p.Ctx, fmt.Sprintf("testdata/storage-class/%s.yaml", VeleroCfg.CloudProvider))
if err != nil {
return errors.Wrapf(err, "failed to install storage class for pv backup filtering test")
}
for _, ns := range *p.NSIncluded {
By(fmt.Sprintf("Create namespaces %s for workload\n", ns), func() {
Expect(CreateNamespace(ctx, p.Client, ns)).To(Succeed(), fmt.Sprintf("Failed to create namespace %s", ns))
Expect(CreateNamespace(p.Ctx, p.Client, ns)).To(Succeed(), fmt.Sprintf("Failed to create namespace %s", ns))
})
var pods []string
By(fmt.Sprintf("Deploy a few pods with several PVs in namespace %s", ns), func() {
@@ -105,7 +102,7 @@ func (p *PVBackupFiltering) CreateResources() error {
p.annotation: volumesToAnnotation,
}
By(fmt.Sprintf("Add annotation to pod %s of namespace %s", pod.Name, ns), func() {
_, err := AddAnnotationToPod(ctx, p.Client, ns, pod.Name, ann)
_, err := AddAnnotationToPod(p.Ctx, p.Client, ns, pod.Name, ann)
Expect(err).To(Succeed())
})
})
@@ -116,17 +113,17 @@ func (p *PVBackupFiltering) CreateResources() error {
By(fmt.Sprintf("Waiting for all pods to start %s\n", p.podsList), func() {
for index, ns := range *p.NSIncluded {
By(fmt.Sprintf("Waiting for all pods to start %d in namespace %s", index, ns), func() {
WaitForPods(ctx, p.Client, ns, p.podsList[index])
Expect(WaitForPods(p.Ctx, p.Client, ns, p.podsList[index])).To(Succeed())
})
}
})
By(fmt.Sprintf("Populate all pods %s with file %s", p.podsList, FILE_NAME), func() {
for index, ns := range *p.NSIncluded {
By(fmt.Sprintf("Creating file in all pods to start %d in namespace %s", index, ns), func() {
WaitForPods(ctx, p.Client, ns, p.podsList[index])
Expect(WaitForPods(p.Ctx, p.Client, ns, p.podsList[index])).To(Succeed())
for i, pod := range p.podsList[index] {
for j := range p.volumesList[i] {
Expect(CreateFileToPod(ctx, ns, pod, pod, p.volumesList[i][j],
Expect(CreateFileToPod(p.Ctx, ns, pod, pod, p.volumesList[i][j],
FILE_NAME, fileContent(ns, pod, p.volumesList[i][j]))).To(Succeed())
}
}
@@ -137,12 +134,10 @@ func (p *PVBackupFiltering) CreateResources() error {
}
func (p *PVBackupFiltering) Verify() error {
ctx, ctxCancel := context.WithTimeout(context.Background(), time.Minute*60)
defer ctxCancel()
By(fmt.Sprintf("Waiting for all pods to start %s", p.podsList), func() {
for index, ns := range *p.NSIncluded {
By(fmt.Sprintf("Waiting for all pods to start %d in namespace %s", index, ns), func() {
WaitForPods(ctx, p.Client, ns, p.podsList[index])
WaitForPods(p.Ctx, p.Client, ns, p.podsList[index])
})
}
})
@@ -155,21 +150,21 @@ func (p *PVBackupFiltering) Verify() error {
if j%2 == 0 {
if p.annotation == OPT_IN_ANN {
By(fmt.Sprintf("File should exists in PV %s of pod %s under namespace %s\n", p.volumesList[i][j], p.podsList[k][i], ns), func() {
Expect(fileExist(ctx, ns, p.podsList[k][i], p.volumesList[i][j])).To(Succeed(), "File not exist as expect")
Expect(fileExist(p.Ctx, ns, p.podsList[k][i], p.volumesList[i][j])).To(Succeed(), "File not exist as expect")
})
} else {
By(fmt.Sprintf("File should not exist in PV %s of pod %s under namespace %s\n", p.volumesList[i][j], p.podsList[k][i], ns), func() {
Expect(fileNotExist(ctx, ns, p.podsList[k][i], p.volumesList[i][j])).To(Succeed(), "File exists, not as expect")
Expect(fileNotExist(p.Ctx, ns, p.podsList[k][i], p.volumesList[i][j])).To(Succeed(), "File exists, not as expect")
})
}
} else {
if p.annotation == OPT_OUT_ANN {
By(fmt.Sprintf("File should exists in PV %s of pod %s under namespace %s\n", p.volumesList[i][j], p.podsList[k][i], ns), func() {
Expect(fileExist(ctx, ns, p.podsList[k][i], p.volumesList[i][j])).To(Succeed(), "File not exist as expect")
Expect(fileExist(p.Ctx, ns, p.podsList[k][i], p.volumesList[i][j])).To(Succeed(), "File not exist as expect")
})
} else {
By(fmt.Sprintf("File should not exist in PV %s of pod %s under namespace %s\n", p.volumesList[i][j], p.podsList[k][i], ns), func() {
Expect(fileNotExist(ctx, ns, p.podsList[k][i], p.volumesList[i][j])).To(Succeed(), "File exists, not as expect")
Expect(fileNotExist(p.Ctx, ns, p.podsList[k][i], p.volumesList[i][j])).To(Succeed(), "File exists, not as expect")
})
}
}

View File

@@ -19,10 +19,8 @@ package filtering
import (
"context"
"fmt"
"math/rand"
"time"
"github.com/google/uuid"
"github.com/pkg/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -43,8 +41,8 @@ var testInBackup = FilteringCase{IsTestInBackup: true}
var testInRestore = FilteringCase{IsTestInBackup: false}
func (f *FilteringCase) Init() error {
rand.Seed(time.Now().UnixNano())
UUIDgen, _ = uuid.NewRandom()
f.TestCase.Init()
f.replica = int32(2)
f.labels = map[string]string{"resourcefiltering": "true"}
f.labelSelector = "resourcefiltering"
@@ -66,26 +64,16 @@ func (f *FilteringCase) Init() error {
}
func (f *FilteringCase) CreateResources() error {
ctx, ctxCancel := context.WithTimeout(context.Background(), 10*time.Minute)
defer ctxCancel()
f.Ctx, f.CtxCancel = context.WithTimeout(context.Background(), 30*time.Minute)
for nsNum := 0; nsNum < f.NamespacesTotal; nsNum++ {
namespace := fmt.Sprintf("%s-%00000d", f.NSBaseName, nsNum)
namespace := fmt.Sprintf("%s-%00000d", f.CaseBaseName, nsNum)
fmt.Printf("Creating resources in namespace ...%s\n", namespace)
if err := CreateNamespace(ctx, f.Client, namespace); err != nil {
if err := CreateNamespace(f.Ctx, f.Client, namespace); err != nil {
return errors.Wrapf(err, "Failed to create namespace %s", namespace)
}
serviceAccountName := "default"
// wait until the service account is created before patch the image pull secret
if err := WaitUntilServiceAccountCreated(ctx, f.Client, namespace, serviceAccountName, 10*time.Minute); err != nil {
return errors.Wrapf(err, "failed to wait the service account %q created under the namespace %q", serviceAccountName, namespace)
}
// add the image pull secret to avoid the image pull limit issue of Docker Hub
if err := PatchServiceAccountWithImagePullSecret(ctx, f.Client, namespace, serviceAccountName, VeleroCfg.RegistryCredentialFile); err != nil {
return errors.Wrapf(err, "failed to patch the service account %q under the namespace %q", serviceAccountName, namespace)
}
//Create deployment
fmt.Printf("Creating deployment in namespaces ...%s\n", namespace)
deployment := NewDeployment(f.NSBaseName, namespace, f.replica, f.labels, nil).Result()
deployment := NewDeployment(f.CaseBaseName, namespace, f.replica, f.labels, nil).Result()
deployment, err := CreateDeployment(f.Client.ClientGo, namespace, deployment)
if err != nil {
return errors.Wrap(err, fmt.Sprintf("failed to delete the namespace %q", namespace))
@@ -95,7 +83,7 @@ func (f *FilteringCase) CreateResources() error {
return errors.Wrap(err, fmt.Sprintf("failed to ensure job completion in namespace: %q", namespace))
}
//Create Secret
secretName := f.NSBaseName
secretName := f.CaseBaseName
fmt.Printf("Creating secret %s in namespaces ...%s\n", secretName, namespace)
_, err = CreateSecret(f.Client.ClientGo, namespace, secretName, f.labels)
if err != nil {
@@ -106,7 +94,7 @@ func (f *FilteringCase) CreateResources() error {
return errors.Wrap(err, fmt.Sprintf("failed to ensure secret completion in namespace: %q", namespace))
}
//Create Configmap
configmaptName := f.NSBaseName
configmaptName := f.CaseBaseName
fmt.Printf("Creating configmap %s in namespaces ...%s\n", configmaptName, namespace)
_, err = CreateConfigMap(f.Client.ClientGo, namespace, configmaptName, f.labels, nil)
if err != nil {
@@ -121,13 +109,11 @@ func (f *FilteringCase) CreateResources() error {
}
func (f *FilteringCase) Verify() error {
ctx, ctxCancel := context.WithTimeout(context.Background(), 10*time.Minute)
defer ctxCancel()
for nsNum := 0; nsNum < f.NamespacesTotal; nsNum++ {
namespace := fmt.Sprintf("%s-%00000d", f.NSBaseName, nsNum)
namespace := fmt.Sprintf("%s-%00000d", f.CaseBaseName, nsNum)
fmt.Printf("Checking resources in namespaces ...%s\n", namespace)
//Check namespace
checkNS, err := GetNamespace(ctx, f.Client, namespace)
checkNS, err := GetNamespace(f.Ctx, f.Client, namespace)
if err != nil {
return errors.Wrapf(err, "Could not retrieve test namespace %s", namespace)
}
@@ -135,7 +121,7 @@ func (f *FilteringCase) Verify() error {
return errors.Errorf("Retrieved namespace for %s has name %s instead", namespace, checkNS.Name)
}
//Check deployment
_, err = GetDeployment(f.Client.ClientGo, namespace, f.NSBaseName)
_, err = GetDeployment(f.Client.ClientGo, namespace, f.CaseBaseName)
if err != nil {
return errors.Wrap(err, fmt.Sprintf("failed to list deployment in namespace: %q", namespace))
}

View File

@@ -45,16 +45,17 @@ var ExcludeFromBackupTest func() = TestFunc(&ExcludeFromBackup{testInBackup})
func (e *ExcludeFromBackup) Init() error {
e.FilteringCase.Init()
e.BackupName = "backup-exclude-from-backup-" + UUIDgen.String()
e.RestoreName = "restore-" + UUIDgen.String()
e.NSBaseName = "exclude-from-backup-" + UUIDgen.String()
e.CaseBaseName = "exclude-from-backup-" + e.UUIDgen
e.BackupName = "backup-" + e.CaseBaseName
e.RestoreName = "restore-" + e.CaseBaseName
e.TestMsg = &TestMSG{
Desc: "Backup with the label velero.io/exclude-from-backup=true are not included test",
Text: "Should not backup resources with the label velero.io/exclude-from-backup=true",
FailedMSG: "Failed to backup resources with the label velero.io/exclude-from-backup=true",
}
for nsNum := 0; nsNum < e.NamespacesTotal; nsNum++ {
createNSName := fmt.Sprintf("%s-%00000d", e.NSBaseName, nsNum)
createNSName := fmt.Sprintf("%s-%00000d", e.CaseBaseName, nsNum)
*e.NSIncluded = append(*e.NSIncluded, createNSName)
}
e.labels = map[string]string{
@@ -64,7 +65,7 @@ func (e *ExcludeFromBackup) Init() error {
e.BackupArgs = []string{
"create", "--namespace", VeleroCfg.VeleroNamespace, "backup", e.BackupName,
"--include-namespaces", e.NSBaseName,
"--include-namespaces", e.CaseBaseName,
"--default-volumes-to-fs-backup", "--wait",
}
@@ -76,9 +77,8 @@ func (e *ExcludeFromBackup) Init() error {
}
func (e *ExcludeFromBackup) CreateResources() error {
ctx, ctxCancel := context.WithTimeout(context.Background(), 10*time.Minute)
defer ctxCancel()
namespace := e.NSBaseName
e.Ctx, e.CtxCancel = context.WithTimeout(context.Background(), 10*time.Minute)
namespace := e.CaseBaseName
// These 2 labels for resources to be included
label1 := map[string]string{
"meaningless-label-resource-to-include": "true",
@@ -87,21 +87,12 @@ func (e *ExcludeFromBackup) CreateResources() error {
"velero.io/exclude-from-backup": "false",
}
fmt.Printf("Creating resources in namespace ...%s\n", namespace)
if err := CreateNamespace(ctx, e.Client, namespace); err != nil {
if err := CreateNamespace(e.Ctx, e.Client, namespace); err != nil {
return errors.Wrapf(err, "Failed to create namespace %s", namespace)
}
serviceAccountName := "default"
// wait until the service account is created before patch the image pull secret
if err := WaitUntilServiceAccountCreated(ctx, e.Client, namespace, serviceAccountName, 10*time.Minute); err != nil {
return errors.Wrapf(err, "failed to wait the service account %q created under the namespace %q", serviceAccountName, namespace)
}
// add the image pull secret to avoid the image pull limit issue of Docker Hub
if err := PatchServiceAccountWithImagePullSecret(ctx, e.Client, namespace, serviceAccountName, VeleroCfg.RegistryCredentialFile); err != nil {
return errors.Wrapf(err, "failed to patch the service account %q under the namespace %q", serviceAccountName, namespace)
}
//Create deployment: to be included
fmt.Printf("Creating deployment in namespaces ...%s\n", namespace)
deployment := NewDeployment(e.NSBaseName, namespace, e.replica, label2, nil).Result()
deployment := NewDeployment(e.CaseBaseName, namespace, e.replica, label2, nil).Result()
deployment, err := CreateDeployment(e.Client.ClientGo, namespace, deployment)
if err != nil {
return errors.Wrap(err, fmt.Sprintf("failed to delete the namespace %q", namespace))
@@ -111,7 +102,7 @@ func (e *ExcludeFromBackup) CreateResources() error {
return errors.Wrap(err, fmt.Sprintf("failed to ensure job completion in namespace: %q", namespace))
}
//Create Secret
secretName := e.NSBaseName
secretName := e.CaseBaseName
fmt.Printf("Creating secret %s in namespaces ...%s\n", secretName, namespace)
_, err = CreateSecret(e.Client.ClientGo, namespace, secretName, e.labels)
if err != nil {
@@ -122,11 +113,11 @@ func (e *ExcludeFromBackup) CreateResources() error {
return errors.Wrap(err, fmt.Sprintf("failed to ensure secret completion in namespace: %q", namespace))
}
By(fmt.Sprintf("Checking secret %s should exists in namespaces ...%s\n", secretName, namespace), func() {
_, err = GetSecret(e.Client.ClientGo, namespace, e.NSBaseName)
_, err = GetSecret(e.Client.ClientGo, namespace, e.CaseBaseName)
Expect(err).ShouldNot(HaveOccurred(), fmt.Sprintf("failed to list deployment in namespace: %q", namespace))
})
//Create Configmap: to be included
configmaptName := e.NSBaseName
configmaptName := e.CaseBaseName
fmt.Printf("Creating configmap %s in namespaces ...%s\n", configmaptName, namespace)
_, err = CreateConfigMap(e.Client.ClientGo, namespace, configmaptName, label1, nil)
if err != nil {
@@ -140,26 +131,24 @@ func (e *ExcludeFromBackup) CreateResources() error {
}
func (e *ExcludeFromBackup) Verify() error {
ctx, ctxCancel := context.WithTimeout(context.Background(), 10*time.Minute)
defer ctxCancel()
namespace := e.NSBaseName
namespace := e.CaseBaseName
By(fmt.Sprintf("Checking resources in namespaces ...%s\n", namespace), func() {
//Check namespace
checkNS, err := GetNamespace(ctx, e.Client, namespace)
checkNS, err := GetNamespace(e.Ctx, e.Client, namespace)
Expect(err).ShouldNot(HaveOccurred(), fmt.Sprintf("Could not retrieve test namespace %s", namespace))
Expect(checkNS.Name == namespace).To(Equal(true), fmt.Sprintf("Retrieved namespace for %s has name %s instead", namespace, checkNS.Name))
//Check deployment: should be included
_, err = GetDeployment(e.Client.ClientGo, namespace, e.NSBaseName)
_, err = GetDeployment(e.Client.ClientGo, namespace, e.CaseBaseName)
Expect(err).ShouldNot(HaveOccurred(), fmt.Sprintf("failed to list deployment in namespace: %q", namespace))
//Check secrets: secrets should not be included
_, err = GetSecret(e.Client.ClientGo, namespace, e.NSBaseName)
_, err = GetSecret(e.Client.ClientGo, namespace, e.CaseBaseName)
Expect(err).Should(HaveOccurred(), fmt.Sprintf("failed to list deployment in namespace: %q", namespace))
Expect(apierrors.IsNotFound(err)).To(Equal(true))
//Check configmap: should be included
_, err = GetConfigmap(e.Client.ClientGo, namespace, e.NSBaseName)
_, err = GetConfigmap(e.Client.ClientGo, namespace, e.CaseBaseName)
Expect(err).ShouldNot(HaveOccurred(), fmt.Sprintf("failed to list configmap in namespace: %q", namespace))
})
return nil

View File

@@ -50,19 +50,20 @@ var RestoreWithExcludeNamespaces func() = TestFunc(&ExcludeNamespaces{FilteringC
func (e *ExcludeNamespaces) Init() error {
e.FilteringCase.Init()
e.CaseBaseName = "exclude-namespaces-" + e.UUIDgen
e.namespacesExcluded = e.NamespacesTotal / 2
e.NSBaseName = "exclude-namespaces-" + UUIDgen.String()
if e.IsTestInBackup {
e.BackupName = "backup-exclude-namespaces-" + UUIDgen.String()
e.RestoreName = "restore-" + UUIDgen.String()
e.BackupName = "backup-" + e.CaseBaseName
e.RestoreName = "restore-" + e.UUIDgen
e.TestMsg = &TestMSG{
Desc: "Backup resources with exclude namespace test",
FailedMSG: "Failed to backup and restore with namespace include",
Text: fmt.Sprintf("should not backup %d namespaces of %d", e.namespacesExcluded, e.NamespacesTotal),
}
} else {
e.BackupName = "backup-" + UUIDgen.String()
e.RestoreName = "restore-exclude-namespaces-" + UUIDgen.String()
e.BackupName = "backup-" + e.UUIDgen
e.RestoreName = "restore-" + e.CaseBaseName
e.TestMsg = &TestMSG{
Desc: "Restore resources with exclude namespace test",
FailedMSG: "Failed to restore with namespace exclude",
@@ -71,7 +72,7 @@ func (e *ExcludeNamespaces) Init() error {
}
e.nsExcluded = &[]string{}
for nsNum := 0; nsNum < e.NamespacesTotal; nsNum++ {
createNSName := fmt.Sprintf("%s-%00000d", e.NSBaseName, nsNum)
createNSName := fmt.Sprintf("%s-%00000d", e.CaseBaseName, nsNum)
if nsNum < e.namespacesExcluded {
*e.nsExcluded = append(*e.nsExcluded, createNSName)
} else {
@@ -109,12 +110,11 @@ func (e *ExcludeNamespaces) Init() error {
}
func (e *ExcludeNamespaces) CreateResources() error {
ctx, ctxCancel := context.WithTimeout(context.Background(), 10*time.Minute)
defer ctxCancel()
e.Ctx, e.CtxCancel = context.WithTimeout(context.Background(), 10*time.Minute)
for nsNum := 0; nsNum < e.NamespacesTotal; nsNum++ {
createNSName := fmt.Sprintf("%s-%00000d", e.NSBaseName, nsNum)
createNSName := fmt.Sprintf("%s-%00000d", e.CaseBaseName, nsNum)
fmt.Printf("Creating namespaces ...%s\n", createNSName)
if err := CreateNamespace(ctx, e.Client, createNSName); err != nil {
if err := CreateNamespace(e.Ctx, e.Client, createNSName); err != nil {
return errors.Wrapf(err, "Failed to create namespace %s", createNSName)
}
}
@@ -122,12 +122,10 @@ func (e *ExcludeNamespaces) CreateResources() error {
}
func (e *ExcludeNamespaces) Verify() error {
ctx, ctxCancel := context.WithTimeout(context.Background(), 10*time.Minute)
defer ctxCancel()
// Verify that we got back all of the namespaces we created
for nsNum := 0; nsNum < e.namespacesExcluded; nsNum++ {
excludeNSName := fmt.Sprintf("%s-%00000d", e.NSBaseName, nsNum)
_, err := GetNamespace(ctx, e.Client, excludeNSName)
excludeNSName := fmt.Sprintf("%s-%00000d", e.CaseBaseName, nsNum)
_, err := GetNamespace(e.Ctx, e.Client, excludeNSName)
if err == nil {
return errors.Wrapf(err, "Resource filtering with exclude namespace but exclude namespace %s exist", excludeNSName)
}
@@ -138,8 +136,8 @@ func (e *ExcludeNamespaces) Verify() error {
}
for nsNum := e.namespacesExcluded; nsNum < e.NamespacesTotal; nsNum++ {
checkNSName := fmt.Sprintf("%s-%00000d", e.NSBaseName, nsNum)
checkNS, err := GetNamespace(ctx, e.Client, checkNSName)
checkNSName := fmt.Sprintf("%s-%00000d", e.CaseBaseName, nsNum)
checkNS, err := GetNamespace(e.Ctx, e.Client, checkNSName)
if err != nil {
return errors.Wrapf(err, "Could not retrieve test namespace %s", checkNSName)
}

View File

@@ -17,7 +17,6 @@ limitations under the License.
package filtering
import (
"context"
"fmt"
"strings"
@@ -49,9 +48,9 @@ var RestoreWithExcludeResources func() = TestFunc(&ExcludeResources{testInRestor
func (e *ExcludeResources) Init() error {
e.FilteringCase.Init()
e.NSBaseName = "exclude-resources-" + UUIDgen.String()
e.CaseBaseName = "exclude-resources-" + e.UUIDgen
for nsNum := 0; nsNum < e.NamespacesTotal; nsNum++ {
createNSName := fmt.Sprintf("%s-%00000d", e.NSBaseName, nsNum)
createNSName := fmt.Sprintf("%s-%00000d", e.CaseBaseName, nsNum)
*e.NSIncluded = append(*e.NSIncluded, createNSName)
}
if e.IsTestInBackup { // testing case backup with exclude-resources option
@@ -60,7 +59,7 @@ func (e *ExcludeResources) Init() error {
Text: "Should not backup resources which is excluded others should be backup",
FailedMSG: "Failed to backup with resource exclude",
}
e.BackupName = "backup-exclude-resources-" + UUIDgen.String()
e.BackupName = "backup-" + e.CaseBaseName
e.RestoreName = "restore-" + UUIDgen.String()
e.BackupArgs = []string{
"create", "--namespace", VeleroCfg.VeleroNamespace, "backup", e.BackupName,
@@ -74,15 +73,13 @@ func (e *ExcludeResources) Init() error {
"--from-backup", e.BackupName, "--wait",
}
} else { // testing case restore with exclude-resources option
e.BackupName = "backup-" + UUIDgen.String()
e.RestoreName = "restore-exclude-resources-" + UUIDgen.String()
e.BackupName = "backup-" + e.UUIDgen
e.RestoreName = "restore-" + e.CaseBaseName
e.TestMsg = &TestMSG{
Desc: "Restore resources with resources included test",
Text: "Should not restore resources which is excluded others should be backup",
FailedMSG: "Failed to restore with resource exclude",
}
e.BackupName = "backup-exclude-resources-" + UUIDgen.String()
e.RestoreName = "restore-exclude-resources-" + UUIDgen.String()
e.BackupArgs = []string{
"create", "--namespace", VeleroCfg.VeleroNamespace, "backup", e.BackupName,
"--include-namespaces", strings.Join(*e.NSIncluded, ","),
@@ -99,15 +96,15 @@ func (e *ExcludeResources) Init() error {
func (e *ExcludeResources) Verify() error {
for nsNum := 0; nsNum < e.NamespacesTotal; nsNum++ {
namespace := fmt.Sprintf("%s-%00000d", e.NSBaseName, nsNum)
namespace := fmt.Sprintf("%s-%00000d", e.CaseBaseName, nsNum)
fmt.Printf("Checking resources in namespaces ...%s\n", namespace)
//Check deployment
_, err := GetDeployment(e.Client.ClientGo, namespace, e.NSBaseName)
_, err := GetDeployment(e.Client.ClientGo, namespace, e.CaseBaseName)
if err != nil {
return errors.Wrap(err, fmt.Sprintf("failed to list deployment in namespace: %q", namespace))
}
//Check secrets
secretsList, err := e.Client.ClientGo.CoreV1().Secrets(namespace).List(context.TODO(), metav1.ListOptions{LabelSelector: e.labelSelector})
secretsList, err := e.Client.ClientGo.CoreV1().Secrets(namespace).List(e.Ctx, metav1.ListOptions{LabelSelector: e.labelSelector})
if err != nil {
if apierrors.IsNotFound(err) { //resource should be excluded
return nil
@@ -118,7 +115,7 @@ func (e *ExcludeResources) Verify() error {
}
//Check configmap
configmapList, err := e.Client.ClientGo.CoreV1().ConfigMaps(namespace).List(context.TODO(), metav1.ListOptions{LabelSelector: e.labelSelector})
configmapList, err := e.Client.ClientGo.CoreV1().ConfigMaps(namespace).List(e.Ctx, metav1.ListOptions{LabelSelector: e.labelSelector})
if err != nil {
return errors.Wrap(err, fmt.Sprintf("failed to list configmap in namespace: %q", namespace))
} else if len(configmapList.Items) == 0 {

View File

@@ -51,11 +51,11 @@ var RestoreWithIncludeNamespaces func() = TestFunc(&IncludeNamespaces{FilteringC
func (i *IncludeNamespaces) Init() error {
i.FilteringCase.Init()
i.CaseBaseName = "include-namespaces-" + i.UUIDgen
i.namespacesIncluded = i.NamespacesTotal / 2
i.allTestNamespaces = &[]string{}
i.NSBaseName = "include-namespaces-" + UUIDgen.String()
for nsNum := 0; nsNum < i.NamespacesTotal; nsNum++ {
createNSName := fmt.Sprintf("%s-%00000d", i.NSBaseName, nsNum)
createNSName := fmt.Sprintf("%s-%00000d", i.CaseBaseName, nsNum)
if nsNum < i.namespacesIncluded {
*i.NSIncluded = append(*i.NSIncluded, createNSName)
}
@@ -63,8 +63,8 @@ func (i *IncludeNamespaces) Init() error {
}
if i.IsTestInBackup {
i.BackupName = "backup-include-namespaces-" + UUIDgen.String()
i.RestoreName = "restore-" + UUIDgen.String()
i.BackupName = "backup-" + i.CaseBaseName
i.RestoreName = "restore-" + i.UUIDgen
i.TestMsg = &TestMSG{
Desc: "Backup resources with include namespace test",
FailedMSG: "Failed to backup with namespace include",
@@ -82,8 +82,8 @@ func (i *IncludeNamespaces) Init() error {
}
} else {
i.BackupName = "backup-" + UUIDgen.String()
i.RestoreName = "restore-include-namespaces-" + UUIDgen.String()
i.BackupName = "backup-" + i.UUIDgen
i.RestoreName = "restore-" + i.CaseBaseName
i.TestMsg = &TestMSG{
Desc: "Restore resources with include namespace test",
FailedMSG: "Failed to restore with namespace include",
@@ -105,12 +105,11 @@ func (i *IncludeNamespaces) Init() error {
}
func (i *IncludeNamespaces) CreateResources() error {
ctx, ctxCancel := context.WithTimeout(context.Background(), 10*time.Minute)
defer ctxCancel()
i.Ctx, i.CtxCancel = context.WithTimeout(context.Background(), 10*time.Minute)
for nsNum := 0; nsNum < i.NamespacesTotal; nsNum++ {
createNSName := fmt.Sprintf("%s-%00000d", i.NSBaseName, nsNum)
createNSName := fmt.Sprintf("%s-%00000d", i.CaseBaseName, nsNum)
fmt.Printf("Creating namespaces ...%s\n", createNSName)
if err := CreateNamespace(ctx, i.Client, createNSName); err != nil {
if err := CreateNamespace(i.Ctx, i.Client, createNSName); err != nil {
return errors.Wrapf(err, "Failed to create namespace %s", createNSName)
}
}
@@ -118,12 +117,10 @@ func (i *IncludeNamespaces) CreateResources() error {
}
func (i *IncludeNamespaces) Verify() error {
ctx, ctxCancel := context.WithTimeout(context.Background(), 10*time.Minute)
defer ctxCancel()
// Verify that we got back all of the namespaces we created
for nsNum := 0; nsNum < i.namespacesIncluded; nsNum++ {
checkNSName := fmt.Sprintf("%s-%00000d", i.NSBaseName, nsNum)
checkNS, err := GetNamespace(ctx, i.Client, checkNSName)
checkNSName := fmt.Sprintf("%s-%00000d", i.CaseBaseName, nsNum)
checkNS, err := GetNamespace(i.Ctx, i.Client, checkNSName)
if err != nil {
return errors.Wrapf(err, "Could not retrieve test namespace %s", checkNSName)
}
@@ -133,8 +130,8 @@ func (i *IncludeNamespaces) Verify() error {
}
for nsNum := i.namespacesIncluded; nsNum < i.NamespacesTotal; nsNum++ {
excludeNSName := fmt.Sprintf("%s-%00000d", i.NSBaseName, nsNum)
_, err := GetNamespace(ctx, i.Client, excludeNSName)
excludeNSName := fmt.Sprintf("%s-%00000d", i.CaseBaseName, nsNum)
_, err := GetNamespace(i.Ctx, i.Client, excludeNSName)
if err == nil {
return errors.Wrapf(err, "Resource filtering with include namespace but exclude namespace %s exist", excludeNSName)
}

View File

@@ -17,7 +17,6 @@ limitations under the License.
package filtering
import (
"context"
"fmt"
"strings"
@@ -47,9 +46,9 @@ var RestoreWithIncludeResources func() = TestFunc(&IncludeResources{testInRestor
func (i *IncludeResources) Init() error {
i.FilteringCase.Init()
i.NSBaseName = "include-resources-" + UUIDgen.String()
i.CaseBaseName = "include-resources-" + i.UUIDgen
for nsNum := 0; nsNum < i.NamespacesTotal; nsNum++ {
createNSName := fmt.Sprintf("%s-%00000d", i.NSBaseName, nsNum)
createNSName := fmt.Sprintf("%s-%00000d", i.CaseBaseName, nsNum)
*i.NSIncluded = append(*i.NSIncluded, createNSName)
}
if i.IsTestInBackup { // testing case backup with include-resources option
@@ -58,8 +57,8 @@ func (i *IncludeResources) Init() error {
Text: "Should backup resources which is included others should not be backup",
FailedMSG: "Failed to backup with resource include",
}
i.BackupName = "backup-include-resources-" + UUIDgen.String()
i.RestoreName = "restore-" + UUIDgen.String()
i.BackupName = "backup-" + i.CaseBaseName
i.RestoreName = "restore-" + i.UUIDgen
i.BackupArgs = []string{
"create", "--namespace", VeleroCfg.VeleroNamespace, "backup", i.BackupName,
"--include-resources", "deployments,configmaps",
@@ -76,8 +75,8 @@ func (i *IncludeResources) Init() error {
Text: "Should restore resources which is included others should not be backup",
FailedMSG: "Failed to restore with resource include",
}
i.BackupName = "backup-" + UUIDgen.String()
i.RestoreName = "restore-include-resources-" + UUIDgen.String()
i.BackupName = "backup-" + i.UUIDgen
i.RestoreName = "restore-" + i.CaseBaseName
i.BackupArgs = []string{
"create", "--namespace", VeleroCfg.VeleroNamespace, "backup", i.BackupName,
"--include-namespaces", strings.Join(*i.NSIncluded, ","),
@@ -94,15 +93,15 @@ func (i *IncludeResources) Init() error {
func (i *IncludeResources) Verify() error {
for nsNum := 0; nsNum < i.NamespacesTotal; nsNum++ {
namespace := fmt.Sprintf("%s-%00000d", i.NSBaseName, nsNum)
namespace := fmt.Sprintf("%s-%00000d", i.CaseBaseName, nsNum)
fmt.Printf("Checking resources in namespaces ...%s\n", namespace)
//Check deployment
_, err := GetDeployment(i.Client.ClientGo, namespace, i.NSBaseName)
_, err := GetDeployment(i.Client.ClientGo, namespace, i.CaseBaseName)
if err != nil {
return errors.Wrap(err, fmt.Sprintf("failed to list deployment in namespace: %q", namespace))
}
//Check secrets
secretsList, err := i.Client.ClientGo.CoreV1().Secrets(namespace).List(context.TODO(), metav1.ListOptions{LabelSelector: i.labelSelector})
secretsList, err := i.Client.ClientGo.CoreV1().Secrets(namespace).List(i.Ctx, metav1.ListOptions{LabelSelector: i.labelSelector})
if err != nil {
if apierrors.IsNotFound(err) { //resource should be excluded
return nil
@@ -113,7 +112,7 @@ func (i *IncludeResources) Verify() error {
}
//Check configmap
configmapList, err := i.Client.ClientGo.CoreV1().ConfigMaps(namespace).List(context.TODO(), metav1.ListOptions{LabelSelector: i.labelSelector})
configmapList, err := i.Client.ClientGo.CoreV1().ConfigMaps(namespace).List(i.Ctx, metav1.ListOptions{LabelSelector: i.labelSelector})
if err != nil {
return errors.Wrap(err, fmt.Sprintf("failed to list configmap in namespace: %q", namespace))
} else if len(configmapList.Items) == 0 {

Some files were not shown because too many files have changed in this diff Show More