From 5a7098364d904d55da32d18a9001cff6d3f99ae3 Mon Sep 17 00:00:00 2001 From: Tiger Kaovilai Date: Thu, 18 May 2023 16:31:06 -0400 Subject: [PATCH] master: OADP-1182 - Velero server args in DPA (#1016) * oadp-1.1: OADP-1557 Add all velero server args supported to DPA (#987) * refactor: remove reconciler from functions Signed-off-by: Tiger Kaovilai * oadp-1.1: go get openshift/velero:oadp-1.1 Signed-off-by: Tiger Kaovilai * add server package for velero server options Signed-off-by: Tiger Kaovilai * wip Signed-off-by: Tiger Kaovilai * replace apimachinery to avoid velero update Signed-off-by: Tiger Kaovilai * Delete util.go * use `base := make(map[T]T)` * Update go.mod, remove todo comment. * Revert "use `base := make(map[T]T)`" This reverts commit 0b9042a7a2230b5fd4c2a9e03bc10ab5338f6056. * controllers: add debugMode Signed-off-by: Tiger Kaovilai * add metrics port parsing error Signed-off-by: Tiger Kaovilai * simplified range expression Signed-off-by: Tiger Kaovilai * rely on remove duplicate at the end of the function Signed-off-by: Tiger Kaovilai * Apply suggestions from code review --------- Signed-off-by: Tiger Kaovilai * oadp-1.2 changes. Signed-off-by: Tiger Kaovilai * Use 4h for fs-backup-timeout Signed-off-by: Tiger Kaovilai * use oadp restic default timeout of 1h --------- Signed-off-by: Tiger Kaovilai --- api/v1alpha1/oadp_types.go | 45 + api/v1alpha1/zz_generated.deepcopy.go | 6 + ...enshift.io_dataprotectionapplications.yaml | 136 + ...enshift.io_dataprotectionapplications.yaml | 136 + controllers/common.go | 10 +- controllers/dpa_controller.go | 3 + controllers/monitor.go | 10 +- controllers/restic.go | 12 +- .../restore_resource_version_priority.go | 4 - controllers/validator.go | 3 +- controllers/velero.go | 281 +- controllers/velero_test.go | 3299 ++++------------- go.mod | 76 +- go.sum | 245 +- pkg/common/common.go | 60 +- pkg/common/common_test.go | 30 +- pkg/klog/klog.go | 90 + pkg/klog/zz_generated.deepcopy.go | 84 + pkg/velero/client/config.go | 16 + pkg/velero/client/zz_generated.deepcopy.go | 44 + pkg/velero/server/args.go | 159 + pkg/velero/server/config.go | 94 + pkg/velero/server/zz_generated.deepcopy.go | 155 + 23 files changed, 1963 insertions(+), 3035 deletions(-) create mode 100644 pkg/klog/klog.go create mode 100644 pkg/klog/zz_generated.deepcopy.go create mode 100644 pkg/velero/client/config.go create mode 100644 pkg/velero/client/zz_generated.deepcopy.go create mode 100644 pkg/velero/server/args.go create mode 100644 pkg/velero/server/config.go create mode 100644 pkg/velero/server/zz_generated.deepcopy.go diff --git a/api/v1alpha1/oadp_types.go b/api/v1alpha1/oadp_types.go index 0264dec83d..8dc002722f 100644 --- a/api/v1alpha1/oadp_types.go +++ b/api/v1alpha1/oadp_types.go @@ -17,6 +17,10 @@ limitations under the License. package v1alpha1 import ( + "time" + + "github.com/openshift/oadp-operator/pkg/common" + "github.com/openshift/oadp-operator/pkg/velero/server" velero "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -97,6 +101,9 @@ type VeleroConfig struct { // Default is 10m // +optional ResourceTimeout string `json:"resourceTimeout,omitempty"` + // Velero args are settings to customize velero server arguments. Overrides values in other fields. + // +optional + Args *server.Args `json:"args,omitempty"` } // PodConfig defines the pod configuration options @@ -356,3 +363,41 @@ func (veleroConfig *VeleroConfig) HasFeatureFlag(flag string) bool { func init() { SchemeBuilder.Register(&DataProtectionApplication{}, &DataProtectionApplicationList{}, &CloudStorage{}, &CloudStorageList{}) } + +// AutoCorrect is a collection of auto-correction functions for the DPA CR +// These auto corrects are in-memory only and do not persist to the CR +// There should not be another place where these auto-corrects are done +func (dpa *DataProtectionApplication) AutoCorrect() { + //check if CSI plugin is added in spec + if hasCSIPlugin(dpa.Spec.Configuration.Velero.DefaultPlugins) { + dpa.Spec.Configuration.Velero.FeatureFlags = append(dpa.Spec.Configuration.Velero.FeatureFlags, velero.CSIFeatureFlag) + } + if dpa.Spec.Configuration.Velero.RestoreResourcesVersionPriority != "" { + // if the RestoreResourcesVersionPriority is specified then ensure feature flag is enabled for enableApiGroupVersions + // duplicate feature flag checks are done in ReconcileVeleroDeployment + dpa.Spec.Configuration.Velero.FeatureFlags = append(dpa.Spec.Configuration.Velero.FeatureFlags, velero.APIGroupVersionsFeatureFlag) + } + if dpa.Spec.Configuration.Velero.Args != nil { + // if args is not nil, we take care of some fields that will be overridden from dpa if not specified in args + // Enable user to specify --fs-backup-timeout duration (OADP default 1h0m0s) + resticTimeout := "1h" + if dpa.Spec.Configuration != nil && dpa.Spec.Configuration.Restic != nil && len(dpa.Spec.Configuration.Restic.Timeout) > 0 { + resticTimeout = dpa.Spec.Configuration.Restic.Timeout + } + if pvOperationTimeout, err := time.ParseDuration(resticTimeout); err == nil && dpa.Spec.Configuration.Velero.Args.PodVolumeOperationTimeout == nil { + dpa.Spec.Configuration.Velero.Args.PodVolumeOperationTimeout = &pvOperationTimeout + } + } + dpa.Spec.Configuration.Velero.DefaultPlugins = common.RemoveDuplicateValues(dpa.Spec.Configuration.Velero.DefaultPlugins) + dpa.Spec.Configuration.Velero.FeatureFlags = common.RemoveDuplicateValues(dpa.Spec.Configuration.Velero.FeatureFlags) +} + +func hasCSIPlugin(plugins []DefaultPlugin) bool { + for _, plugin := range plugins { + if plugin == DefaultPluginCSI { + // CSI plugin is added so ensure that CSI feature flags is set + return true + } + } + return false +} diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 8565fad80c..4a08a4c761 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -22,6 +22,7 @@ limitations under the License. package v1alpha1 import ( + "github.com/openshift/oadp-operator/pkg/velero/server" velerov1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -574,6 +575,11 @@ func (in *VeleroConfig) DeepCopyInto(out *VeleroConfig) { *out = new(PodConfig) (*in).DeepCopyInto(*out) } + if in.Args != nil { + in, out := &in.Args, &out.Args + *out = new(server.Args) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VeleroConfig. diff --git a/bundle/manifests/oadp.openshift.io_dataprotectionapplications.yaml b/bundle/manifests/oadp.openshift.io_dataprotectionapplications.yaml index 1b1e56e7a2..c5e51b2054 100644 --- a/bundle/manifests/oadp.openshift.io_dataprotectionapplications.yaml +++ b/bundle/manifests/oadp.openshift.io_dataprotectionapplications.yaml @@ -311,6 +311,142 @@ spec: type: object velero: properties: + args: + description: Velero args are settings to customize velero server arguments. Overrides values in other fields. + properties: + add_dir_header: + description: If true, adds the file directory to the header of the log messages + type: boolean + alsologtostderr: + description: log to standard error as well as files (no effect when -logtostderr=true) + type: boolean + backup-sync-period: + description: How often to ensure all Velero backups in object storage exist as Backup API objects in the cluster. This is the default sync period if none is explicitly specified for a backup storage location. + format: int64 + type: integer + client-burst: + description: Maximum number of requests by the server to the Kubernetes API in a short period of time. + type: integer + client-page-size: + description: Page size of requests by the server to the Kubernetes API when listing objects during a backup. Set to 0 to disable paging. + type: integer + client-qps: + description: Maximum number of requests per second by the server to the Kubernetes API once the burst limit has been reached. this will be validated as a valid float32 + type: string + colorized: + description: Show colored output in TTY + type: boolean + default-backup-ttl: + description: default 720h0m0s + format: int64 + type: integer + default-item-operation-timeout: + description: How long to wait on asynchronous BackupItemActions and RestoreItemActions to complete before timing out. (default 1h0m0s) + format: int64 + type: integer + default-repo-maintain-frequency: + description: How often 'maintain' is run for backup repositories by default. + format: int64 + type: integer + default-volumes-to-fs-backup: + description: Backup all volumes with pod volume file system backup by default. + type: boolean + disabled-controllers: + description: List of controllers to disable on startup. Valid values are backup,backup-operations,backup-deletion,backup-finalizer,backup-sync,download-request,gc,backup-repo,restore,restore-operations,schedule,server-status-request + enum: + - backup + - backup-operations + - backup-deletion + - backup-finalizer + - backup-sync + - download-request + - gc + - backup-repo + - restore + - restore-operations + - schedule + - server-status-request + items: + type: string + type: array + fs-backup-timeout: + description: How long pod volume file system backups/restores should be allowed to run before timing out. (default 4h0m0s) + format: int64 + type: integer + garbage-collection-frequency: + description: How long to wait by default before backups can be garbage collected. (default 720h0m0s) + format: int64 + type: integer + item-operation-sync-frequency: + description: How often to check status on backup/restore operations after backup/restore processing. + format: int64 + type: integer + log-format: + description: The format for log output. Valid values are text, json. (default text) + enum: + - text + - json + type: string + log_backtrace_at: + description: when logging hits line file:N, emit a stack trace + type: string + log_dir: + description: If non-empty, write log files in this directory (no effect when -logtostderr=true) + type: string + log_file: + description: If non-empty, use this log file (no effect when -logtostderr=true) + type: string + log_file_max_size: + description: Defines the maximum size a log file can grow to (no effect when -logtostderr=true). Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800) + format: int64 + minimum: 0 + type: integer + logtostderr: + description: 'Boolean flags. Not handled atomically because the flag.Value interface does not let us avoid the =true, and that shorthand is necessary for compatibility. TODO: does this matter enough to fix? Seems unlikely.' + type: boolean + max-concurrent-k8s-connections: + description: Max concurrent connections number that Velero can create with kube-apiserver. Default is 30. (default 30) + type: integer + metrics-address: + description: The address to expose prometheus metrics + type: string + one_output: + description: If true, only write logs to their native severity level (vs also writing to each lower severity level; no effect when -logtostderr=true) + type: boolean + profiler-address: + description: The address to expose the pprof profiler. + type: string + resource-timeout: + description: How long to wait for resource processes which are not covered by other specific timeout parameters. Default is 10 minutes. (default 10m0s) + format: int64 + type: integer + restore-resource-priorities: + description: Desired order of resource restores, the priority list contains two parts which are split by "-" element. The resources before "-" element are restored first as high priorities, the resources after "-" element are restored last as low priorities, and any resource not in the list will be restored alphabetically between the high and low priorities. (default customresourcedefinitions,namespaces,storageclasses,volumesnapshotbackups.datamover.oadp.openshift.io,volumesnapshotclass.snapshot.storage.k8s.io,volumesnapshotcontents.snapshot.storage.k8s.io,volumesnapshots.snapshot.storage.k8s.io,persistentvolumes,persistentvolumeclaims,serviceaccounts,secrets,configmaps,limitranges,pods,replicasets.apps,clusterclasses.cluster.x-k8s.io,services,-,clusterbootstraps.run.tanzu.vmware.com,clusters.cluster.x-k8s.io,clusterresourcesets.addons.cluster.x-k8s.io) + type: string + skip_headers: + description: If true, avoid header prefixes in the log messages + type: boolean + skip_log_headers: + description: If true, avoid headers when opening log files (no effect when -logtostderr=true) + type: boolean + stderrthreshold: + description: logs at or above this threshold go to stderr when writing to files and stderr (no effect when -logtostderr=true or -alsologtostderr=false) (default 2) + type: integer + store-validation-frequency: + description: How often to verify if the storage is valid. Optional. Set this to `0s` to disable sync. Default 1 minute. + format: int64 + type: integer + terminating-resource-timeout: + description: How long to wait on persistent volumes and namespaces to terminate during a restore before timing out. + format: int64 + type: integer + v: + description: number for the log level verbosity + type: integer + vmodule: + description: comma-separated list of pattern=N settings for file-filtered logging + type: string + type: object customPlugins: description: customPlugins defines the custom plugin to be installed with Velero items: diff --git a/config/crd/bases/oadp.openshift.io_dataprotectionapplications.yaml b/config/crd/bases/oadp.openshift.io_dataprotectionapplications.yaml index 1b1e56e7a2..c5e51b2054 100644 --- a/config/crd/bases/oadp.openshift.io_dataprotectionapplications.yaml +++ b/config/crd/bases/oadp.openshift.io_dataprotectionapplications.yaml @@ -311,6 +311,142 @@ spec: type: object velero: properties: + args: + description: Velero args are settings to customize velero server arguments. Overrides values in other fields. + properties: + add_dir_header: + description: If true, adds the file directory to the header of the log messages + type: boolean + alsologtostderr: + description: log to standard error as well as files (no effect when -logtostderr=true) + type: boolean + backup-sync-period: + description: How often to ensure all Velero backups in object storage exist as Backup API objects in the cluster. This is the default sync period if none is explicitly specified for a backup storage location. + format: int64 + type: integer + client-burst: + description: Maximum number of requests by the server to the Kubernetes API in a short period of time. + type: integer + client-page-size: + description: Page size of requests by the server to the Kubernetes API when listing objects during a backup. Set to 0 to disable paging. + type: integer + client-qps: + description: Maximum number of requests per second by the server to the Kubernetes API once the burst limit has been reached. this will be validated as a valid float32 + type: string + colorized: + description: Show colored output in TTY + type: boolean + default-backup-ttl: + description: default 720h0m0s + format: int64 + type: integer + default-item-operation-timeout: + description: How long to wait on asynchronous BackupItemActions and RestoreItemActions to complete before timing out. (default 1h0m0s) + format: int64 + type: integer + default-repo-maintain-frequency: + description: How often 'maintain' is run for backup repositories by default. + format: int64 + type: integer + default-volumes-to-fs-backup: + description: Backup all volumes with pod volume file system backup by default. + type: boolean + disabled-controllers: + description: List of controllers to disable on startup. Valid values are backup,backup-operations,backup-deletion,backup-finalizer,backup-sync,download-request,gc,backup-repo,restore,restore-operations,schedule,server-status-request + enum: + - backup + - backup-operations + - backup-deletion + - backup-finalizer + - backup-sync + - download-request + - gc + - backup-repo + - restore + - restore-operations + - schedule + - server-status-request + items: + type: string + type: array + fs-backup-timeout: + description: How long pod volume file system backups/restores should be allowed to run before timing out. (default 4h0m0s) + format: int64 + type: integer + garbage-collection-frequency: + description: How long to wait by default before backups can be garbage collected. (default 720h0m0s) + format: int64 + type: integer + item-operation-sync-frequency: + description: How often to check status on backup/restore operations after backup/restore processing. + format: int64 + type: integer + log-format: + description: The format for log output. Valid values are text, json. (default text) + enum: + - text + - json + type: string + log_backtrace_at: + description: when logging hits line file:N, emit a stack trace + type: string + log_dir: + description: If non-empty, write log files in this directory (no effect when -logtostderr=true) + type: string + log_file: + description: If non-empty, use this log file (no effect when -logtostderr=true) + type: string + log_file_max_size: + description: Defines the maximum size a log file can grow to (no effect when -logtostderr=true). Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800) + format: int64 + minimum: 0 + type: integer + logtostderr: + description: 'Boolean flags. Not handled atomically because the flag.Value interface does not let us avoid the =true, and that shorthand is necessary for compatibility. TODO: does this matter enough to fix? Seems unlikely.' + type: boolean + max-concurrent-k8s-connections: + description: Max concurrent connections number that Velero can create with kube-apiserver. Default is 30. (default 30) + type: integer + metrics-address: + description: The address to expose prometheus metrics + type: string + one_output: + description: If true, only write logs to their native severity level (vs also writing to each lower severity level; no effect when -logtostderr=true) + type: boolean + profiler-address: + description: The address to expose the pprof profiler. + type: string + resource-timeout: + description: How long to wait for resource processes which are not covered by other specific timeout parameters. Default is 10 minutes. (default 10m0s) + format: int64 + type: integer + restore-resource-priorities: + description: Desired order of resource restores, the priority list contains two parts which are split by "-" element. The resources before "-" element are restored first as high priorities, the resources after "-" element are restored last as low priorities, and any resource not in the list will be restored alphabetically between the high and low priorities. (default customresourcedefinitions,namespaces,storageclasses,volumesnapshotbackups.datamover.oadp.openshift.io,volumesnapshotclass.snapshot.storage.k8s.io,volumesnapshotcontents.snapshot.storage.k8s.io,volumesnapshots.snapshot.storage.k8s.io,persistentvolumes,persistentvolumeclaims,serviceaccounts,secrets,configmaps,limitranges,pods,replicasets.apps,clusterclasses.cluster.x-k8s.io,services,-,clusterbootstraps.run.tanzu.vmware.com,clusters.cluster.x-k8s.io,clusterresourcesets.addons.cluster.x-k8s.io) + type: string + skip_headers: + description: If true, avoid header prefixes in the log messages + type: boolean + skip_log_headers: + description: If true, avoid headers when opening log files (no effect when -logtostderr=true) + type: boolean + stderrthreshold: + description: logs at or above this threshold go to stderr when writing to files and stderr (no effect when -logtostderr=true or -alsologtostderr=false) (default 2) + type: integer + store-validation-frequency: + description: How often to verify if the storage is valid. Optional. Set this to `0s` to disable sync. Default 1 minute. + format: int64 + type: integer + terminating-resource-timeout: + description: How long to wait on persistent volumes and namespaces to terminate during a restore before timing out. + format: int64 + type: integer + v: + description: number for the log level verbosity + type: integer + vmodule: + description: comma-separated list of pattern=N settings for file-filtered logging + type: string + type: object customPlugins: description: customPlugins defines the custom plugin to be installed with Velero items: diff --git a/controllers/common.go b/controllers/common.go index f3b372e40c..80f5eeb43e 100644 --- a/controllers/common.go +++ b/controllers/common.go @@ -15,12 +15,12 @@ func setContainerDefaults(container *corev1.Container) { if container.TerminationMessagePolicy == "" { container.TerminationMessagePolicy = corev1.TerminationMessageReadFile } - for i, _ := range container.Ports { + for i := range container.Ports { if container.Ports[i].Protocol == "" { container.Ports[i].Protocol = corev1.ProtocolTCP } } - for i, _ := range container.Env { + for i := range container.Env { if container.Env[i].ValueFrom != nil && container.Env[i].ValueFrom.FieldRef != nil && container.Env[i].ValueFrom.FieldRef.APIVersion == "" { container.Env[i].ValueFrom.FieldRef.APIVersion = "v1" } @@ -28,6 +28,10 @@ func setContainerDefaults(container *corev1.Container) { } func setPodTemplateSpecDefaults(template *corev1.PodTemplateSpec) { + if template.Annotations["deployment.kubernetes.io/revision"] != "" { + // unset the revision annotation to avoid emitting update events + delete(template.Annotations, "deployment.kubernetes.io/revision") + } if template.Spec.RestartPolicy == "" { template.Spec.RestartPolicy = corev1.RestartPolicyAlways } @@ -47,7 +51,7 @@ func setPodTemplateSpecDefaults(template *corev1.PodTemplateSpec) { template.Spec.SchedulerName = "default-scheduler" } // for each volumes, if volumeSource is Projected or SecretVolumeSource, set default mode - for i, _ := range template.Spec.Volumes { + for i := range template.Spec.Volumes { if template.Spec.Volumes[i].Projected != nil { if template.Spec.Volumes[i].Projected != nil { template.Spec.Volumes[i].Projected.DefaultMode = common.DefaultModePtr() diff --git a/controllers/dpa_controller.go b/controllers/dpa_controller.go index 70325a51bf..ba9b05589d 100644 --- a/controllers/dpa_controller.go +++ b/controllers/dpa_controller.go @@ -18,6 +18,7 @@ package controllers import ( "context" + "os" routev1 "github.com/openshift/api/route/v1" velerov1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" @@ -52,6 +53,8 @@ type DPAReconciler struct { EventRecorder record.EventRecorder } +var debugMode = os.Getenv("DEBUG") == "true" + //TODO!!! FIX THIS!!!! //+kubebuilder:rbac:groups=*,resources=*,verbs=* diff --git a/controllers/monitor.go b/controllers/monitor.go index b7982d8963..6a9c6c245d 100644 --- a/controllers/monitor.go +++ b/controllers/monitor.go @@ -30,7 +30,7 @@ func (r *DPAReconciler) ReconcileVeleroServiceMonitor(log logr.Logger) (bool, er if serviceMonitor.ObjectMeta.CreationTimestamp.IsZero() { serviceMonitor.Spec.Selector = metav1.LabelSelector{ - MatchLabels: r.getDpaAppLabels(&dpa), + MatchLabels: getDpaAppLabels(&dpa), } } @@ -72,10 +72,10 @@ func (r *DPAReconciler) buildVeleroServiceMonitor(serviceMonitor *monitor.Servic } serviceMonitor.Spec.Selector = metav1.LabelSelector{ - MatchLabels: r.getDpaAppLabels(dpa), + MatchLabels: getDpaAppLabels(dpa), } - serviceMonitor.Labels = r.getDpaAppLabels(dpa) + serviceMonitor.Labels = getDpaAppLabels(dpa) serviceMonitor.Spec.Endpoints = []monitor.Endpoint{ { @@ -147,7 +147,7 @@ func (r *DPAReconciler) updateVeleroMetricsSVC(svc *corev1.Service, dpa *oadpv1a // when updating the spec fields we update each field individually // to get around the immutable fields - svc.Spec.Selector = r.getDpaAppLabels(dpa) + svc.Spec.Selector = getDpaAppLabels(dpa) svc.Spec.Type = corev1.ServiceTypeClusterIP svc.Spec.Ports = []corev1.ServicePort{ @@ -161,6 +161,6 @@ func (r *DPAReconciler) updateVeleroMetricsSVC(svc *corev1.Service, dpa *oadpv1a }, } - svc.Labels = r.getDpaAppLabels(dpa) + svc.Labels = getDpaAppLabels(dpa) return nil } diff --git a/controllers/restic.go b/controllers/restic.go index 1201a9e1ed..02407d5265 100644 --- a/controllers/restic.go +++ b/controllers/restic.go @@ -112,7 +112,7 @@ func (r *DPAReconciler) ReconcileResticDaemonset(log logr.Logger) (bool, error) if ds.Spec.Selector.MatchLabels == nil { ds.Spec.Selector.MatchLabels = make(map[string]string) } - ds.Spec.Selector.MatchLabels, err = common.AppendUniqueLabels(ds.Spec.Selector.MatchLabels, nodeAgentLabelSelector.MatchLabels) + ds.Spec.Selector.MatchLabels, err = common.AppendUniqueKeyTOfTMaps(ds.Spec.Selector.MatchLabels, nodeAgentLabelSelector.MatchLabels) if err != nil { return fmt.Errorf("failed to append labels to selector: %s", err) } @@ -172,7 +172,7 @@ func (r *DPAReconciler) buildResticDaemonset(dpa *oadpv1alpha1.DataProtectionApp // get resource requirements for restic ds // ignoring err here as it is checked in validator.go - resticResourceReqs, _ := r.getResticResourceReqs(dpa) + resticResourceReqs, _ := getResticResourceReqs(dpa) installDs := install.DaemonSet(ds.Namespace, install.WithResources(resticResourceReqs), @@ -184,7 +184,11 @@ func (r *DPAReconciler) buildResticDaemonset(dpa *oadpv1alpha1.DataProtectionApp // Update Items in ObjectMeta dsName := ds.Name ds.TypeMeta = installDs.TypeMeta - ds.Labels, _ = common.AppendUniqueLabels(ds.Labels, installDs.Labels) + var err error + ds.Labels, err = common.AppendUniqueKeyTOfTMaps(ds.Labels, installDs.Labels) + if err != nil { + return nil, fmt.Errorf("restic daemonset label: %s", err) + } // Update Spec ds.Spec = installDs.Spec ds.Name = dsName @@ -200,7 +204,7 @@ func (r *DPAReconciler) customizeResticDaemonset(dpa *oadpv1alpha1.DataProtectio // add custom pod labels if dpa.Spec.Configuration.Restic.PodConfig != nil && dpa.Spec.Configuration.Restic.PodConfig.Labels != nil { var err error - ds.Spec.Template.Labels, err = common.AppendUniqueLabels(ds.Spec.Template.Labels, dpa.Spec.Configuration.Restic.PodConfig.Labels) + ds.Spec.Template.Labels, err = common.AppendUniqueKeyTOfTMaps(ds.Spec.Template.Labels, dpa.Spec.Configuration.Restic.PodConfig.Labels) if err != nil { return nil, fmt.Errorf("restic daemonset template custom label: %s", err) } diff --git a/controllers/restore_resource_version_priority.go b/controllers/restore_resource_version_priority.go index cafede309e..7f6d8fc93c 100644 --- a/controllers/restore_resource_version_priority.go +++ b/controllers/restore_resource_version_priority.go @@ -10,7 +10,6 @@ import ( ) const ( - enableApiGroupVersionsFeatureFlag = "EnableAPIGroupVersions" enableApiGroupVersionsConfigMapName = "enableapigroupversions" restoreResourcesVersionPriorityDataKey = "restoreResourcesVersionPriority" ) @@ -20,9 +19,6 @@ func (r *DPAReconciler) ReconcileRestoreResourcesVersionPriority(dpa *oadpv1alph if len(dpa.Spec.Configuration.Velero.RestoreResourcesVersionPriority) == 0 { return true, nil } - // if the RestoreResourcesVersionPriority is specified then ensure feature flag is enabled for enableApiGroupVersions - // duplicate feature flag checks are done in ReconcileVeleroDeployment - dpa.Spec.Configuration.Velero.FeatureFlags = append(dpa.Spec.Configuration.Velero.FeatureFlags, enableApiGroupVersionsFeatureFlag) configMap := corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: enableApiGroupVersionsConfigMapName, diff --git a/controllers/validator.go b/controllers/validator.go index 1115427cb6..186412aff6 100644 --- a/controllers/validator.go +++ b/controllers/validator.go @@ -8,6 +8,7 @@ import ( "time" mapset "github.com/deckarep/golang-set/v2" + "github.com/go-logr/logr" oadpv1alpha1 "github.com/openshift/oadp-operator/api/v1alpha1" "github.com/openshift/oadp-operator/pkg/credentials" @@ -91,7 +92,7 @@ func (r *DPAReconciler) ValidateDataProtectionCR(log logr.Logger) (bool, error) return false, err } - if _, err := r.getResticResourceReqs(&dpa); err != nil { + if _, err := getResticResourceReqs(&dpa); err != nil { return false, err } diff --git a/controllers/velero.go b/controllers/velero.go index 415b0399b9..a1b26e6329 100644 --- a/controllers/velero.go +++ b/controllers/velero.go @@ -4,14 +4,14 @@ import ( "fmt" "os" "reflect" + "strconv" "strings" + "github.com/google/go-cmp/cmp" "github.com/openshift/oadp-operator/pkg/credentials" "github.com/operator-framework/operator-lib/proxy" "github.com/sirupsen/logrus" - v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/intstr" //"sigs.k8s.io/controller-runtime/pkg/client" @@ -34,8 +34,7 @@ import ( ) const ( - Server = "server" - Registry = "Registry" + Server = "server" //TODO: Check for default secret names VeleroAWSSecretName = "cloud-credentials" VeleroAzureSecretName = "cloud-credentials-azure" @@ -60,149 +59,6 @@ var ( } ) -// TODO: Remove this function as it's no longer being used -func (r *DPAReconciler) ReconcileVeleroServiceAccount(log logr.Logger) (bool, error) { - dpa := oadpv1alpha1.DataProtectionApplication{} - if err := r.Get(r.Context, r.NamespacedName, &dpa); err != nil { - return false, err - } - veleroSa := &corev1.ServiceAccount{ - ObjectMeta: metav1.ObjectMeta{ - Name: common.Velero, - Namespace: dpa.Namespace, - }, - } - op, err := controllerutil.CreateOrPatch(r.Context, r.Client, veleroSa, func() error { - // Setting controller owner reference on the velero SA - err := controllerutil.SetControllerReference(&dpa, veleroSa, r.Scheme) - if err != nil { - return err - } - - // update the SA template - veleroSaUpdate, err := r.veleroServiceAccount(&dpa) - veleroSa = veleroSaUpdate - return err - }) - - if err != nil { - return false, err - } - - //TODO: Review velero SA status and report errors and conditions - - if op == controllerutil.OperationResultCreated || op == controllerutil.OperationResultUpdated { - // Trigger event to indicate velero SA was created or updated - r.EventRecorder.Event(veleroSa, - corev1.EventTypeNormal, - "VeleroServiceAccountReconciled", - fmt.Sprintf("performed %s on velero service account %s/%s", op, veleroSa.Namespace, veleroSa.Name), - ) - } - return true, nil -} - -// TODO: Remove this function as it's no longer being used -//TODO: Temporary solution for Non-OLM Operator install -func (r *DPAReconciler) ReconcileVeleroCRDs(log logr.Logger) (bool, error) { - dpa := oadpv1alpha1.DataProtectionApplication{} - if err := r.Get(r.Context, r.NamespacedName, &dpa); err != nil { - return false, err - } - - // check for Non-OLM install and proceed with Velero supporting CRD installation - /*if velero.Spec.OlmManaged != nil && !*velero.Spec.OlmManaged { - err := r.InstallVeleroCRDs(log) - if err != nil { - return false, err - } - }*/ - - return true, nil -} - -// TODO: Remove this function as it's no longer being used -func (r *DPAReconciler) InstallVeleroCRDs(log logr.Logger) error { - var err error - // Install CRDs - for _, unstructuredCrd := range install.AllCRDs().Items { - foundCrd := &v1.CustomResourceDefinition{} - crd := &v1.CustomResourceDefinition{} - if err := runtime.DefaultUnstructuredConverter.FromUnstructured(unstructuredCrd.Object, crd); err != nil { - return err - } - // Add Conversion to the spec, as this will be returned in the foundCrd - crd.Spec.Conversion = &v1.CustomResourceConversion{ - Strategy: v1.NoneConverter, - } - if err = r.Client.Get(r.Context, types.NamespacedName{Name: crd.ObjectMeta.Name}, foundCrd); err != nil { - if errors.IsNotFound(err) { - // Didn't find CRD, we should create it. - log.Info("Creating CRD", "CRD.Name", crd.ObjectMeta.Name) - if err = r.Client.Create(r.Context, crd); err != nil { - return err - } - } else { - // Return other errors - return err - } - } else { - // CRD exists, check if it's updated. - if !reflect.DeepEqual(foundCrd.Spec, crd.Spec) { - // Specs aren't equal, update and fix. - log.Info("Updating CRD", "CRD.Name", crd.ObjectMeta.Name, "foundCrd.Spec", foundCrd.Spec, "crd.Spec", crd.Spec) - foundCrd.Spec = *crd.Spec.DeepCopy() - if err = r.Client.Update(r.Context, foundCrd); err != nil { - return err - } - } - } - } - - return nil -} - -// TODO: Remove this function as it's no longer being used -func (r *DPAReconciler) ReconcileVeleroClusterRoleBinding(log logr.Logger) (bool, error) { - dpa := oadpv1alpha1.DataProtectionApplication{} - if err := r.Get(r.Context, r.NamespacedName, &dpa); err != nil { - return false, err - } - veleroCRB, err := r.veleroClusterRoleBinding(&dpa) - if err != nil { - return false, err - } - op, err := controllerutil.CreateOrPatch(r.Context, r.Client, veleroCRB, func() error { - // Setting controller owner reference on the velero CRB - // TODO: HOW DO I DO THIS?? ALAY HALP PLZ - /*err := controllerutil.SetControllerReference(&velero, veleroCRB, r.Scheme) - if err != nil { - return err - }*/ - - // update the CRB template - veleroCRBUpdate, err := r.veleroClusterRoleBinding(&dpa) - veleroCRB = veleroCRBUpdate - return err - }) - - if err != nil { - return false, err - } - - //TODO: Review velero CRB status and report errors and conditions - - if op == controllerutil.OperationResultCreated || op == controllerutil.OperationResultUpdated { - // Trigger event to indicate velero SA was created or updated - r.EventRecorder.Event(veleroCRB, - corev1.EventTypeNormal, - "VeleroClusterRoleBindingReconciled", - fmt.Sprintf("performed %s on velero clusterrolebinding %s", op, veleroCRB.Name), - ) - } - return true, nil -} - func (r *DPAReconciler) ReconcileVeleroDeployment(log logr.Logger) (bool, error) { dpa := oadpv1alpha1.DataProtectionApplication{} if err := r.Get(r.Context, r.NamespacedName, &dpa); err != nil { @@ -215,12 +71,15 @@ func (r *DPAReconciler) ReconcileVeleroDeployment(log logr.Logger) (bool, error) Namespace: dpa.Namespace, }, } + var orig *appsv1.Deployment // for debugging purposes op, err := controllerutil.CreateOrPatch(r.Context, r.Client, veleroDeployment, func() error { - + if debugMode { + orig = veleroDeployment.DeepCopy() // for debugging purposes + } // Setting Deployment selector if a new object is created as it is immutable if veleroDeployment.ObjectMeta.CreationTimestamp.IsZero() { veleroDeployment.Spec.Selector = &metav1.LabelSelector{ - MatchLabels: r.getDpaAppLabels(&dpa), + MatchLabels: getDpaAppLabels(&dpa), } } @@ -233,6 +92,9 @@ func (r *DPAReconciler) ReconcileVeleroDeployment(log logr.Logger) (bool, error) // Setting controller owner reference on the velero deployment return controllerutil.SetControllerReference(&dpa, veleroDeployment, r.Scheme) }) + if debugMode && op != controllerutil.OperationResultNone { // for debugging purposes + fmt.Printf("DEBUG: There was a diff which resulted in an operation on Velero Deployment: %s\n", cmp.Diff(orig, veleroDeployment)) + } if err != nil { if errors.IsInvalid(err) { @@ -268,13 +130,13 @@ func (r *DPAReconciler) ReconcileVeleroDeployment(log logr.Logger) (bool, error) func (r *DPAReconciler) veleroServiceAccount(dpa *oadpv1alpha1.DataProtectionApplication) (*corev1.ServiceAccount, error) { annotations := make(map[string]string) sa := install.ServiceAccount(dpa.Namespace, annotations) - sa.Labels = r.getDpaAppLabels(dpa) + sa.Labels = getDpaAppLabels(dpa) return sa, nil } func (r *DPAReconciler) veleroClusterRoleBinding(dpa *oadpv1alpha1.DataProtectionApplication) (*rbacv1.ClusterRoleBinding, error) { crb := install.ClusterRoleBinding(dpa.Namespace) - crb.Labels = r.getDpaAppLabels(dpa) + crb.Labels = getDpaAppLabels(dpa) return crb, nil } @@ -287,32 +149,27 @@ func (r *DPAReconciler) buildVeleroDeployment(veleroDeployment *appsv1.Deploymen if veleroDeployment == nil { return fmt.Errorf("velero deployment cannot be nil") } + // Auto corrects DPA + dpa.AutoCorrect() - //check if CSI plugin is added in spec - for _, plugin := range dpa.Spec.Configuration.Velero.DefaultPlugins { - if plugin == oadpv1alpha1.DefaultPluginCSI { - // CSI plugin is added so ensure that CSI feature flags is set - dpa.Spec.Configuration.Velero.FeatureFlags = append(dpa.Spec.Configuration.Velero.FeatureFlags, enableCSIFeatureFlag) - break - } - } _, err := r.ReconcileRestoreResourcesVersionPriority(dpa) if err != nil { return fmt.Errorf("error creating configmap for restore resource version priority:" + err.Error()) } - // get resource requirements for velero deployment // ignoring err here as it is checked in validator.go veleroResourceReqs, _ := r.getVeleroResourceReqs(dpa) - - // TODO! Reuse removeDuplicateValues with interface type - dpa.Spec.Configuration.Velero.DefaultPlugins = removeDuplicatePluginValues(dpa.Spec.Configuration.Velero.DefaultPlugins) - dpa.Spec.Configuration.Velero.FeatureFlags = removeDuplicateValues(dpa.Spec.Configuration.Velero.FeatureFlags) + podAnnotations, err := common.AppendUniqueKeyTOfTMaps(dpa.Spec.PodAnnotations, veleroDeployment.Annotations) + if err != nil { + return fmt.Errorf("error appending pod annotations: %v", err) + } installDeployment := install.Deployment(veleroDeployment.Namespace, install.WithResources(veleroResourceReqs), install.WithImage(getVeleroImage(dpa)), + install.WithAnnotations(podAnnotations), install.WithFeatures(dpa.Spec.Configuration.Velero.FeatureFlags), - install.WithAnnotations(dpa.Spec.PodAnnotations), + // last label overrides previous ones + install.WithLabels(veleroDeployment.Labels), // use WithSecret false even if we have secret because we use a different VolumeMounts and EnvVars // see: https://github.com/vmware-tanzu/velero/blob/ed5809b7fc22f3661eeef10bdcb63f0d74472b76/pkg/install/deployment.go#L223-L261 // our secrets are appended to containers/volumeMounts in credentials.AppendPluginSpecificSpecs function @@ -322,46 +179,21 @@ func (r *DPAReconciler) buildVeleroDeployment(veleroDeployment *appsv1.Deploymen veleroDeploymentName := veleroDeployment.Name veleroDeployment.TypeMeta = installDeployment.TypeMeta veleroDeployment.Spec = installDeployment.Spec - veleroDeployment.Labels, _ = common.AppendUniqueLabels(veleroDeployment.Labels, installDeployment.Labels) veleroDeployment.Name = veleroDeploymentName - return r.customizeVeleroDeployment(dpa, veleroDeployment) -} - -func removeDuplicatePluginValues(slice []oadpv1alpha1.DefaultPlugin) []oadpv1alpha1.DefaultPlugin { - if slice == nil { - return nil - } - keys := make(map[oadpv1alpha1.DefaultPlugin]bool) - list := []oadpv1alpha1.DefaultPlugin{} - for _, entry := range slice { - if _, found := keys[entry]; !found { //add entry to list if not found in keys already - keys[entry] = true - list = append(list, entry) - } - } - return list // return the result through the passed in argument -} - -// remove duplicate entry in string slice -func removeDuplicateValues(slice []string) []string { - if slice == nil { - return nil - } - keys := make(map[string]bool) - list := []string{} - for _, entry := range slice { - if _, found := keys[entry]; !found { //add entry to list if not found in keys already - keys[entry] = true - list = append(list, entry) - } + labels, err := common.AppendUniqueKeyTOfTMaps(veleroDeployment.Labels, installDeployment.Labels) + if err != nil { + return fmt.Errorf("velero deployment label: %v", err) } - return list // return the result through the passed in argument + veleroDeployment.Labels = labels + annotations, err := common.AppendUniqueKeyTOfTMaps(veleroDeployment.Annotations, installDeployment.Annotations) + veleroDeployment.Annotations = annotations + return r.customizeVeleroDeployment(dpa, veleroDeployment) } func (r *DPAReconciler) customizeVeleroDeployment(dpa *oadpv1alpha1.DataProtectionApplication, veleroDeployment *appsv1.Deployment) error { //append dpa labels var err error - veleroDeployment.Labels, err = common.AppendUniqueLabels(veleroDeployment.Labels, r.getDpaAppLabels(dpa)) + veleroDeployment.Labels, err = common.AppendUniqueKeyTOfTMaps(veleroDeployment.Labels, getDpaAppLabels(dpa)) if err != nil { return fmt.Errorf("velero deployment label: %v", err) } @@ -373,17 +205,17 @@ func (r *DPAReconciler) customizeVeleroDeployment(dpa *oadpv1alpha1.DataProtecti if veleroDeployment.Spec.Selector.MatchLabels == nil { veleroDeployment.Spec.Selector.MatchLabels = make(map[string]string) } - veleroDeployment.Spec.Selector.MatchLabels, err = common.AppendUniqueLabels(veleroDeployment.Spec.Selector.MatchLabels, veleroDeployment.Labels, r.getDpaAppLabels(dpa)) + veleroDeployment.Spec.Selector.MatchLabels, err = common.AppendUniqueKeyTOfTMaps(veleroDeployment.Spec.Selector.MatchLabels, veleroDeployment.Labels, getDpaAppLabels(dpa)) if err != nil { return fmt.Errorf("velero deployment selector label: %v", err) } - veleroDeployment.Spec.Template.Labels, err = common.AppendUniqueLabels(veleroDeployment.Spec.Template.Labels, veleroDeployment.Labels) + veleroDeployment.Spec.Template.Labels, err = common.AppendUniqueKeyTOfTMaps(veleroDeployment.Spec.Template.Labels, veleroDeployment.Labels) if err != nil { return fmt.Errorf("velero deployment template label: %v", err) } // add custom pod labels if dpa.Spec.Configuration.Velero != nil && dpa.Spec.Configuration.Velero.PodConfig != nil && dpa.Spec.Configuration.Velero.PodConfig.Labels != nil { - veleroDeployment.Spec.Template.Labels, err = common.AppendUniqueLabels(veleroDeployment.Spec.Template.Labels, dpa.Spec.Configuration.Velero.PodConfig.Labels) + veleroDeployment.Spec.Template.Labels, err = common.AppendUniqueKeyTOfTMaps(veleroDeployment.Spec.Template.Labels, dpa.Spec.Configuration.Velero.PodConfig.Labels) if err != nil { return fmt.Errorf("velero deployment template custom label: %v", err) } @@ -441,14 +273,31 @@ func (r *DPAReconciler) customizeVeleroDeployment(dpa *oadpv1alpha1.DataProtecti veleroDeployment.Spec.Template.Spec.DNSConfig = &dpa.Spec.PodDnsConfig } + // if metrics address is set, change annotation and ports + var prometheusPort *int + if dpa.Spec.Configuration.Velero.Args != nil && + dpa.Spec.Configuration.Velero.Args.MetricsAddress != "" { + address := strings.Split(dpa.Spec.Configuration.Velero.Args.MetricsAddress, ":") + if len(address) == 2 { + veleroDeployment.Spec.Template.Annotations["prometheus.io/port"] = address[1] + if prometheusPort == nil { + prometheusPort = new(int) + } + *prometheusPort, err = strconv.Atoi(address[1]) + if err != nil { + return fmt.Errorf("error parsing metrics address port: %v", err) + } + } + } + var veleroContainer *corev1.Container - for i, container := range veleroDeployment.Spec.Template.Spec.Containers { + for _, container := range veleroDeployment.Spec.Template.Spec.Containers { if container.Name == common.Velero { - veleroContainer = &veleroDeployment.Spec.Template.Spec.Containers[i] + veleroContainer = &veleroDeployment.Spec.Template.Spec.Containers[0] break } } - if err := r.customizeVeleroContainer(dpa, veleroDeployment, veleroContainer, isSTSNeeded); err != nil { + if err := r.customizeVeleroContainer(dpa, veleroDeployment, veleroContainer, isSTSNeeded, prometheusPort); err != nil { return err } @@ -511,10 +360,18 @@ func (r *DPAReconciler) customizeVeleroDeployment(dpa *oadpv1alpha1.DataProtecti return credentials.AppendPluginSpecificSpecs(dpa, veleroDeployment, veleroContainer, providerNeedsDefaultCreds, hasCloudStorage) } -func (r *DPAReconciler) customizeVeleroContainer(dpa *oadpv1alpha1.DataProtectionApplication, veleroDeployment *appsv1.Deployment, veleroContainer *corev1.Container, isSTSNeeded bool) error { +func (r *DPAReconciler) customizeVeleroContainer(dpa *oadpv1alpha1.DataProtectionApplication, veleroDeployment *appsv1.Deployment, veleroContainer *corev1.Container, isSTSNeeded bool, prometheusPort *int) error { if veleroContainer == nil { return fmt.Errorf("could not find velero container in Deployment") } + if prometheusPort != nil { + for i := range veleroContainer.Ports { + if veleroContainer.Ports[i].Name == "metrics" { + veleroContainer.Ports[i].ContainerPort = int32(*prometheusPort) + break + } + } + } veleroContainer.ImagePullPolicy = corev1.PullAlways veleroContainer.VolumeMounts = append(veleroContainer.VolumeMounts, corev1.VolumeMount{ @@ -568,6 +425,16 @@ func (r *DPAReconciler) customizeVeleroContainer(dpa *oadpv1alpha1.DataProtectio veleroContainer.Args = append(veleroContainer.Args, fmt.Sprintf("--fs-backup-timeout=%s", fsBackupTimeout)) setContainerDefaults(veleroContainer) + // if server args is set, override the default server args + if dpa.Spec.Configuration.Velero.Args != nil { + var err error + veleroContainer.Args, err = dpa.Spec.Configuration.Velero.Args.StringArr( + dpa.Spec.Configuration.Velero.FeatureFlags, + dpa.Spec.Configuration.Velero.LogLevel) + if err != nil { + return err + } + } return nil } @@ -603,7 +470,7 @@ func getVeleroImage(dpa *oadpv1alpha1.DataProtectionApplication) string { return os.Getenv("RELATED_IMAGE_VELERO") } -func (r *DPAReconciler) getDpaAppLabels(dpa *oadpv1alpha1.DataProtectionApplication) map[string]string { +func getDpaAppLabels(dpa *oadpv1alpha1.DataProtectionApplication) map[string]string { //append dpa name if dpa != nil { return getAppLabels(dpa.Name) @@ -681,7 +548,7 @@ func (r *DPAReconciler) getVeleroResourceReqs(dpa *oadpv1alpha1.DataProtectionAp } // Get Restic Resource Requirements -func (r *DPAReconciler) getResticResourceReqs(dpa *oadpv1alpha1.DataProtectionApplication) (corev1.ResourceRequirements, error) { +func getResticResourceReqs(dpa *oadpv1alpha1.DataProtectionApplication) (corev1.ResourceRequirements, error) { // Set default values ResourcesReqs := corev1.ResourceRequirements{ diff --git a/controllers/velero_test.go b/controllers/velero_test.go index 3284076614..972b95856f 100644 --- a/controllers/velero_test.go +++ b/controllers/velero_test.go @@ -5,6 +5,7 @@ import ( "fmt" "os" "reflect" + "strconv" "strings" "testing" @@ -12,6 +13,7 @@ import ( "github.com/google/go-cmp/cmp" oadpv1alpha1 "github.com/openshift/oadp-operator/api/v1alpha1" "github.com/openshift/oadp-operator/pkg/common" + "github.com/openshift/oadp-operator/pkg/velero/server" "github.com/sirupsen/logrus" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" @@ -25,8 +27,88 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ) -const proxyEnvKey = "HTTP_PROXY" -const proxyEnvValue = "http://proxy.example.com:8080" +const ( + proxyEnvKey = "HTTP_PROXY" + proxyEnvValue = "http://proxy.example.com:8080" + argsMetricsPortTest int32 = 69420 +) + +var ( + veleroDeploymentLabel = map[string]string{ + "app.kubernetes.io/name": common.Velero, + "app.kubernetes.io/instance": "test-Velero-CR", + "app.kubernetes.io/managed-by": common.OADPOperator, + "app.kubernetes.io/component": Server, + "component": "velero", + oadpv1alpha1.OadpOperatorLabel: "True", + } + veleroPodLabelAppend = map[string]string{"deploy": "velero"} + veleroDeploymentMatchLabels = common.AppendTTMapAsCopy(veleroDeploymentLabel, veleroPodLabelAppend) + veleroPodAnnotations = map[string]string{ + "prometheus.io/scrape": "true", + "prometheus.io/port": "8085", + "prometheus.io/path": "/metrics", + } + veleroPodObjectMeta = metav1.ObjectMeta{ + Labels: veleroDeploymentMatchLabels, + Annotations: veleroPodAnnotations, + } + baseEnvVars = []corev1.EnvVar{ + {Name: common.VeleroScratchDirEnvKey, Value: "/scratch"}, + { + Name: common.VeleroNamespaceEnvKey, + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.namespace"}, + }, + }, + {Name: common.LDLibraryPathEnvKey, Value: "/plugins"}, + {Name: "OPENSHIFT_IMAGESTREAM_BACKUP", Value: "true"}, + } + + baseVolumeMounts = []corev1.VolumeMount{ + {Name: "plugins", MountPath: "/plugins"}, + {Name: "scratch", MountPath: "/scratch"}, + {Name: "certs", MountPath: "/etc/ssl/certs"}, + } + + baseVolumes = []corev1.Volume{ + { + Name: "plugins", + VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{}}, + }, + { + Name: "scratch", + VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{}}, + }, + { + Name: "certs", + VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{}}, + }, + } + baseContainer = corev1.Container{ + Image: common.AWSPluginImage, + Name: common.VeleroPluginForAWS, + ImagePullPolicy: corev1.PullAlways, + Resources: corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("500m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + }, + TerminationMessagePath: "/dev/termination-log", + TerminationMessagePolicy: "File", + VolumeMounts: []corev1.VolumeMount{ + {MountPath: "/target", Name: "plugins"}, + }, + } +) + +func pluginContainer(name, image string) corev1.Container { + container := baseContainer + container.Name = name + container.Image = image + return container +} func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { type fields struct { @@ -72,7 +154,6 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { }, }, }, - { name: "Velero Deployment is nil", veleroDeployment: nil, @@ -88,17 +169,7 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { Namespace: "test-ns", }, Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, }, }, dpa: &oadpv1alpha1.DataProtectionApplication{ @@ -117,49 +188,17 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "test-velero-deployment", Namespace: "test-ns", - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, + Labels: veleroDeploymentLabel, }, TypeMeta: metav1.TypeMeta{ Kind: "Deployment", APIVersion: appsv1.SchemeGroupVersion.String(), }, Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, Replicas: pointer.Int32(1), Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - Annotations: map[string]string{ - "prometheus.io/scrape": "true", - "prometheus.io/port": "8085", - "prometheus.io/path": "/metrics", - }, - }, + ObjectMeta: veleroPodObjectMeta, Spec: corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyAlways, ServiceAccountName: common.Velero, @@ -168,81 +207,18 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { Name: common.Velero, Image: common.VeleroImage, ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - }, - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - Command: []string{"/velero"}, + Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, + Resources: corev1.ResourceRequirements{Requests: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("500m"), corev1.ResourceMemory: resource.MustParse("128Mi")}}, + Command: []string{"/velero"}, Args: []string{ "server", "--fs-backup-timeout=1h", }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "plugins", - MountPath: "/plugins", - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - }, - Env: []corev1.EnvVar{ - { - Name: common.VeleroScratchDirEnvKey, - Value: "/scratch", - }, - { - Name: common.VeleroNamespaceEnvKey, - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: common.LDLibraryPathEnvKey, - Value: "/plugins", - }, - { - Name: "OPENSHIFT_IMAGESTREAM_BACKUP", - Value: "true", - }, - }, - }, - }, - Volumes: []corev1.Volume{ - { - Name: "plugins", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, + VolumeMounts: baseVolumeMounts, + Env: baseEnvVars, }, }, + Volumes: baseVolumes, InitContainers: []corev1.Container{}, }, }, @@ -257,17 +233,7 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { Namespace: "test-ns", }, Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, }, }, dpa: &oadpv1alpha1.DataProtectionApplication{ @@ -280,10 +246,7 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { Velero: &oadpv1alpha1.VeleroConfig{ PodConfig: &oadpv1alpha1.PodConfig{ Env: []corev1.EnvVar{ - { - Name: "TEST_ENV", - Value: "TEST_VALUE", - }, + {Name: "TEST_ENV", Value: "TEST_VALUE"}, }, }, }, @@ -295,49 +258,17 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "test-velero-deployment", Namespace: "test-ns", - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, + Labels: veleroDeploymentLabel, }, TypeMeta: metav1.TypeMeta{ Kind: "Deployment", APIVersion: appsv1.SchemeGroupVersion.String(), }, Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, Replicas: pointer.Int32(1), Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - Annotations: map[string]string{ - "prometheus.io/scrape": "true", - "prometheus.io/port": "8085", - "prometheus.io/path": "/metrics", - }, - }, + ObjectMeta: veleroPodObjectMeta, Spec: corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyAlways, ServiceAccountName: common.Velero, @@ -346,42 +277,16 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { Name: common.Velero, Image: common.VeleroImage, ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - }, - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - Command: []string{"/velero"}, + Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, + Resources: corev1.ResourceRequirements{Requests: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("500m"), corev1.ResourceMemory: resource.MustParse("128Mi")}}, + Command: []string{"/velero"}, Args: []string{ "server", "--fs-backup-timeout=1h", }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "plugins", - MountPath: "/plugins", - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - }, + VolumeMounts: baseVolumeMounts, Env: []corev1.EnvVar{ - { - Name: common.VeleroScratchDirEnvKey, - Value: "/scratch", - }, + {Name: common.VeleroScratchDirEnvKey, Value: "/scratch"}, { Name: common.VeleroNamespaceEnvKey, ValueFrom: &corev1.EnvVarSource{ @@ -390,41 +295,13 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { }, }, }, - { - Name: common.LDLibraryPathEnvKey, - Value: "/plugins", - }, - { - Name: "TEST_ENV", - Value: "TEST_VALUE", - }, - { - Name: "OPENSHIFT_IMAGESTREAM_BACKUP", - Value: "true", - }, - }, - }, - }, - Volumes: []corev1.Volume{ - { - Name: "plugins", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, + {Name: common.LDLibraryPathEnvKey, Value: "/plugins"}, + {Name: "TEST_ENV", Value: "TEST_VALUE"}, + {Name: "OPENSHIFT_IMAGESTREAM_BACKUP", Value: "true"}, }, }, }, + Volumes: baseVolumes, InitContainers: []corev1.Container{}, }, }, @@ -439,17 +316,7 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { Namespace: "test-ns", }, Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, }, }, dpa: &oadpv1alpha1.DataProtectionApplication{ @@ -474,49 +341,17 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "test-velero-deployment", Namespace: "test-ns", - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, + Labels: veleroDeploymentLabel, }, TypeMeta: metav1.TypeMeta{ Kind: "Deployment", APIVersion: appsv1.SchemeGroupVersion.String(), }, Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, Replicas: pointer.Int32(1), Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - Annotations: map[string]string{ - "prometheus.io/scrape": "true", - "prometheus.io/port": "8085", - "prometheus.io/path": "/metrics", - }, - }, + ObjectMeta: veleroPodObjectMeta, Spec: corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyAlways, ServiceAccountName: common.Velero, @@ -525,105 +360,27 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { Name: common.Velero, Image: common.VeleroImage, ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - }, - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - Command: []string{"/velero"}, + Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, + Resources: corev1.ResourceRequirements{Requests: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("500m"), corev1.ResourceMemory: resource.MustParse("128Mi")}}, + Command: []string{"/velero"}, Args: []string{ "server", "--features=EnableCSI", "--fs-backup-timeout=1h", }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "plugins", - MountPath: "/plugins", - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - { - Name: "cloud-credentials", - MountPath: "/credentials", - }, - { - Name: "cloud-credentials-gcp", - MountPath: "/credentials-gcp", - }, - { - Name: "cloud-credentials-azure", - MountPath: "/credentials-azure", - }, - }, - Env: []corev1.EnvVar{ - { - Name: common.VeleroScratchDirEnvKey, - Value: "/scratch", - }, - { - Name: common.VeleroNamespaceEnvKey, - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: common.LDLibraryPathEnvKey, - Value: "/plugins", - }, - { - Name: "OPENSHIFT_IMAGESTREAM_BACKUP", - Value: "true", - }, - { - Name: common.AWSSharedCredentialsFileEnvKey, - Value: "/credentials/cloud", - }, - { - Name: common.GCPCredentialsEnvKey, - Value: "/credentials-gcp/cloud", - }, - { - Name: common.AzureCredentialsFileEnvKey, - Value: "/credentials-azure/cloud", - }, - }, + VolumeMounts: append(baseVolumeMounts, []corev1.VolumeMount{ + {Name: "cloud-credentials", MountPath: "/credentials"}, + {Name: "cloud-credentials-gcp", MountPath: "/credentials-gcp"}, + {Name: "cloud-credentials-azure", MountPath: "/credentials-azure"}, + }...), + Env: append(baseEnvVars, []corev1.EnvVar{ + {Name: common.AWSSharedCredentialsFileEnvKey, Value: "/credentials/cloud"}, + {Name: common.GCPCredentialsEnvKey, Value: "/credentials-gcp/cloud"}, + {Name: common.AzureCredentialsFileEnvKey, Value: "/credentials-azure/cloud"}, + }...), }, }, - Volumes: []corev1.Volume{ - { - Name: "plugins", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, + Volumes: append(baseVolumes, []corev1.Volume{ { Name: "cloud-credentials", VolumeSource: corev1.VolumeSource{ @@ -648,122 +405,14 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { }, }, }, - }, + }...), InitContainers: []corev1.Container{ - { - Image: common.AWSPluginImage, - Name: common.VeleroPluginForAWS, - ImagePullPolicy: corev1.PullAlways, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - TerminationMessagePath: "/dev/termination-log", - TerminationMessagePolicy: "File", - VolumeMounts: []corev1.VolumeMount{ - { - MountPath: "/target", - Name: "plugins", - }, - }, - }, - { - Image: common.GCPPluginImage, - Name: common.VeleroPluginForGCP, - ImagePullPolicy: corev1.PullAlways, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - TerminationMessagePath: "/dev/termination-log", - TerminationMessagePolicy: "File", - VolumeMounts: []corev1.VolumeMount{ - { - MountPath: "/target", - Name: "plugins", - }, - }, - }, - { - Image: common.AzurePluginImage, - Name: common.VeleroPluginForAzure, - ImagePullPolicy: corev1.PullAlways, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - TerminationMessagePath: "/dev/termination-log", - TerminationMessagePolicy: "File", - VolumeMounts: []corev1.VolumeMount{ - { - MountPath: "/target", - Name: "plugins", - }, - }, - }, - { - Image: common.KubeVirtPluginImage, - Name: common.KubeVirtPlugin, - ImagePullPolicy: corev1.PullAlways, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - TerminationMessagePath: "/dev/termination-log", - TerminationMessagePolicy: "File", - VolumeMounts: []corev1.VolumeMount{ - { - MountPath: "/target", - Name: "plugins", - }, - }, - }, - { - Image: common.OpenshiftPluginImage, - Name: common.VeleroPluginForOpenshift, - ImagePullPolicy: corev1.PullAlways, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - TerminationMessagePath: "/dev/termination-log", - TerminationMessagePolicy: "File", - VolumeMounts: []corev1.VolumeMount{ - { - MountPath: "/target", - Name: "plugins", - }, - }, - }, - { - Image: common.CSIPluginImage, - Name: common.VeleroPluginForCSI, - ImagePullPolicy: corev1.PullAlways, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - TerminationMessagePath: "/dev/termination-log", - TerminationMessagePolicy: "File", - VolumeMounts: []corev1.VolumeMount{ - { - MountPath: "/target", - Name: "plugins", - }, - }, - }, + pluginContainer(common.VeleroPluginForAWS, common.AWSPluginImage), + pluginContainer(common.VeleroPluginForGCP, common.GCPPluginImage), + pluginContainer(common.VeleroPluginForAzure, common.AzurePluginImage), + pluginContainer(common.KubeVirtPlugin, common.KubeVirtPluginImage), + pluginContainer(common.VeleroPluginForOpenshift, common.OpenshiftPluginImage), + pluginContainer(common.VeleroPluginForCSI, common.CSIPluginImage), }, }, }, @@ -778,17 +427,7 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { Namespace: "test-ns", }, Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, }, }, testProxy: true, @@ -808,49 +447,17 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "test-velero-deployment", Namespace: "test-ns", - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, + Labels: veleroDeploymentLabel, }, TypeMeta: metav1.TypeMeta{ Kind: "Deployment", APIVersion: appsv1.SchemeGroupVersion.String(), }, Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, Replicas: pointer.Int32(1), Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - Annotations: map[string]string{ - "prometheus.io/scrape": "true", - "prometheus.io/port": "8085", - "prometheus.io/path": "/metrics", - }, - }, + ObjectMeta: veleroPodObjectMeta, Spec: corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyAlways, ServiceAccountName: common.Velero, @@ -859,43 +466,17 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { Name: common.Velero, Image: common.VeleroImage, ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - }, - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - Command: []string{"/velero"}, + Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, + Resources: corev1.ResourceRequirements{Requests: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("500m"), corev1.ResourceMemory: resource.MustParse("128Mi")}}, + Command: []string{"/velero"}, Args: []string{ "server", "--fs-backup-timeout=1h", }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "plugins", - MountPath: "/plugins", - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - }, + VolumeMounts: baseVolumeMounts, Env: []corev1.EnvVar{ - { - Name: common.VeleroScratchDirEnvKey, - Value: "/scratch", - }, + {Name: common.VeleroScratchDirEnvKey, Value: "/scratch"}, { Name: common.VeleroNamespaceEnvKey, ValueFrom: &corev1.EnvVarSource{ @@ -904,45 +485,14 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { }, }, }, - { - Name: common.LDLibraryPathEnvKey, - Value: "/plugins", - }, - { - Name: proxyEnvKey, - Value: proxyEnvValue, - }, - { - Name: strings.ToLower(proxyEnvKey), - Value: proxyEnvValue, - }, - { - Name: "OPENSHIFT_IMAGESTREAM_BACKUP", - Value: "true", - }, - }, - }, - }, - Volumes: []corev1.Volume{ - { - Name: "plugins", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, + {Name: common.LDLibraryPathEnvKey, Value: "/plugins"}, + {Name: proxyEnvKey, Value: proxyEnvValue}, + {Name: strings.ToLower(proxyEnvKey), Value: proxyEnvValue}, + {Name: "OPENSHIFT_IMAGESTREAM_BACKUP", Value: "true"}, }, }, }, + Volumes: baseVolumes, InitContainers: []corev1.Container{}, }, }, @@ -957,17 +507,7 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { Namespace: "test-ns", }, Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, }, }, dpa: &oadpv1alpha1.DataProtectionApplication{ @@ -992,49 +532,22 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "test-velero-deployment", Namespace: "test-ns", - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, + Labels: veleroDeploymentLabel, }, TypeMeta: metav1.TypeMeta{ Kind: "Deployment", APIVersion: appsv1.SchemeGroupVersion.String(), }, Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, Replicas: pointer.Int32(1), Template: corev1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - "thisIsVelero": "yes", - }, - Annotations: map[string]string{ - "prometheus.io/scrape": "true", - "prometheus.io/port": "8085", - "prometheus.io/path": "/metrics", - }, + Labels: common.AppendTTMapAsCopy(veleroDeploymentMatchLabels, + map[string]string{ + "thisIsVelero": "yes", + }), + Annotations: veleroPodAnnotations, }, Spec: corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyAlways, @@ -1044,81 +557,18 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { Name: common.Velero, Image: common.VeleroImage, ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - }, - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - Command: []string{"/velero"}, + Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, + Resources: corev1.ResourceRequirements{Requests: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("500m"), corev1.ResourceMemory: resource.MustParse("128Mi")}}, + Command: []string{"/velero"}, Args: []string{ "server", "--fs-backup-timeout=1h", }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "plugins", - MountPath: "/plugins", - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - }, - Env: []corev1.EnvVar{ - { - Name: common.VeleroScratchDirEnvKey, - Value: "/scratch", - }, - { - Name: common.VeleroNamespaceEnvKey, - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: common.LDLibraryPathEnvKey, - Value: "/plugins", - }, - { - Name: "OPENSHIFT_IMAGESTREAM_BACKUP", - Value: "true", - }, - }, - }, - }, - Volumes: []corev1.Volume{ - { - Name: "plugins", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, + VolumeMounts: baseVolumeMounts, + Env: baseEnvVars, }, }, + Volumes: baseVolumes, InitContainers: []corev1.Container{}, }, }, @@ -1133,17 +583,7 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { Namespace: "test-ns", }, Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, }, }, dpa: &oadpv1alpha1.DataProtectionApplication{ @@ -1520,6 +960,74 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { }, { name: "given valid DPA CR and log level is defined correctly, log level is set", + veleroDeployment: &appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-velero-deployment", + Namespace: "test-ns", + }, + Spec: appsv1.DeploymentSpec{ + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, + }, + }, + dpa: &oadpv1alpha1.DataProtectionApplication{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-Velero-CR", + Namespace: "test-ns", + }, + Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{ + LogLevel: logrus.InfoLevel.String(), + }, + }, + }, + }, + wantErr: false, + wantVeleroDeployment: &appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-velero-deployment", + Namespace: "test-ns", + Labels: veleroDeploymentLabel, + }, + TypeMeta: metav1.TypeMeta{ + Kind: "Deployment", + APIVersion: appsv1.SchemeGroupVersion.String(), + }, + Spec: appsv1.DeploymentSpec{ + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, + Replicas: pointer.Int32(1), + Template: corev1.PodTemplateSpec{ + ObjectMeta: veleroPodObjectMeta, + Spec: corev1.PodSpec{ + RestartPolicy: corev1.RestartPolicyAlways, + ServiceAccountName: common.Velero, + Containers: []corev1.Container{ + { + Name: common.Velero, + Image: common.VeleroImage, + ImagePullPolicy: corev1.PullAlways, + Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, + Resources: corev1.ResourceRequirements{Requests: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("500m"), corev1.ResourceMemory: resource.MustParse("128Mi")}}, + Command: []string{"/velero"}, + Args: []string{ + "server", + "--fs-backup-timeout=1h", + "--log-level", + logrus.InfoLevel.String(), + }, + VolumeMounts: baseVolumeMounts, + Env: baseEnvVars, + }, + }, + Volumes: baseVolumes, + InitContainers: []corev1.Container{}, + }, + }, + }, + }, + }, + { + name: "given valid DPA CR and ResourceTimeout is defined correctly, ResourceTimeout is set", veleroDeployment: &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: "test-velero-deployment", @@ -1547,7 +1055,8 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { Spec: oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ Velero: &oadpv1alpha1.VeleroConfig{ - LogLevel: logrus.InfoLevel.String(), + LogLevel: logrus.InfoLevel.String(), + ResourceTimeout: "5m", }, }, }, @@ -1626,6 +1135,7 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { "--fs-backup-timeout=1h", "--log-level", logrus.InfoLevel.String(), + "--resource-timeout=5m", }, VolumeMounts: []corev1.VolumeMount{ { @@ -1692,26 +1202,47 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { }, }, { - name: "given valid DPA CR and ResourceTimeout is defined correctly, ResourceTimeout is set", + name: "given valid DPA CR and log level is defined incorrectly error is returned", veleroDeployment: &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: "test-velero-deployment", Namespace: "test-ns", }, Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, + }, + }, + dpa: &oadpv1alpha1.DataProtectionApplication{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-Velero-CR", + Namespace: "test-ns", + }, + Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{ + LogLevel: logrus.InfoLevel.String() + "typo", }, }, }, }, + wantErr: true, + wantVeleroDeployment: nil, + }, + { + name: "given valid DPA CR, velero deployment resource customization", + veleroDeployment: &appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-velero-deployment", + Namespace: "test-ns", + }, + TypeMeta: metav1.TypeMeta{ + Kind: "Deployment", + APIVersion: appsv1.SchemeGroupVersion.String(), + }, + Spec: appsv1.DeploymentSpec{ + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, + }, + }, dpa: &oadpv1alpha1.DataProtectionApplication{ ObjectMeta: metav1.ObjectMeta{ Name: "test-Velero-CR", @@ -1720,8 +1251,18 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { Spec: oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ Velero: &oadpv1alpha1.VeleroConfig{ - LogLevel: logrus.InfoLevel.String(), - ResourceTimeout: "5m", + PodConfig: &oadpv1alpha1.PodConfig{ + ResourceAllocations: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("2"), + corev1.ResourceMemory: resource.MustParse("700Mi"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("1"), + corev1.ResourceMemory: resource.MustParse("256Mi"), + }, + }, + }, }, }, }, @@ -1731,49 +1272,17 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "test-velero-deployment", Namespace: "test-ns", - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, + Labels: veleroDeploymentLabel, }, TypeMeta: metav1.TypeMeta{ Kind: "Deployment", APIVersion: appsv1.SchemeGroupVersion.String(), }, Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, Replicas: pointer.Int32(1), Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - Annotations: map[string]string{ - "prometheus.io/scrape": "true", - "prometheus.io/port": "8085", - "prometheus.io/path": "/metrics", - }, - }, + ObjectMeta: veleroPodObjectMeta, Spec: corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyAlways, ServiceAccountName: common.Velero, @@ -1782,84 +1291,27 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { Name: common.Velero, Image: common.VeleroImage, ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - }, - }, + Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("2"), + corev1.ResourceMemory: resource.MustParse("700Mi"), + }, Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), + corev1.ResourceCPU: resource.MustParse("1"), + corev1.ResourceMemory: resource.MustParse("256Mi"), }, }, Command: []string{"/velero"}, Args: []string{ "server", "--fs-backup-timeout=1h", - "--log-level", - logrus.InfoLevel.String(), - "--resource-timeout=5m", - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "plugins", - MountPath: "/plugins", - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - }, - Env: []corev1.EnvVar{ - { - Name: common.VeleroScratchDirEnvKey, - Value: "/scratch", - }, - { - Name: common.VeleroNamespaceEnvKey, - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: common.LDLibraryPathEnvKey, - Value: "/plugins", - }, - { - Name: "OPENSHIFT_IMAGESTREAM_BACKUP", - Value: "true", - }, - }, - }, - }, - Volumes: []corev1.Volume{ - { - Name: "plugins", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, }, + VolumeMounts: baseVolumeMounts, + Env: baseEnvVars, }, }, + Volumes: baseVolumes, InitContainers: []corev1.Container{}, }, }, @@ -1867,24 +1319,18 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { }, }, { - name: "given valid DPA CR and log level is defined incorrectly error is returned", + name: "given valid DPA CR, velero deployment resource customization only cpu limit", veleroDeployment: &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: "test-velero-deployment", Namespace: "test-ns", }, + TypeMeta: metav1.TypeMeta{ + Kind: "Deployment", + APIVersion: appsv1.SchemeGroupVersion.String(), + }, Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, }, }, dpa: &oadpv1alpha1.DataProtectionApplication{ @@ -1895,16 +1341,69 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { Spec: oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ Velero: &oadpv1alpha1.VeleroConfig{ - LogLevel: logrus.InfoLevel.String() + "typo", + PodConfig: &oadpv1alpha1.PodConfig{ + ResourceAllocations: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("2"), + }, + }, + }, + }, + }, + }, + }, + wantErr: false, + wantVeleroDeployment: &appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-velero-deployment", + Namespace: "test-ns", + Labels: veleroDeploymentLabel, + }, + TypeMeta: metav1.TypeMeta{ + Kind: "Deployment", + APIVersion: appsv1.SchemeGroupVersion.String(), + }, + Spec: appsv1.DeploymentSpec{ + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, + Replicas: pointer.Int32(1), + Template: corev1.PodTemplateSpec{ + ObjectMeta: veleroPodObjectMeta, + Spec: corev1.PodSpec{ + RestartPolicy: corev1.RestartPolicyAlways, + ServiceAccountName: common.Velero, + Containers: []corev1.Container{ + { + Name: common.Velero, + Image: common.VeleroImage, + ImagePullPolicy: corev1.PullAlways, + Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("2"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("500m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + }, + Command: []string{"/velero"}, + Args: []string{ + "server", + "--fs-backup-timeout=1h", + }, + VolumeMounts: baseVolumeMounts, + Env: baseEnvVars, + }, + }, + Volumes: baseVolumes, + InitContainers: []corev1.Container{}, }, }, }, }, - wantErr: true, - wantVeleroDeployment: nil, }, { - name: "given valid DPA CR, velero deployment resource customization", + name: "given valid DPA CR, velero deployment resource customization only cpu request", veleroDeployment: &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: "test-velero-deployment", @@ -1915,17 +1414,7 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { APIVersion: appsv1.SchemeGroupVersion.String(), }, Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, }, }, dpa: &oadpv1alpha1.DataProtectionApplication{ @@ -1938,13 +1427,8 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { Velero: &oadpv1alpha1.VeleroConfig{ PodConfig: &oadpv1alpha1.PodConfig{ ResourceAllocations: corev1.ResourceRequirements{ - Limits: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("2"), - corev1.ResourceMemory: resource.MustParse("700Mi"), - }, Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("1"), - corev1.ResourceMemory: resource.MustParse("256Mi"), + corev1.ResourceCPU: resource.MustParse("2"), }, }, }, @@ -1957,49 +1441,17 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "test-velero-deployment", Namespace: "test-ns", - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, + Labels: veleroDeploymentLabel, }, TypeMeta: metav1.TypeMeta{ Kind: "Deployment", APIVersion: appsv1.SchemeGroupVersion.String(), }, Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, Replicas: pointer.Int32(1), Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - Annotations: map[string]string{ - "prometheus.io/scrape": "true", - "prometheus.io/port": "8085", - "prometheus.io/path": "/metrics", - }, - }, + ObjectMeta: veleroPodObjectMeta, Spec: corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyAlways, ServiceAccountName: common.Velero, @@ -2008,20 +1460,11 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { Name: common.Velero, Image: common.VeleroImage, ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - }, - }, + Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, Resources: corev1.ResourceRequirements{ - Limits: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("2"), - corev1.ResourceMemory: resource.MustParse("700Mi"), - }, Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("1"), - corev1.ResourceMemory: resource.MustParse("256Mi"), + corev1.ResourceCPU: resource.MustParse("2"), + corev1.ResourceMemory: resource.MustParse("128Mi"), }, }, Command: []string{"/velero"}, @@ -2029,64 +1472,11 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { "server", "--fs-backup-timeout=1h", }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "plugins", - MountPath: "/plugins", - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - }, - Env: []corev1.EnvVar{ - { - Name: common.VeleroScratchDirEnvKey, - Value: "/scratch", - }, - { - Name: common.VeleroNamespaceEnvKey, - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: common.LDLibraryPathEnvKey, - Value: "/plugins", - }, - { - Name: "OPENSHIFT_IMAGESTREAM_BACKUP", - Value: "true", - }, - }, - }, - }, - Volumes: []corev1.Volume{ - { - Name: "plugins", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, + VolumeMounts: baseVolumeMounts, + Env: baseEnvVars, }, }, + Volumes: baseVolumes, InitContainers: []corev1.Container{}, }, }, @@ -2094,7 +1484,7 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { }, }, { - name: "given valid DPA CR, velero deployment resource customization only cpu limit", + name: "given valid DPA CR, velero deployment resource customization only memory request", veleroDeployment: &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: "test-velero-deployment", @@ -2105,17 +1495,7 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { APIVersion: appsv1.SchemeGroupVersion.String(), }, Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, }, }, dpa: &oadpv1alpha1.DataProtectionApplication{ @@ -2128,8 +1508,8 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { Velero: &oadpv1alpha1.VeleroConfig{ PodConfig: &oadpv1alpha1.PodConfig{ ResourceAllocations: corev1.ResourceRequirements{ - Limits: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("2"), + Requests: corev1.ResourceList{ + corev1.ResourceMemory: resource.MustParse("256Mi"), }, }, }, @@ -2142,49 +1522,17 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "test-velero-deployment", Namespace: "test-ns", - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, + Labels: veleroDeploymentLabel, }, TypeMeta: metav1.TypeMeta{ Kind: "Deployment", APIVersion: appsv1.SchemeGroupVersion.String(), }, Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, Replicas: pointer.Int32(1), Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - Annotations: map[string]string{ - "prometheus.io/scrape": "true", - "prometheus.io/port": "8085", - "prometheus.io/path": "/metrics", - }, - }, + ObjectMeta: veleroPodObjectMeta, Spec: corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyAlways, ServiceAccountName: common.Velero, @@ -2193,19 +1541,11 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { Name: common.Velero, Image: common.VeleroImage, ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - }, - }, + Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, Resources: corev1.ResourceRequirements{ - Limits: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("2"), - }, Requests: corev1.ResourceList{ corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), + corev1.ResourceMemory: resource.MustParse("256Mi"), }, }, Command: []string{"/velero"}, @@ -2213,64 +1553,11 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { "server", "--fs-backup-timeout=1h", }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "plugins", - MountPath: "/plugins", - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - }, - Env: []corev1.EnvVar{ - { - Name: common.VeleroScratchDirEnvKey, - Value: "/scratch", - }, - { - Name: common.VeleroNamespaceEnvKey, - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: common.LDLibraryPathEnvKey, - Value: "/plugins", - }, - { - Name: "OPENSHIFT_IMAGESTREAM_BACKUP", - Value: "true", - }, - }, - }, - }, - Volumes: []corev1.Volume{ - { - Name: "plugins", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, + VolumeMounts: baseVolumeMounts, + Env: baseEnvVars, }, }, + Volumes: baseVolumes, InitContainers: []corev1.Container{}, }, }, @@ -2278,7 +1565,7 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { }, }, { - name: "given valid DPA CR, velero deployment resource customization only cpu request", + name: "given valid DPA CR, velero deployment resource customization only memory limit", veleroDeployment: &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: "test-velero-deployment", @@ -2289,17 +1576,7 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { APIVersion: appsv1.SchemeGroupVersion.String(), }, Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, }, }, dpa: &oadpv1alpha1.DataProtectionApplication{ @@ -2312,8 +1589,8 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { Velero: &oadpv1alpha1.VeleroConfig{ PodConfig: &oadpv1alpha1.PodConfig{ ResourceAllocations: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("2"), + Limits: corev1.ResourceList{ + corev1.ResourceMemory: resource.MustParse("128Mi"), }, }, }, @@ -2326,49 +1603,17 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "test-velero-deployment", Namespace: "test-ns", - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, + Labels: veleroDeploymentLabel, }, TypeMeta: metav1.TypeMeta{ Kind: "Deployment", APIVersion: appsv1.SchemeGroupVersion.String(), }, Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, Replicas: pointer.Int32(1), Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - Annotations: map[string]string{ - "prometheus.io/scrape": "true", - "prometheus.io/port": "8085", - "prometheus.io/path": "/metrics", - }, - }, + ObjectMeta: veleroPodObjectMeta, Spec: corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyAlways, ServiceAccountName: common.Velero, @@ -2377,15 +1622,13 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { Name: common.Velero, Image: common.VeleroImage, ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - }, - }, + Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("2"), + corev1.ResourceCPU: resource.MustParse("500m"), corev1.ResourceMemory: resource.MustParse("128Mi"), }, }, @@ -2394,64 +1637,11 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { "server", "--fs-backup-timeout=1h", }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "plugins", - MountPath: "/plugins", - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - }, - Env: []corev1.EnvVar{ - { - Name: common.VeleroScratchDirEnvKey, - Value: "/scratch", - }, - { - Name: common.VeleroNamespaceEnvKey, - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: common.LDLibraryPathEnvKey, - Value: "/plugins", - }, - { - Name: "OPENSHIFT_IMAGESTREAM_BACKUP", - Value: "true", - }, - }, - }, - }, - Volumes: []corev1.Volume{ - { - Name: "plugins", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, + VolumeMounts: baseVolumeMounts, + Env: baseEnvVars, }, }, + Volumes: baseVolumes, InitContainers: []corev1.Container{}, }, }, @@ -2459,7 +1649,7 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { }, }, { - name: "given valid DPA CR, velero deployment resource customization only memory request", + name: "given valid DPA CR, velero deployment tolerations", veleroDeployment: &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: "test-velero-deployment", @@ -2470,17 +1660,7 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { APIVersion: appsv1.SchemeGroupVersion.String(), }, Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, }, }, dpa: &oadpv1alpha1.DataProtectionApplication{ @@ -2493,10 +1673,23 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { Velero: &oadpv1alpha1.VeleroConfig{ PodConfig: &oadpv1alpha1.PodConfig{ ResourceAllocations: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("2"), + corev1.ResourceMemory: resource.MustParse("700Mi"), + }, Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("1"), corev1.ResourceMemory: resource.MustParse("256Mi"), }, }, + Tolerations: []corev1.Toleration{ + { + Key: "key1", + Operator: "Equal", + Value: "value1", + Effect: "NoSchedule", + }, + }, }, }, }, @@ -2512,8 +1705,8 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { "app.kubernetes.io/instance": "test-Velero-CR", "app.kubernetes.io/managed-by": common.OADPOperator, "app.kubernetes.io/component": Server, - "component": "velero", oadpv1alpha1.OadpOperatorLabel: "True", + "component": "velero", }, }, TypeMeta: metav1.TypeMeta{ @@ -2521,52 +1714,37 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { APIVersion: appsv1.SchemeGroupVersion.String(), }, Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, Replicas: pointer.Int32(1), Template: corev1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - Annotations: map[string]string{ - "prometheus.io/scrape": "true", - "prometheus.io/port": "8085", - "prometheus.io/path": "/metrics", - }, + Labels: veleroDeploymentMatchLabels, + Annotations: veleroPodAnnotations, }, Spec: corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyAlways, ServiceAccountName: common.Velero, + Tolerations: []corev1.Toleration{ + { + Key: "key1", + Operator: "Equal", + Value: "value1", + Effect: "NoSchedule", + }, + }, Containers: []corev1.Container{ { Name: common.Velero, Image: common.VeleroImage, ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - }, - }, + Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("2"), + corev1.ResourceMemory: resource.MustParse("700Mi"), + }, Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), + corev1.ResourceCPU: resource.MustParse("1"), corev1.ResourceMemory: resource.MustParse("256Mi"), }, }, @@ -2575,64 +1753,11 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { "server", "--fs-backup-timeout=1h", }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "plugins", - MountPath: "/plugins", - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - }, - Env: []corev1.EnvVar{ - { - Name: common.VeleroScratchDirEnvKey, - Value: "/scratch", - }, - { - Name: common.VeleroNamespaceEnvKey, - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: common.LDLibraryPathEnvKey, - Value: "/plugins", - }, - { - Name: "OPENSHIFT_IMAGESTREAM_BACKUP", - Value: "true", - }, - }, - }, - }, - Volumes: []corev1.Volume{ - { - Name: "plugins", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, + VolumeMounts: baseVolumeMounts, + Env: baseEnvVars, }, }, + Volumes: baseVolumes, InitContainers: []corev1.Container{}, }, }, @@ -2640,7 +1765,7 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { }, }, { - name: "given valid DPA CR, velero deployment resource customization only memory limit", + name: "given valid DPA CR, velero deployment nodeselector", veleroDeployment: &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: "test-velero-deployment", @@ -2651,17 +1776,7 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { APIVersion: appsv1.SchemeGroupVersion.String(), }, Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, }, }, dpa: &oadpv1alpha1.DataProtectionApplication{ @@ -2675,9 +1790,17 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { PodConfig: &oadpv1alpha1.PodConfig{ ResourceAllocations: corev1.ResourceRequirements{ Limits: corev1.ResourceList{ - corev1.ResourceMemory: resource.MustParse("128Mi"), + corev1.ResourceCPU: resource.MustParse("2"), + corev1.ResourceMemory: resource.MustParse("700Mi"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("1"), + corev1.ResourceMemory: resource.MustParse("256Mi"), }, }, + NodeSelector: map[string]string{ + "foo": "bar", + }, }, }, }, @@ -2693,8 +1816,8 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { "app.kubernetes.io/instance": "test-Velero-CR", "app.kubernetes.io/managed-by": common.OADPOperator, "app.kubernetes.io/component": Server, - "component": "velero", oadpv1alpha1.OadpOperatorLabel: "True", + "component": "velero", }, }, TypeMeta: metav1.TypeMeta{ @@ -2702,56 +1825,33 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { APIVersion: appsv1.SchemeGroupVersion.String(), }, Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, Replicas: pointer.Int32(1), Template: corev1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - Annotations: map[string]string{ - "prometheus.io/scrape": "true", - "prometheus.io/port": "8085", - "prometheus.io/path": "/metrics", - }, + Labels: veleroDeploymentMatchLabels, + Annotations: veleroPodAnnotations, }, Spec: corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyAlways, ServiceAccountName: common.Velero, + NodeSelector: map[string]string{ + "foo": "bar", + }, Containers: []corev1.Container{ { Name: common.Velero, Image: common.VeleroImage, ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - }, - }, + Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, Resources: corev1.ResourceRequirements{ Limits: corev1.ResourceList{ - corev1.ResourceMemory: resource.MustParse("128Mi"), + corev1.ResourceCPU: resource.MustParse("2"), + corev1.ResourceMemory: resource.MustParse("700Mi"), }, Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), + corev1.ResourceCPU: resource.MustParse("1"), + corev1.ResourceMemory: resource.MustParse("256Mi"), }, }, Command: []string{"/velero"}, @@ -2759,64 +1859,11 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { "server", "--fs-backup-timeout=1h", }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "plugins", - MountPath: "/plugins", - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - }, - Env: []corev1.EnvVar{ - { - Name: common.VeleroScratchDirEnvKey, - Value: "/scratch", - }, - { - Name: common.VeleroNamespaceEnvKey, - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: common.LDLibraryPathEnvKey, - Value: "/plugins", - }, - { - Name: "OPENSHIFT_IMAGESTREAM_BACKUP", - Value: "true", - }, - }, - }, - }, - Volumes: []corev1.Volume{ - { - Name: "plugins", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, + VolumeMounts: baseVolumeMounts, + Env: baseEnvVars, }, }, + Volumes: baseVolumes, InitContainers: []corev1.Container{}, }, }, @@ -2824,28 +1871,14 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { }, }, { - name: "given valid DPA CR, velero deployment tolerations", + name: "given valid DPA CR, appropriate velero deployment is build with aws plugin specific specs", veleroDeployment: &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: "test-velero-deployment", Namespace: "test-ns", }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - oadpv1alpha1.OadpOperatorLabel: "True", - "component": "velero", - "deploy": "velero", - }, - }, + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, }, }, dpa: &oadpv1alpha1.DataProtectionApplication{ @@ -2856,25 +1889,8 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { Spec: oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ Velero: &oadpv1alpha1.VeleroConfig{ - PodConfig: &oadpv1alpha1.PodConfig{ - ResourceAllocations: corev1.ResourceRequirements{ - Limits: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("2"), - corev1.ResourceMemory: resource.MustParse("700Mi"), - }, - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("1"), - corev1.ResourceMemory: resource.MustParse("256Mi"), - }, - }, - Tolerations: []corev1.Toleration{ - { - Key: "key1", - Operator: "Equal", - Value: "value1", - Effect: "NoSchedule", - }, - }, + DefaultPlugins: []oadpv1alpha1.DefaultPlugin{ + oadpv1alpha1.DefaultPluginAWS, }, }, }, @@ -2885,173 +1901,65 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "test-velero-deployment", Namespace: "test-ns", - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - oadpv1alpha1.OadpOperatorLabel: "True", - "component": "velero", - }, + Labels: veleroDeploymentLabel, }, TypeMeta: metav1.TypeMeta{ Kind: "Deployment", APIVersion: appsv1.SchemeGroupVersion.String(), }, Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - oadpv1alpha1.OadpOperatorLabel: "True", - "component": "velero", - "deploy": "velero", - }, - }, + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, Replicas: pointer.Int32(1), Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - oadpv1alpha1.OadpOperatorLabel: "True", - "component": "velero", - "deploy": "velero", - }, - Annotations: map[string]string{ - "prometheus.io/scrape": "true", - "prometheus.io/port": "8085", - "prometheus.io/path": "/metrics", - }, - }, + ObjectMeta: veleroPodObjectMeta, Spec: corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyAlways, ServiceAccountName: common.Velero, - Tolerations: []corev1.Toleration{ - { - Key: "key1", - Operator: "Equal", - Value: "value1", - Effect: "NoSchedule", - }, - }, Containers: []corev1.Container{ { Name: common.Velero, Image: common.VeleroImage, ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - }, - }, - Resources: corev1.ResourceRequirements{ - Limits: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("2"), - corev1.ResourceMemory: resource.MustParse("700Mi"), - }, - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("1"), - corev1.ResourceMemory: resource.MustParse("256Mi"), - }, - }, - Command: []string{"/velero"}, + Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, + Resources: corev1.ResourceRequirements{Requests: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("500m"), corev1.ResourceMemory: resource.MustParse("128Mi")}}, + Command: []string{"/velero"}, Args: []string{ "server", "--fs-backup-timeout=1h", }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "plugins", - MountPath: "/plugins", - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - }, - Env: []corev1.EnvVar{ - { - Name: common.VeleroScratchDirEnvKey, - Value: "/scratch", - }, - { - Name: common.VeleroNamespaceEnvKey, - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: common.LDLibraryPathEnvKey, - Value: "/plugins", - }, - { - Name: "OPENSHIFT_IMAGESTREAM_BACKUP", - Value: "true", - }, - }, + VolumeMounts: append(baseVolumeMounts, []corev1.VolumeMount{ + {Name: "cloud-credentials", MountPath: "/credentials"}, + }...), + Env: append(baseEnvVars, []corev1.EnvVar{ + {Name: common.AWSSharedCredentialsFileEnvKey, Value: "/credentials/cloud"}, + }...), }, }, - Volumes: []corev1.Volume{ - { - Name: "plugins", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, + Volumes: append(baseVolumes, []corev1.Volume{{ + Name: "cloud-credentials", + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: "cloud-credentials", }, }, + }}...), + InitContainers: []corev1.Container{ + pluginContainer(common.VeleroPluginForAWS, common.AWSPluginImage), }, - InitContainers: []corev1.Container{}, }, }, }, }, }, { - name: "given valid DPA CR, velero deployment nodeselector", + name: "given valid DPA CR, appropriate velero deployment is build with aws and kubevirt plugin specific specs", veleroDeployment: &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: "test-velero-deployment", Namespace: "test-ns", }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - oadpv1alpha1.OadpOperatorLabel: "True", - "component": "velero", - "deploy": "velero", - }, - }, + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, }, }, dpa: &oadpv1alpha1.DataProtectionApplication{ @@ -3062,20 +1970,9 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { Spec: oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ Velero: &oadpv1alpha1.VeleroConfig{ - PodConfig: &oadpv1alpha1.PodConfig{ - ResourceAllocations: corev1.ResourceRequirements{ - Limits: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("2"), - corev1.ResourceMemory: resource.MustParse("700Mi"), - }, - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("1"), - corev1.ResourceMemory: resource.MustParse("256Mi"), - }, - }, - NodeSelector: map[string]string{ - "foo": "bar", - }, + DefaultPlugins: []oadpv1alpha1.DefaultPlugin{ + oadpv1alpha1.DefaultPluginAWS, + oadpv1alpha1.DefaultPluginKubeVirt, }, }, }, @@ -3086,164 +1983,69 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "test-velero-deployment", Namespace: "test-ns", - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - oadpv1alpha1.OadpOperatorLabel: "True", - "component": "velero", - }, + Labels: veleroDeploymentLabel, }, TypeMeta: metav1.TypeMeta{ Kind: "Deployment", APIVersion: appsv1.SchemeGroupVersion.String(), }, Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - oadpv1alpha1.OadpOperatorLabel: "True", - "component": "velero", - "deploy": "velero", - }, - }, + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, Replicas: pointer.Int32(1), Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - oadpv1alpha1.OadpOperatorLabel: "True", - "component": "velero", - "deploy": "velero", - }, - Annotations: map[string]string{ - "prometheus.io/scrape": "true", - "prometheus.io/port": "8085", - "prometheus.io/path": "/metrics", - }, - }, + ObjectMeta: veleroPodObjectMeta, Spec: corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyAlways, ServiceAccountName: common.Velero, - NodeSelector: map[string]string{ - "foo": "bar", - }, Containers: []corev1.Container{ { Name: common.Velero, Image: common.VeleroImage, ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - }, - }, - Resources: corev1.ResourceRequirements{ - Limits: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("2"), - corev1.ResourceMemory: resource.MustParse("700Mi"), - }, - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("1"), - corev1.ResourceMemory: resource.MustParse("256Mi"), - }, - }, - Command: []string{"/velero"}, + Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, + Resources: corev1.ResourceRequirements{Requests: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("500m"), corev1.ResourceMemory: resource.MustParse("128Mi")}}, + Command: []string{"/velero"}, Args: []string{ "server", "--fs-backup-timeout=1h", }, VolumeMounts: []corev1.VolumeMount{ - { - Name: "plugins", - MountPath: "/plugins", - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - }, - Env: []corev1.EnvVar{ - { - Name: common.VeleroScratchDirEnvKey, - Value: "/scratch", - }, - { - Name: common.VeleroNamespaceEnvKey, - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: common.LDLibraryPathEnvKey, - Value: "/plugins", - }, - { - Name: "OPENSHIFT_IMAGESTREAM_BACKUP", - Value: "true", - }, + {Name: "plugins", MountPath: "/plugins"}, + {Name: "scratch", MountPath: "/scratch"}, + {Name: "certs", MountPath: "/etc/ssl/certs"}, + {Name: "cloud-credentials", MountPath: "/credentials"}, }, + Env: append(baseEnvVars, []corev1.EnvVar{ + {Name: common.AWSSharedCredentialsFileEnvKey, Value: "/credentials/cloud"}, + }...), }, }, - Volumes: []corev1.Volume{ - { - Name: "plugins", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, + Volumes: append(baseVolumes, []corev1.Volume{{ + Name: "cloud-credentials", + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: "cloud-credentials", }, }, + }}...), + InitContainers: []corev1.Container{ + pluginContainer(common.VeleroPluginForAWS, common.AWSPluginImage), + pluginContainer(common.KubeVirtPlugin, common.KubeVirtPluginImage), }, - InitContainers: []corev1.Container{}, }, }, }, }, }, { - name: "given valid DPA CR, appropriate velero deployment is build with aws plugin specific specs", + name: "given valid DPA CR with annotations, appropriate velero deployment is build with aws plugin specific specs", veleroDeployment: &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: "test-velero-deployment", Namespace: "test-ns", }, Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, }, }, dpa: &oadpv1alpha1.DataProtectionApplication{ @@ -3259,6 +2061,9 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { }, }, }, + PodAnnotations: map[string]string{ + "test-annotation": "awesome annotation", + }, }, }, wantErr: false, @@ -3266,48 +2071,23 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "test-velero-deployment", Namespace: "test-ns", - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, + Labels: veleroDeploymentLabel, }, TypeMeta: metav1.TypeMeta{ Kind: "Deployment", APIVersion: appsv1.SchemeGroupVersion.String(), }, Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, Replicas: pointer.Int32(1), Template: corev1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - Annotations: map[string]string{ - "prometheus.io/scrape": "true", - "prometheus.io/port": "8085", - "prometheus.io/path": "/metrics", - }, + Labels: veleroDeploymentMatchLabels, + Annotations: common.AppendTTMapAsCopy(veleroPodAnnotations, + map[string]string{ + "test-annotation": "awesome annotation", + }, + ), }, Spec: corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyAlways, @@ -3317,117 +2097,34 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { Name: common.Velero, Image: common.VeleroImage, ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - }, - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - Command: []string{"/velero"}, + Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, + Resources: corev1.ResourceRequirements{Requests: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("500m"), corev1.ResourceMemory: resource.MustParse("128Mi")}}, + Command: []string{"/velero"}, Args: []string{ "server", "--fs-backup-timeout=1h", }, VolumeMounts: []corev1.VolumeMount{ - { - Name: "plugins", - MountPath: "/plugins", - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - { - Name: "cloud-credentials", - MountPath: "/credentials", - }, - }, - Env: []corev1.EnvVar{ - { - Name: common.VeleroScratchDirEnvKey, - Value: "/scratch", - }, - { - Name: common.VeleroNamespaceEnvKey, - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: common.LDLibraryPathEnvKey, - Value: "/plugins", - }, - { - Name: "OPENSHIFT_IMAGESTREAM_BACKUP", - Value: "true", - }, - { - Name: common.AWSSharedCredentialsFileEnvKey, - Value: "/credentials/cloud", - }, + {Name: "plugins", MountPath: "/plugins"}, + {Name: "scratch", MountPath: "/scratch"}, + {Name: "certs", MountPath: "/etc/ssl/certs"}, + {Name: "cloud-credentials", MountPath: "/credentials"}, }, + Env: append(baseEnvVars, []corev1.EnvVar{ + {Name: common.AWSSharedCredentialsFileEnvKey, Value: "/credentials/cloud"}, + }...), }, }, - Volumes: []corev1.Volume{ - { - Name: "plugins", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "cloud-credentials", - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: "cloud-credentials", - }, + Volumes: append(baseVolumes, []corev1.Volume{{ + Name: "cloud-credentials", + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: "cloud-credentials", }, }, - }, + }}...), InitContainers: []corev1.Container{ - { - Image: common.AWSPluginImage, - Name: common.VeleroPluginForAWS, - ImagePullPolicy: corev1.PullAlways, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - TerminationMessagePath: "/dev/termination-log", - TerminationMessagePolicy: "File", - VolumeMounts: []corev1.VolumeMount{ - { - MountPath: "/target", - Name: "plugins", - }, - }, - }, + pluginContainer(common.VeleroPluginForAWS, common.AWSPluginImage), }, }, }, @@ -3435,466 +2132,14 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { }, }, { - name: "given valid DPA CR, appropriate velero deployment is build with aws and kubevirt plugin specific specs", + name: "given valid DPA CR with PodDNS Policy/Config, annotations, appropriate velero deployment is build with aws plugin specific specs", veleroDeployment: &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: "test-velero-deployment", Namespace: "test-ns", }, Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", - }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ - Configuration: &oadpv1alpha1.ApplicationConfig{ - Velero: &oadpv1alpha1.VeleroConfig{ - DefaultPlugins: []oadpv1alpha1.DefaultPlugin{ - oadpv1alpha1.DefaultPluginAWS, - oadpv1alpha1.DefaultPluginKubeVirt, - }, - }, - }, - }, - }, - wantErr: false, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - Replicas: pointer.Int32(1), - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - Annotations: map[string]string{ - "prometheus.io/scrape": "true", - "prometheus.io/port": "8085", - "prometheus.io/path": "/metrics", - }, - }, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - }, - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - Command: []string{"/velero"}, - Args: []string{ - "server", - "--fs-backup-timeout=1h", - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "plugins", - MountPath: "/plugins", - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - { - Name: "cloud-credentials", - MountPath: "/credentials", - }, - }, - Env: []corev1.EnvVar{ - { - Name: common.VeleroScratchDirEnvKey, - Value: "/scratch", - }, - { - Name: common.VeleroNamespaceEnvKey, - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: common.LDLibraryPathEnvKey, - Value: "/plugins", - }, - { - Name: "OPENSHIFT_IMAGESTREAM_BACKUP", - Value: "true", - }, - { - Name: common.AWSSharedCredentialsFileEnvKey, - Value: "/credentials/cloud", - }, - }, - }, - }, - Volumes: []corev1.Volume{ - { - Name: "plugins", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "cloud-credentials", - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: "cloud-credentials", - }, - }, - }, - }, - InitContainers: []corev1.Container{ - { - Image: common.AWSPluginImage, - Name: common.VeleroPluginForAWS, - ImagePullPolicy: corev1.PullAlways, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - TerminationMessagePath: "/dev/termination-log", - TerminationMessagePolicy: "File", - VolumeMounts: []corev1.VolumeMount{ - { - MountPath: "/target", - Name: "plugins", - }, - }, - }, - { - Image: common.KubeVirtPluginImage, - Name: common.KubeVirtPlugin, - ImagePullPolicy: corev1.PullAlways, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - TerminationMessagePath: "/dev/termination-log", - TerminationMessagePolicy: "File", - VolumeMounts: []corev1.VolumeMount{ - { - MountPath: "/target", - Name: "plugins", - }, - }, - }, - }, - }, - }, - }, - }, - }, - { - name: "given valid DPA CR with annotations, appropriate velero deployment is build with aws plugin specific specs", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", - }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ - Configuration: &oadpv1alpha1.ApplicationConfig{ - Velero: &oadpv1alpha1.VeleroConfig{ - DefaultPlugins: []oadpv1alpha1.DefaultPlugin{ - oadpv1alpha1.DefaultPluginAWS, - }, - }, - }, - PodAnnotations: map[string]string{ - "test-annotation": "awesome annotation", - }, - }, - }, - wantErr: false, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - Replicas: pointer.Int32(1), - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - Annotations: map[string]string{ - "prometheus.io/scrape": "true", - "prometheus.io/port": "8085", - "prometheus.io/path": "/metrics", - "test-annotation": "awesome annotation", - }, - }, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - }, - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - Command: []string{"/velero"}, - Args: []string{ - "server", - "--fs-backup-timeout=1h", - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "plugins", - MountPath: "/plugins", - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - { - Name: "cloud-credentials", - MountPath: "/credentials", - }, - }, - Env: []corev1.EnvVar{ - { - Name: common.VeleroScratchDirEnvKey, - Value: "/scratch", - }, - { - Name: common.VeleroNamespaceEnvKey, - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: common.LDLibraryPathEnvKey, - Value: "/plugins", - }, - { - Name: "OPENSHIFT_IMAGESTREAM_BACKUP", - Value: "true", - }, - { - Name: common.AWSSharedCredentialsFileEnvKey, - Value: "/credentials/cloud", - }, - }, - }, - }, - Volumes: []corev1.Volume{ - { - Name: "plugins", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "cloud-credentials", - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: "cloud-credentials", - }, - }, - }, - }, - InitContainers: []corev1.Container{ - { - Image: common.AWSPluginImage, - Name: common.VeleroPluginForAWS, - ImagePullPolicy: corev1.PullAlways, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - TerminationMessagePath: "/dev/termination-log", - TerminationMessagePolicy: "File", - VolumeMounts: []corev1.VolumeMount{ - { - MountPath: "/target", - Name: "plugins", - }, - }, - }, - }, - }, - }, - }, - }, - }, - { - name: "given valid DPA CR with PodDNS Policy/Config, annotations, appropriate velero deployment is build with aws plugin specific specs", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, }, }, dpa: &oadpv1alpha1.DataProtectionApplication{ @@ -3920,202 +2165,84 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { "8.8.8.8", }, Options: []corev1.PodDNSConfigOption{ - { - Name: "ndots", - Value: pointer.String("2"), - }, - { - Name: "edns0", - }, - }, - }, - }, - }, - wantErr: false, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - Replicas: pointer.Int32(1), - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - Annotations: map[string]string{ - "prometheus.io/scrape": "true", - "prometheus.io/port": "8085", - "prometheus.io/path": "/metrics", - "test-annotation": "awesome annotation", - }, - }, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - DNSPolicy: "None", - DNSConfig: &corev1.PodDNSConfig{ - Nameservers: []string{ - "1.1.1.1", - "8.8.8.8", - }, - Options: []corev1.PodDNSConfigOption{ - { - Name: "ndots", - Value: pointer.String("2"), - }, - { - Name: "edns0", - }, - }, - }, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - }, - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - Command: []string{"/velero"}, - Args: []string{ - "server", - "--fs-backup-timeout=1h", - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "plugins", - MountPath: "/plugins", - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - { - Name: "cloud-credentials", - MountPath: "/credentials", - }, - }, - Env: []corev1.EnvVar{ - { - Name: common.VeleroScratchDirEnvKey, - Value: "/scratch", - }, - { - Name: common.VeleroNamespaceEnvKey, - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: common.LDLibraryPathEnvKey, - Value: "/plugins", - }, - { - Name: "OPENSHIFT_IMAGESTREAM_BACKUP", - Value: "true", - }, - { - Name: common.AWSSharedCredentialsFileEnvKey, - Value: "/credentials/cloud", - }, - }, - }, + {Name: "ndots", Value: pointer.String("2")}, + { + Name: "edns0", }, - Volumes: []corev1.Volume{ - { - Name: "plugins", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, + }, + }, + }, + }, + wantErr: false, + wantVeleroDeployment: &appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-velero-deployment", + Namespace: "test-ns", + Labels: veleroDeploymentLabel, + }, + TypeMeta: metav1.TypeMeta{ + Kind: "Deployment", + APIVersion: appsv1.SchemeGroupVersion.String(), + }, + Spec: appsv1.DeploymentSpec{ + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, + Replicas: pointer.Int32(1), + Template: corev1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: veleroDeploymentMatchLabels, + Annotations: common.AppendTTMapAsCopy(veleroPodAnnotations, + map[string]string{ + "test-annotation": "awesome annotation", }, - { - Name: "cloud-credentials", - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: "cloud-credentials", - }, + ), + }, + Spec: corev1.PodSpec{ + RestartPolicy: corev1.RestartPolicyAlways, + ServiceAccountName: common.Velero, + DNSPolicy: "None", + DNSConfig: &corev1.PodDNSConfig{ + Nameservers: []string{"1.1.1.1", "8.8.8.8"}, + Options: []corev1.PodDNSConfigOption{ + {Name: "ndots", Value: pointer.String("2")}, + { + Name: "edns0", }, }, }, - InitContainers: []corev1.Container{ + Containers: []corev1.Container{ { - Image: common.AWSPluginImage, - Name: common.VeleroPluginForAWS, + Name: common.Velero, + Image: common.VeleroImage, ImagePullPolicy: corev1.PullAlways, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, + Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, + Resources: corev1.ResourceRequirements{Requests: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("500m"), corev1.ResourceMemory: resource.MustParse("128Mi")}}, + Command: []string{"/velero"}, + Args: []string{ + "server", + "--fs-backup-timeout=1h", }, - TerminationMessagePath: "/dev/termination-log", - TerminationMessagePolicy: "File", VolumeMounts: []corev1.VolumeMount{ - { - MountPath: "/target", - Name: "plugins", - }, + {Name: "plugins", MountPath: "/plugins"}, + {Name: "scratch", MountPath: "/scratch"}, + {Name: "certs", MountPath: "/etc/ssl/certs"}, + {Name: "cloud-credentials", MountPath: "/credentials"}, }, + Env: append(baseEnvVars, []corev1.EnvVar{ + {Name: common.AWSSharedCredentialsFileEnvKey, Value: "/credentials/cloud"}, + }...), }, }, + Volumes: append(baseVolumes, []corev1.Volume{{ + Name: "cloud-credentials", + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: "cloud-credentials", + }, + }, + }}...), + InitContainers: []corev1.Container{ + pluginContainer(common.VeleroPluginForAWS, common.AWSPluginImage), + }, }, }, }, @@ -4129,17 +2256,7 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { Namespace: "test-ns", }, Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, }, }, dpa: &oadpv1alpha1.DataProtectionApplication{ @@ -4180,49 +2297,17 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "test-velero-deployment", Namespace: "test-ns", - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, + Labels: veleroDeploymentLabel, }, TypeMeta: metav1.TypeMeta{ Kind: "Deployment", APIVersion: appsv1.SchemeGroupVersion.String(), }, Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, Replicas: pointer.Int32(1), Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - Annotations: map[string]string{ - "prometheus.io/scrape": "true", - "prometheus.io/port": "8085", - "prometheus.io/path": "/metrics", - }, - }, + ObjectMeta: veleroPodObjectMeta, Spec: corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyAlways, ServiceAccountName: common.Velero, @@ -4231,85 +2316,27 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { Name: common.Velero, Image: common.VeleroImage, ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - }, - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - Command: []string{"/velero"}, + Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, + Resources: corev1.ResourceRequirements{Requests: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("500m"), corev1.ResourceMemory: resource.MustParse("128Mi")}}, + Command: []string{"/velero"}, Args: []string{ "server", "--fs-backup-timeout=1h", }, VolumeMounts: []corev1.VolumeMount{ - { - Name: "plugins", - MountPath: "/plugins", - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, + {Name: "plugins", MountPath: "/plugins"}, + {Name: "scratch", MountPath: "/scratch"}, + {Name: "certs", MountPath: "/etc/ssl/certs"}, { Name: "bound-sa-token", MountPath: "/var/run/secrets/openshift/serviceaccount", ReadOnly: true, }, }, - Env: []corev1.EnvVar{ - { - Name: common.VeleroScratchDirEnvKey, - Value: "/scratch", - }, - { - Name: common.VeleroNamespaceEnvKey, - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: common.LDLibraryPathEnvKey, - Value: "/plugins", - }, - { - Name: "OPENSHIFT_IMAGESTREAM_BACKUP", - Value: "true", - }, - }, + Env: baseEnvVars, }, }, - Volumes: []corev1.Volume{ - { - Name: "plugins", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, + Volumes: append(baseVolumes, []corev1.Volume{ { Name: "bound-sa-token", VolumeSource: corev1.VolumeSource{ @@ -4326,28 +2353,9 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { }, }, }, - }, - }, + }}...), InitContainers: []corev1.Container{ - { - Image: common.AWSPluginImage, - Name: common.VeleroPluginForAWS, - ImagePullPolicy: corev1.PullAlways, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - TerminationMessagePath: "/dev/termination-log", - TerminationMessagePolicy: "File", - VolumeMounts: []corev1.VolumeMount{ - { - MountPath: "/target", - Name: "plugins", - }, - }, - }, + pluginContainer(common.VeleroPluginForAWS, common.AWSPluginImage), }, }, }, @@ -4365,6 +2373,81 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { }, }, }, + { + name: "velero with custom metrics address", + veleroDeployment: &appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-velero-deployment", + Namespace: "test-ns", + }, + Spec: appsv1.DeploymentSpec{ + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, + }, + }, + dpa: &oadpv1alpha1.DataProtectionApplication{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-Velero-CR", + Namespace: "test-ns", + }, + Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{ + Args: &server.Args{ + ServerConfig: server.ServerConfig{ + MetricsAddress: ":" + strconv.Itoa(int(argsMetricsPortTest)), + }, + }, + }, + }, + }, + }, + wantVeleroDeployment: &appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-velero-deployment", + Namespace: "test-ns", + Labels: veleroDeploymentLabel, + }, + TypeMeta: metav1.TypeMeta{ + Kind: "Deployment", + APIVersion: appsv1.SchemeGroupVersion.String(), + }, + Spec: appsv1.DeploymentSpec{ + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, + Replicas: pointer.Int32(1), + Template: corev1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: veleroDeploymentMatchLabels, + Annotations: common.AppendTTMapAsCopy(veleroPodAnnotations, map[string]string{ + "prometheus.io/port": strconv.Itoa(int(argsMetricsPortTest)), + }), + }, + Spec: corev1.PodSpec{ + RestartPolicy: corev1.RestartPolicyAlways, + ServiceAccountName: common.Velero, + Containers: []corev1.Container{ + { + Name: common.Velero, + Image: common.VeleroImage, + ImagePullPolicy: corev1.PullAlways, + Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: argsMetricsPortTest}}, + Resources: corev1.ResourceRequirements{Requests: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("500m"), corev1.ResourceMemory: resource.MustParse("128Mi")}}, + Command: []string{"/velero"}, + Args: []string{ + "server", + "--metrics-address=:" + strconv.Itoa(int(argsMetricsPortTest)), + "--fs-backup-timeout=1h0m0s", + }, + VolumeMounts: baseVolumeMounts, + Env: baseEnvVars, + }, + }, + Volumes: baseVolumes, + InitContainers: []corev1.Container{}, + }, + }, + }, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -4522,7 +2605,7 @@ func Test_removeDuplicateValues(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := removeDuplicateValues(tt.args.slice); !reflect.DeepEqual(got, tt.want) { + if got := common.RemoveDuplicateValues(tt.args.slice); !reflect.DeepEqual(got, tt.want) { t.Errorf("removeDuplicateValues() = %v, want %v", got, tt.want) } }) diff --git a/go.mod b/go.mod index 23b76a9b4e..011fc8e4f0 100644 --- a/go.mod +++ b/go.mod @@ -26,20 +26,17 @@ require ( require ( github.com/backube/volsync v0.4.0 + github.com/deckarep/golang-set/v2 v2.3.0 github.com/google/go-cmp v0.5.9 github.com/konveyor/volume-snapshot-mover v0.0.0-20220725191622-4b360b792c3e ) require ( - github.com/deckarep/golang-set/v2 v2.1.0 - github.com/google/go-cmp v0.5.9 -) - -require ( - cloud.google.com/go v0.100.2 // indirect - cloud.google.com/go/compute v1.5.0 // indirect - cloud.google.com/go/iam v0.1.1 // indirect - cloud.google.com/go/storage v1.21.0 // indirect + cloud.google.com/go v0.105.0 // indirect + cloud.google.com/go/compute v1.13.0 // indirect + cloud.google.com/go/compute/metadata v0.2.1 // indirect + cloud.google.com/go/iam v0.7.0 // indirect + cloud.google.com/go/storage v1.27.0 // indirect github.com/Azure/azure-sdk-for-go v67.2.0+incompatible // indirect github.com/Azure/azure-sdk-for-go/sdk/azcore v0.21.1 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.3 // indirect @@ -56,7 +53,8 @@ require ( github.com/Azure/go-autorest/tracing v0.6.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/bombsimon/logrusr/v3 v3.0.0 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/chmduquesne/rollinghash v4.0.0+incompatible // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dimchansky/utfbom v1.1.1 // indirect @@ -77,13 +75,14 @@ require ( github.com/golang/protobuf v1.5.2 // indirect github.com/google/gnostic v0.6.9 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/googleapis/gax-go/v2 v2.2.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect + github.com/googleapis/gax-go/v2 v2.7.0 // indirect github.com/hashicorp/go-hclog v0.14.1 // indirect github.com/hashicorp/go-plugin v1.4.3 // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb // indirect github.com/imdario/mergo v0.3.13 // indirect - github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/inconshreveable/mousetrap v1.0.1 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/joho/godotenv v1.3.0 // indirect github.com/josharian/intern v1.0.0 // indirect @@ -96,7 +95,7 @@ require ( github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-isatty v0.0.14 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/minio/md5-simd v1.1.2 // indirect github.com/minio/minio-go/v7 v7.0.23 // indirect github.com/minio/sha256-simd v1.0.0 // indirect @@ -111,35 +110,36 @@ require ( github.com/oklog/run v1.0.0 // indirect github.com/pierrec/lz4 v2.6.1+incompatible // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/prometheus/client_golang v1.12.2 // indirect - github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.34.0 // indirect - github.com/prometheus/procfs v0.7.3 // indirect + github.com/prometheus/client_golang v1.14.0 // indirect + github.com/prometheus/client_model v0.3.0 // indirect + github.com/prometheus/common v0.39.0 // indirect + github.com/prometheus/procfs v0.9.0 // indirect + github.com/robfig/cron v1.1.0 // indirect github.com/rogpeppe/go-internal v1.9.0 // indirect github.com/rs/xid v1.3.0 // indirect - github.com/spf13/cobra v1.4.0 // indirect + github.com/spf13/cobra v1.6.1 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/zeebo/blake3 v0.2.3 // indirect - go.opencensus.io v0.23.0 // indirect - go.uber.org/atomic v1.9.0 // indirect - go.uber.org/multierr v1.8.0 // indirect - go.uber.org/zap v1.21.0 // indirect - golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd // indirect + go.opencensus.io v0.24.0 // indirect + go.uber.org/atomic v1.10.0 // indirect + go.uber.org/multierr v1.9.0 // indirect + go.uber.org/zap v1.24.0 // indirect + golang.org/x/crypto v0.6.0 // indirect golang.org/x/exp v0.0.0-20210916165020-5cb4fee858ee // indirect - golang.org/x/net v0.7.0 // indirect - golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb // indirect + golang.org/x/net v0.8.0 // indirect + golang.org/x/oauth2 v0.4.0 // indirect golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.5.0 // indirect - golang.org/x/term v0.5.0 // indirect - golang.org/x/text v0.7.0 // indirect - golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect - golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect + golang.org/x/sys v0.6.0 // indirect + golang.org/x/term v0.6.0 // indirect + golang.org/x/text v0.8.0 // indirect + golang.org/x/time v0.3.0 // indirect + golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect - google.golang.org/api v0.74.0 // indirect + google.golang.org/api v0.103.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb // indirect - google.golang.org/grpc v1.45.0 // indirect - google.golang.org/protobuf v1.28.0 // indirect + google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c // indirect + google.golang.org/grpc v1.50.1 // indirect + google.golang.org/protobuf v1.28.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.66.2 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect @@ -148,6 +148,7 @@ require ( k8s.io/cli-runtime v0.24.0 // indirect k8s.io/component-base v0.24.2 // indirect k8s.io/klog/v2 v2.70.1 // indirect + k8s.io/kube-aggregator v0.19.12 // indirect k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 // indirect sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect @@ -155,3 +156,10 @@ require ( ) replace github.com/vmware-tanzu/velero => github.com/openshift/velero v0.10.2-0.20230411180851-203d5bb613eb + +// // needed for util/clock without bumping replacing clock in velero +// replace ( +// k8s.io/apimachinery => k8s.io/apimachinery v0.24.13 +// k8s.io/client-go => k8s.io/client-go v0.24.13 +// sigs.k8s.io/controller-runtime => sigs.k8s.io/controller-runtime v0.12.3 +// ) diff --git a/go.sum b/go.sum index 18b0400841..28c4177db4 100644 --- a/go.sum +++ b/go.sum @@ -19,33 +19,24 @@ cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmW cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= -cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= -cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= -cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= -cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= -cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= -cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= -cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= -cloud.google.com/go v0.100.1/go.mod h1:fs4QogzfH5n2pBXBP9vRiU+eCny7lD2vmFZy79Iuw1U= -cloud.google.com/go v0.100.2 h1:t9Iw5QH5v4XtlEQaCtUY7x6sCABps8sW0acw7e2WQ6Y= -cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= +cloud.google.com/go v0.105.0 h1:DNtEKRBAAzeS4KyIory52wWHuClNaXJ5x1F7xa4q+5Y= +cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= -cloud.google.com/go/compute v1.2.0/go.mod h1:xlogom/6gr8RJGBe7nT2eGsQYAFUbbv8dbC29qE3Xmw= -cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= -cloud.google.com/go/compute v1.5.0 h1:b1zWmYuuHz7gO9kDcM/EpHGr06UgsYNRpNJzI2kFiLM= -cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= +cloud.google.com/go/compute v1.13.0 h1:AYrLkB8NPdDRslNp4Jxmzrhdr03fUAIDbiGFjLWowoU= +cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARyZtRXDJ8GE= +cloud.google.com/go/compute/metadata v0.2.1 h1:efOwf5ymceDhK6PKMnnrTHP4pppY5L22mle96M1yP48= +cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= -cloud.google.com/go/iam v0.1.1 h1:4CapQyNFjiksks1/x7jsvsygFPhihslYk5GptIrlX68= -cloud.google.com/go/iam v0.1.1/go.mod h1:CKqrcnI/suGpybEHxZ7BMehL0oA4LpdyJdUlTl9jVMw= +cloud.google.com/go/iam v0.7.0 h1:k4MuwOsS7zGJJ+QfZ5vBK8SgHBAvYN/23BWsiihJ1vs= +cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg= +cloud.google.com/go/longrunning v0.3.0 h1:NjljC+FYPV3uh5/OwWT6pVU+doBqMg2x/rZlE+CamDs= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -55,8 +46,8 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -cloud.google.com/go/storage v1.21.0 h1:HwnT2u2D309SFDHQII6m18HlrCi3jAXhUMTLOWXYH14= -cloud.google.com/go/storage v1.21.0/go.mod h1:XmRlxkgPjlBONznT2dDUU/5XlpU2OjMnKuqnZI01LAA= +cloud.google.com/go/storage v1.27.0 h1:YOO045NZI9RKfCj1c5A/ZtuuENUc8OAW+gHdGnDgyMQ= +cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/Azure/azure-pipeline-go v0.2.3 h1:7U9HBg1JFK3jHl5qmo4CTZKFTVgMwdFHMVtCdfBE21U= github.com/Azure/azure-sdk-for-go v67.2.0+incompatible h1:Uu/Ww6ernvPTrpq31kITVTIm/I5jlJ1wjtEH/bmSB2k= @@ -158,14 +149,17 @@ github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnweb github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= +github.com/bombsimon/logrusr/v3 v3.0.0 h1:tcAoLfuAhKP9npBxWzSdpsvKPQt1XV02nSf2lZA82TQ= +github.com/bombsimon/logrusr/v3 v3.0.0/go.mod h1:PksPPgSFEL2I52pla2glgCyyd2OqOHAnFF5E+g8Ixco= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chmduquesne/rollinghash v4.0.0+incompatible h1:hnREQO+DXjqIw3rUTzWN7/+Dpw+N5Um8zpKV0JOEgbo= github.com/chmduquesne/rollinghash v4.0.0+incompatible/go.mod h1:Uc2I36RRfTAf7Dge82bi3RU0OQUmXT9iweIcPqvr8A0= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= @@ -175,11 +169,7 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= @@ -200,6 +190,7 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -211,8 +202,8 @@ github.com/dave/rebecca v0.9.1/go.mod h1:N6XYdMD/OKw3lkF3ywh8Z6wPGuwNFDNtWYEMFWE github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= -github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= +github.com/deckarep/golang-set/v2 v2.3.0 h1:qs18EKUfHm2X9fA50Mr/M5hccg2tNnVqsiBImnyDs0g= +github.com/deckarep/golang-set/v2 v2.3.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= @@ -242,7 +233,6 @@ github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5y github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= @@ -279,11 +269,9 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2 github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= @@ -383,7 +371,6 @@ github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= -github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -403,7 +390,6 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= @@ -424,7 +410,6 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -436,7 +421,6 @@ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXi github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.2.1 h1:d8MncMlErDFTwQGBK1xhv026j9kqhvw1Qv9IbWT1VLQ= -github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/pprof v0.0.0-20181127221834-b4f47329b966/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -449,9 +433,6 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -459,12 +440,12 @@ github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.2.0 h1:y8Yozv7SZtlU//QXbezB6QkpuE6jMD2/gfzk4AftXjs= +github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= -github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= -github.com/googleapis/gax-go/v2 v2.2.0 h1:s7jOdKSaksJVOxE0Y/S32otcfiP+UQ0cL8/GTKaONwE= -github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= +github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ= +github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= @@ -519,8 +500,9 @@ github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJ github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= -github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= +github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE= github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74= @@ -613,8 +595,9 @@ github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9 github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mikefarah/yq/v3 v3.0.0-20201202084205-8846255d1c37/go.mod h1:dYWq+UWoFCDY1TndvFUQuhBbIYmZpjreC8adEAx93zE= github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= @@ -637,6 +620,7 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= +github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc= github.com/moby/term v0.0.0-20210610120745-9d4ed1856297/go.mod h1:vgPCkQMyxTZ7IDy8SXRufE172gr8+K/JE/7hHFxHW3A= github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= @@ -720,30 +704,34 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.12.2 h1:51L9cDoUHVrXx4zWYlcLQIZ+d+VXHgqnYKkIuq4g/34= -github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= +github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= +github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.34.0 h1:RBmGO9d/FVjqHT0yUGQwBJhkwKV+wPCn7KGpvfab0uE= -github.com/prometheus/common v0.34.0/go.mod h1:gB3sOl7P0TvJabZpLY5uQMpUqRCPPCyRLCZYc7JZTNE= +github.com/prometheus/common v0.39.0 h1:oOyhkDq05hPZKItWVBkJ6g6AtGxi+fy7F4JvUV8uhsI= +github.com/prometheus/common v0.39.0/go.mod h1:6XBZ7lYdLCbkAVhwRsWTZn+IN5AB9F/NXd5w0BbEX0Y= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= +github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/robfig/cron v1.1.0 h1:jk4/Hud3TTdcrJgUOBgsqrZBarcxl6ADIjSC2iniwLY= +github.com/robfig/cron v1.1.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -782,8 +770,9 @@ github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHN github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= -github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q= github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= +github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= +github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= @@ -799,14 +788,19 @@ github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= -github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -839,6 +833,7 @@ go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.etcd.io/etcd v0.5.0-alpha.5.0.20200819165624-17cef6e3e9d5/go.mod h1:skWido08r9w6Lq/w70DO5XYIKMu4QFu1+4VsqLQuJy8= go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= @@ -859,8 +854,9 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4= @@ -877,20 +873,19 @@ go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0H go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= -go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= +go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= -go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= +go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= +go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= -go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= +go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= +go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= golang.org/x/arch v0.0.0-20180920145803-b19384d3c130/go.mod h1:cYlCBUl1MsqxdiKgmc4uh7TxZfWSFLOGSRR090WDxt8= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -913,8 +908,8 @@ golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38= -golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= +golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1007,7 +1002,6 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -1016,10 +1010,8 @@ golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1033,14 +1025,9 @@ golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb h1:8tDJ3aechhddbdPAxpycgXHJRMLpk/Ab+aa4OgdN5/g= -golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= +golang.org/x/oauth2 v0.4.0 h1:NF0gk8LVPg1Ml7SSbGyySuoxdsXitj7TvgvuRxIMc/M= +golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1112,6 +1099,7 @@ golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1128,36 +1116,26 @@ golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1168,8 +1146,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1178,8 +1156,8 @@ golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220609170525-579cf78fd858 h1:Dpdu/EMxGMFgq0CeYMh4fazTD2vtlZRYE7wyynxJb9U= -golang.org/x/time v0.0.0-20220609170525-579cf78fd858/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1243,17 +1221,15 @@ golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.10-0.20220218145154-897bd77cd717/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= gomodules.xyz/jsonpatch/v2 v2.2.0 h1:4pT439QV83L+G9FkcCriY6EkpcK6r6bK+A5FBUMI7qY= gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= @@ -1278,24 +1254,8 @@ google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjR google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= -google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= -google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= -google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= -google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= -google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= -google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= -google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= -google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= -google.golang.org/api v0.64.0/go.mod h1:931CdxA8Rm4t6zqTFGSsgwbAEZ2+GMYurbndwSimebM= -google.golang.org/api v0.66.0/go.mod h1:I1dmXYpX7HGwz/ejRxwQp2qj5bFAz93HiCU1C1oYd9M= -google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= -google.golang.org/api v0.69.0/go.mod h1:boanBiw+h5c3s+tBPgEzLDRHfFLWV0qXxRHz3ws7C80= -google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= -google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= -google.golang.org/api v0.74.0 h1:ExR2D+5TYIrMphWgs5JCgwRhEDlPDXXrLwHHMgPHTXE= -google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= +google.golang.org/api v0.103.0 h1:9yuVqlu2JCvcLg9p8S3fcFLZij8EPSyvODIY1rkMizQ= +google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1349,41 +1309,11 @@ google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= -google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211223182754-3ac035c7e7cb/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220111164026-67b88f271998/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220114231437-d2e6a121cae0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220201184016-50beb8ab5c44/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220211171837-173942840c17/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220216160803-4663080d8bc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb h1:0m9wktIpOxGw+SSKmydXWB3Z3GTfcPP6+q75HCQa6HI= -google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= +google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c h1:S34D59DS2GWOEwWNt4fYmTcFrtlOgukG2k9WsomZ7tg= +google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -1407,16 +1337,10 @@ google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.45.0 h1:NEpgUqV3Z+ZjkqMsxMg11IaDrXY4RY6CQukSGK0uI1M= -google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= +google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY= +google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1430,8 +1354,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1485,6 +1409,7 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/api v0.18.3/go.mod h1:UOaMwERbqJMfeeeHc8XJKawj4P9TgDRnViIqqBeH2QA= k8s.io/api v0.19.0/go.mod h1:I1K45XlvTrDjmj5LoM5LuP/KYrhWbjUKT/SoPG0qTjw= +k8s.io/api v0.19.12/go.mod h1:EK+KvSq2urA6+CjVdZyAHEphXoLq2K2eW6lxOzTKSaY= k8s.io/api v0.21.1/go.mod h1:FstGROTmsSHBarKc8bylzXih8BLNYTiS3TZcsoEDg2s= k8s.io/api v0.21.3/go.mod h1:hUgeYHUbBp23Ue4qdX9tR8/ANi/g3ehylAqDn9NWVOg= k8s.io/api v0.22.0-rc.0/go.mod h1:EUcKB6RvpW74HMRUSSNwpUzrIHBdGT1FeAvOV+txic0= @@ -1501,6 +1426,7 @@ k8s.io/apiextensions-apiserver v0.24.2 h1:/4NEQHKlEz1MlaK/wHT5KMKC9UKYz6NZz6JE6o k8s.io/apiextensions-apiserver v0.24.2/go.mod h1:e5t2GMFVngUEHUd0wuCJzw8YDwZoqZfJiGOW6mm2hLQ= k8s.io/apimachinery v0.18.3/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko= k8s.io/apimachinery v0.19.0/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= +k8s.io/apimachinery v0.19.12/go.mod h1:9eb44nUQSsz9QZiilFRuMj3ZbTmoWolU8S2gnXoRMjo= k8s.io/apimachinery v0.21.1/go.mod h1:jbreFvJo3ov9rj7eWT7+sYiRx+qZuCYXwWT1bcDswPY= k8s.io/apimachinery v0.21.3/go.mod h1:H/IM+5vH9kZRNJ4l3x/fXP/5bOPJaVP/guptnZPeCFI= k8s.io/apimachinery v0.22.0-rc.0/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= @@ -1510,6 +1436,7 @@ k8s.io/apimachinery v0.24.2/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2U k8s.io/apimachinery v0.25.6 h1:r6KIF2AHwLqFfZ0LcOA3I11SF62YZK83dxj1fn14NOQ= k8s.io/apimachinery v0.25.6/go.mod h1:1S2i1QHkmxc8+EZCIxe/fX5hpldVXk4gvnJInMEb8D4= k8s.io/apiserver v0.18.3/go.mod h1:tHQRmthRPLUtwqsOnJJMoI8SW3lnoReZeE861lH8vUw= +k8s.io/apiserver v0.19.12/go.mod h1:ldZAZTNIKfMMv/UUEhk6UyTXC0/34iRdNFHo+MJOPc4= k8s.io/apiserver v0.21.1/go.mod h1:nLLYZvMWn35glJ4/FZRhzLG/3MPxAaZTgV4FJZdr+tY= k8s.io/apiserver v0.21.3/go.mod h1:eDPWlZG6/cCCMj/JBcEpDoK+I+6i3r9GsChYBHSbAzU= k8s.io/apiserver v0.22.1/go.mod h1:2mcM6dzSt+XndzVQJX21Gx0/Klo7Aen7i0Ai6tIa400= @@ -1518,6 +1445,7 @@ k8s.io/cli-runtime v0.24.0 h1:ot3Qf49T852uEyNApABO1UHHpFIckKK/NqpheZYN2gM= k8s.io/cli-runtime v0.24.0/go.mod h1:9XxoZDsEkRFUThnwqNviqzljtT/LdHtNWvcNFrAXl0A= k8s.io/client-go v0.18.3/go.mod h1:4a/dpQEvzAhT1BbuWW09qvIaGw6Gbu1gZYiQZIi1DMw= k8s.io/client-go v0.19.0/go.mod h1:H9E/VT95blcFQnlyShFgnFT9ZnJOAceiUHM3MlRC+mU= +k8s.io/client-go v0.19.12/go.mod h1:BAGKQraZ6fDmXhT46pGXWZQQqN7P4E0BJux0+9O6Gt0= k8s.io/client-go v0.21.1/go.mod h1:/kEw4RgW+3xnBGzvp9IWxKSNA+lXn3A7AuH3gdOAzLs= k8s.io/client-go v0.21.3/go.mod h1:+VPhCgTsaFmGILxR/7E1N0S+ryO010QBeNCv5JwRGYU= k8s.io/client-go v0.22.1/go.mod h1:BquC5A4UOo4qVDUtoc04/+Nxp1MeHcVc1HJm1KmG8kk= @@ -1527,12 +1455,14 @@ k8s.io/client-go v0.25.6 h1:CHxACHi0DijmlYyUR7ooZoXnD5P8jYLgBHcxp775x/U= k8s.io/client-go v0.25.6/go.mod h1:s9mMAGFYiH3Z66j7BESzu0GEradT9GQ2LjFf/YRrnyc= k8s.io/code-generator v0.18.3/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c= k8s.io/code-generator v0.19.0/go.mod h1:moqLn7w0t9cMs4+5CQyxnfA/HV8MF6aAVENF+WZZhgk= +k8s.io/code-generator v0.19.12/go.mod h1:ADrDvaUQWGn4a8lX0ONtzb7uFmDRQOMSYIMk1qWIAx8= k8s.io/code-generator v0.21.1/go.mod h1:hUlps5+9QaTrKx+jiM4rmq7YmH8wPOIko64uZCHDh6Q= k8s.io/code-generator v0.21.3/go.mod h1:K3y0Bv9Cz2cOW2vXUrNZlFbflhuPvuadW6JdnN6gGKo= k8s.io/code-generator v0.22.0-rc.0/go.mod h1:eV77Y09IopzeXOJzndrDyCI88UBok2h6WxAlBwpxa+o= k8s.io/code-generator v0.22.1/go.mod h1:eV77Y09IopzeXOJzndrDyCI88UBok2h6WxAlBwpxa+o= k8s.io/code-generator v0.24.2/go.mod h1:dpVhs00hTuTdTY6jvVxvTFCk6gSMrtfRydbhZwHI15w= k8s.io/component-base v0.18.3/go.mod h1:bp5GzGR0aGkYEfTj+eTY0AN/vXTgkJdQXjNTTVUaa3k= +k8s.io/component-base v0.19.12/go.mod h1:tpwExE0sY3A7CwtlxGL7SnQOdQfUlnFybT6GmAD+z/s= k8s.io/component-base v0.21.1/go.mod h1:NgzFZ2qu4m1juby4TnrmpR8adRk6ka62YdH5DkIIyKA= k8s.io/component-base v0.21.3/go.mod h1:kkuhtfEHeZM6LkX0saqSK8PbdO7A0HigUngmhhrwfGQ= k8s.io/component-base v0.22.1/go.mod h1:0D+Bl8rrnsPN9v0dyYvkqFfBeAd4u7n77ze+p8CMiPo= @@ -1555,6 +1485,8 @@ k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= k8s.io/klog/v2 v2.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/klog/v2 v2.70.1 h1:7aaoSdahviPmR+XkS7FyxlkkXs6tHISSG03RxleQAVQ= k8s.io/klog/v2 v2.70.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kube-aggregator v0.19.12 h1:OwyNUe/7/gxzEnaLd3sC9Yrpx0fZAERzvFslX5Qq5g8= +k8s.io/kube-aggregator v0.19.12/go.mod h1:K76wPd03pSHEmS1FgJOcpryac5C3va4cbCvSu+4EmE0= k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E= k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE= @@ -1594,6 +1526,7 @@ sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.1.0/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= diff --git a/pkg/common/common.go b/pkg/common/common.go index af6b87ea72..2766de2a8b 100644 --- a/pkg/common/common.go +++ b/pkg/common/common.go @@ -66,22 +66,20 @@ func DefaultModePtr() *int32 { return &mode } -// append labels together -func AppendUniqueLabels(userLabels ...map[string]string) (map[string]string, error) { - return AppendUniqueKeyStringOfStringMaps(userLabels...) -} - -func AppendUniqueKeyStringOfStringMaps(userLabels ...map[string]string) (map[string]string, error) { - base := map[string]string{} +func AppendUniqueKeyTOfTMaps[T comparable](userLabels ...map[T]T) (map[T]T, error) { + var base map[T]T for _, labels := range userLabels { if labels == nil { continue } + if base == nil { + base = make(map[T]T) + } for k, v := range labels { - if base[k] == "" { + if _, found := base[k]; !found { base[k] = v } else if base[k] != v { - return nil, fmt.Errorf("conflicting key %s with value %s may not override %s", k, v, base[k]) + return nil, fmt.Errorf("conflicting key %v with value %v may not override %v", k, v, base[k]) } } } @@ -112,3 +110,47 @@ func containsEnvVar(envVars []corev1.EnvVar, envVar corev1.EnvVar) bool { } return false } + +func AppendUniqueValues[T comparable](slice []T, values ...T) []T { + if values == nil || len(values) == 0 { + return slice + } + slice = append(slice, values...) + return RemoveDuplicateValues(slice) +} + +type e struct{} // empty struct + +func RemoveDuplicateValues[T comparable](slice []T) []T { + if slice == nil { + return nil + } + keys := make(map[T]e) + list := []T{} + for _, entry := range slice { + if _, found := keys[entry]; !found { //add entry to list if not found in keys already + keys[entry] = e{} + list = append(list, entry) + } + } + return list // return the result through the passed in argument +} + +func AppendTTMapAsCopy[T comparable](add ...map[T]T) map[T]T { + if add == nil || len(add) == 0 { + return nil + } + base := map[T]T{} + for k, v := range add[0] { + base[k] = v + } + if len(add) == 1 { + return base + } + for i := 1; i < len(add); i++ { + for k, v := range add[i] { + base[k] = v + } + } + return base +} diff --git a/pkg/common/common_test.go b/pkg/common/common_test.go index 1c1b9ff557..f5ef4f6512 100644 --- a/pkg/common/common_test.go +++ b/pkg/common/common_test.go @@ -5,7 +5,7 @@ import ( "testing" ) -func TestAppendUniqueLabels(t *testing.T) { +func TestAppendUniqueKeyTOfTMaps(t *testing.T) { type args struct { userLabels []map[string]string } @@ -70,14 +70,36 @@ func TestAppendUniqueLabels(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := AppendUniqueLabels(tt.args.userLabels...) + got, err := AppendUniqueKeyTOfTMaps(tt.args.userLabels...) if (err != nil) != tt.wantErr { - t.Errorf("AppendUniqueLabels() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("AppendUniqueKeyTOfTMaps() error = %v, wantErr %v", err, tt.wantErr) return } if !reflect.DeepEqual(got, tt.want) { - t.Errorf("AppendUniqueLabels() = %v, want %v", got, tt.want) + t.Errorf("AppendUniqueKeyTOfTMaps() = %v, want %v", got, tt.want) } }) } } + +// Test that a copy of the map is returned and not the original map +func TestAppendTTMapAsCopy(t *testing.T) { + base := map[string]string{ + "a": "a", + } + add := map[string]string{ + "b": "b", + } + want := map[string]string{ + "a": "a", + "b": "b", + } + t.Run("original map is not returned", func(t *testing.T) { + if got := AppendTTMapAsCopy(base, add); !reflect.DeepEqual(got, want) { + t.Errorf("AppendTTMapAsCopy() = %v, want %v", got, want) + } + if !reflect.DeepEqual(base, map[string]string{"a": "a"}) { + t.Errorf("AppendTTMapAsCopy() = %v, want %v", base, map[string]string{"a": "a"}) + } + }) +} diff --git a/pkg/klog/klog.go b/pkg/klog/klog.go new file mode 100644 index 0000000000..3d70814667 --- /dev/null +++ b/pkg/klog/klog.go @@ -0,0 +1,90 @@ +package klog + +// klog init flags from https://github.com/openshift/velero/blob/240b4e666fe15ef98defa2b51483fe87ac9996fb/pkg/cmd/velero/velero.go#L125 +// loggingT collects all the global state of the logging setup. +// +kubebuilder:object:generate=true +type LoggingT struct { + // Boolean flags. Not handled atomically because the flag.Value interface + // does not let us avoid the =true, and that shorthand is necessary for + // compatibility. TODO: does this matter enough to fix? Seems unlikely. + // +optional + ToStderr *bool `json:"logtostderr,omitempty"` // The -logtostderr flag. + // log to standard error as well as files (no effect when -logtostderr=true) + // +optional + AlsoToStderr *bool `json:"alsologtostderr,omitempty"` // The -alsologtostderr flag. + + // logs at or above this threshold go to stderr when writing to files and stderr (no effect when -logtostderr=true or -alsologtostderr=false) (default 2) + // +optional + StderrThreshold *int `json:"stderrthreshold,omitempty"` // The -stderrthreshold flag. + + // bufferCache maintains the free list. It uses its own mutex + // so buffers can be grabbed and printed to without holding the main lock, + // for better parallelization. + // bufferCache buffer.Buffers + + // mu protects the remaining elements of this structure and is + // used to synchronize logging. + // mu sync.Mutex + // file holds writer for each of the log types. + // file [severity.NumSeverity]flushSyncWriter + // flushD holds a flushDaemon that frequently flushes log file buffers. + // flushD *flushDaemon + // flushInterval is the interval for periodic flushing. If zero, + // the global default will be used. + // flushInterval time.Duration + // pcs is used in V to avoid an allocation when computing the caller's PC. + // pcs [1]uintptr + // vmap is a cache of the V Level for each V() call site, identified by PC. + // It is wiped whenever the vmodule flag changes state. + // vmap map[uintptr]Level + // filterLength stores the length of the vmodule filter chain. If greater + // than zero, it means vmodule is enabled. It may be read safely + // using sync.LoadInt32, but is only modified under mu. + // filterLength int32 + // traceLocation is the state of the -log_backtrace_at flag. + + // when logging hits line file:N, emit a stack trace + // +optional + TraceLocation string `json:"log_backtrace_at,omitempty"` + // These flags are modified only under lock, although verbosity may be fetched + // safely using atomic.LoadInt32. + + // comma-separated list of pattern=N settings for file-filtered logging + // +optional + Vmodule string `json:"vmodule,omitempty"` // The state of the -vmodule flag. + // number for the log level verbosity + // +optional + Verbosity *int `json:"v,omitempty"` // V logging level, the value of the -v flag/ + + // If non-empty, write log files in this directory (no effect when -logtostderr=true) + // +optional + LogDir string `json:"log_dir,omitempty"` + + // If non-empty, use this log file (no effect when -logtostderr=true) + // +optional + LogFile string `json:"log_file,omitempty"` + + // Defines the maximum size a log file can grow to (no effect when -logtostderr=true). Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800) + // +kubebuilder:validation:Minimum=0 + // +optional + LogFileMaxSizeMB *int64 `json:"log_file_max_size,omitempty"` + + // If true, avoid header prefixes in the log messages + // +optional + SkipHeaders *bool `json:"skip_headers,omitempty"` + + // If true, avoid headers when opening log files (no effect when -logtostderr=true) + // +optional + SkipLogHeaders *bool `json:"skip_log_headers,omitempty"` + + // If true, adds the file directory to the header of the log messages + // +optional + AddDirHeader *bool `json:"add_dir_header,omitempty"` + + // If true, only write logs to their native severity level (vs also writing to each lower severity level; no effect when -logtostderr=true) + // +optional + OneOutput *bool `json:"one_output,omitempty"` + + // If set, all output will be filtered through the filter. + // filter LogFilter +} diff --git a/pkg/klog/zz_generated.deepcopy.go b/pkg/klog/zz_generated.deepcopy.go new file mode 100644 index 0000000000..54abd9feb9 --- /dev/null +++ b/pkg/klog/zz_generated.deepcopy.go @@ -0,0 +1,84 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright 2021. + +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 controller-gen. DO NOT EDIT. + +package klog + +import () + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LoggingT) DeepCopyInto(out *LoggingT) { + *out = *in + if in.ToStderr != nil { + in, out := &in.ToStderr, &out.ToStderr + *out = new(bool) + **out = **in + } + if in.AlsoToStderr != nil { + in, out := &in.AlsoToStderr, &out.AlsoToStderr + *out = new(bool) + **out = **in + } + if in.StderrThreshold != nil { + in, out := &in.StderrThreshold, &out.StderrThreshold + *out = new(int) + **out = **in + } + if in.Verbosity != nil { + in, out := &in.Verbosity, &out.Verbosity + *out = new(int) + **out = **in + } + if in.LogFileMaxSizeMB != nil { + in, out := &in.LogFileMaxSizeMB, &out.LogFileMaxSizeMB + *out = new(int64) + **out = **in + } + if in.SkipHeaders != nil { + in, out := &in.SkipHeaders, &out.SkipHeaders + *out = new(bool) + **out = **in + } + if in.SkipLogHeaders != nil { + in, out := &in.SkipLogHeaders, &out.SkipLogHeaders + *out = new(bool) + **out = **in + } + if in.AddDirHeader != nil { + in, out := &in.AddDirHeader, &out.AddDirHeader + *out = new(bool) + **out = **in + } + if in.OneOutput != nil { + in, out := &in.OneOutput, &out.OneOutput + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LoggingT. +func (in *LoggingT) DeepCopy() *LoggingT { + if in == nil { + return nil + } + out := new(LoggingT) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/velero/client/config.go b/pkg/velero/client/config.go new file mode 100644 index 0000000000..e87fce4236 --- /dev/null +++ b/pkg/velero/client/config.go @@ -0,0 +1,16 @@ +package client + +// +kubebuilder:object:generate=true +type VeleroConfig struct { + // We use same namespace as DataProtectionApplication + // Namespace string `json:"namespace,omitempty"` + + // Features is an existing field in DataProtectionApplication + // --kubebuilder:validation:Enum=EnableCSI;EnableAPIGroupVersions;EnableUploadProgress + // Features []VeleroFeatureFlag `json:"features,omitempty"` + + // Show colored output in TTY + // +optional + Colorized *bool `json:"colorized,omitempty"` + // CACert is not a flag in velero server +} diff --git a/pkg/velero/client/zz_generated.deepcopy.go b/pkg/velero/client/zz_generated.deepcopy.go new file mode 100644 index 0000000000..75a8a9e82c --- /dev/null +++ b/pkg/velero/client/zz_generated.deepcopy.go @@ -0,0 +1,44 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright 2021. + +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 controller-gen. DO NOT EDIT. + +package client + +import () + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VeleroConfig) DeepCopyInto(out *VeleroConfig) { + *out = *in + if in.Colorized != nil { + in, out := &in.Colorized, &out.Colorized + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VeleroConfig. +func (in *VeleroConfig) DeepCopy() *VeleroConfig { + if in == nil { + return nil + } + out := new(VeleroConfig) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/velero/server/args.go b/pkg/velero/server/args.go new file mode 100644 index 0000000000..092f0bf24b --- /dev/null +++ b/pkg/velero/server/args.go @@ -0,0 +1,159 @@ +package server + +import ( + "fmt" + "strconv" + "strings" + + "github.com/openshift/oadp-operator/pkg/klog" + "github.com/openshift/oadp-operator/pkg/velero/client" + "github.com/sirupsen/logrus" + "github.com/vmware-tanzu/velero/pkg/util/boolptr" +) + +// VeleroServerArgs are the arguments that are passed to the Velero server +// +kubebuilder:object:generate=true +type Args struct { + ServerConfig `json:",inline"` + GlobalFlags `json:",inline"` +} + +// GlobalFlags are flags that are defined across Velero CLI commands +// +kubebuilder:object:generate=true +type GlobalFlags struct { + client.VeleroConfig `json:",inline"` + klog.LoggingT `json:",inline"` +} + +// StringArr returns the Velero server arguments as a string array +// dpaFeatureFlags are the feature flags that are defined in the DPA CR which will be merged with Args +// Most validations are done in the DPA CRD except float32 validation +func (a Args) StringArr(dpaFeatureFlags []string, logLevel string) ([]string, error) { + args := []string{"server"} + // we are overriding args, so recreate args from scratch + if len(dpaFeatureFlags) > 0 { + args = append(args, fmt.Sprintf("--features=%s", strings.Join(dpaFeatureFlags, ","))) + } + if boolptr.IsSetToTrue(a.DefaultVolumesToFsBackup) { + args = append(args, "--default-volumes-to-fs-backup=true") + } else if boolptr.IsSetToFalse(a.DefaultVolumesToFsBackup) { + args = append(args, "--default-volumes-to-fs-backup=false") + } + if logLevel != "" { + logrusLevel, err := logrus.ParseLevel(logLevel) + if err != nil { + return []string{}, fmt.Errorf("invalid log level %s, use: %s", logLevel, "trace, debug, info, warning, error, fatal, or panic") + } + args = append(args, fmt.Sprintf("--log-level=%s", logrusLevel.String())) + } + if a.BackupSyncPeriod != nil { + args = append(args, fmt.Sprintf("--backup-sync-period=%s", a.BackupSyncPeriod.String())) // duration + } + if a.ClientBurst != nil { + args = append(args, fmt.Sprintf("--client-burst=%s", strconv.Itoa(*a.ClientBurst))) // int + } + if a.ClientPageSize != nil { + args = append(args, fmt.Sprintf("--client-page-size=%s", strconv.Itoa(*a.ClientPageSize))) // int + } + if a.ClientQPS != nil { + if _, err := strconv.ParseFloat(*a.ClientQPS, 32); err != nil { + return nil, err + } + args = append(args, fmt.Sprintf("--client-qps=%s", *a.ClientQPS)) // float32 + } + // default-backup-storage-location set outside Args + if a.DefaultBackupTTL != nil { + args = append(args, fmt.Sprintf("--default-backup-ttl=%s", a.DefaultBackupTTL.String())) // duration + } + if a.DefaultItemOperationTimeout != nil { + args = append(args, fmt.Sprintf("--default-item-operation-timeout=%s", a.DefaultItemOperationTimeout.String())) // duration + } + if a.ResourceTimeout != nil { + args = append(args, fmt.Sprintf("--resource-timeout=%s", a.ResourceTimeout.String())) // duration + } + if a.RepoMaintenanceFrequency != nil { + args = append(args, fmt.Sprintf("--default-repo-maintain-frequency=%s", a.RepoMaintenanceFrequency.String())) // duration + } + // default-volume-snapshot-locations set outside Args + if a.DisabledControllers != nil { + args = append(args, fmt.Sprintf("--disable-controllers=%s", strings.Join(a.DisabledControllers, ","))) // strings + } + if a.GarbageCollectionFrequency != nil { + args = append(args, fmt.Sprintf("--garbage-collection-frequency=%s", a.GarbageCollectionFrequency.String())) // duration + } + if a.FormatFlag != "" { + args = append(args, fmt.Sprintf("--log-format=%s", a.FormatFlag)) // format + } + if a.MetricsAddress != "" { + args = append(args, fmt.Sprintf("--metrics-address=%s", a.MetricsAddress)) // string + } + // plugin-dir is fixed to /plugins + if a.ProfilerAddress != "" { + args = append(args, fmt.Sprintf("--profiler-address=%s", a.ProfilerAddress)) // string + } + if a.PodVolumeOperationTimeout != nil { + args = append(args, fmt.Sprintf("--fs-backup-timeout=%s", a.PodVolumeOperationTimeout.String())) // duration + } + if a.ItemOperationSyncFrequency != nil { + args = append(args, fmt.Sprintf("--item-operation-sync-frequency=%s", a.ItemOperationSyncFrequency.String())) // duration + } + if a.MaxConcurrentK8SConnections != nil { + args = append(args, fmt.Sprintf("--max-concurrent-k8s-connections=%d", *a.MaxConcurrentK8SConnections)) // uint + } + // restore-only is being deprecated, set in bsl + // RestoreResourcePriorities are set in DPA which creates a configmap + // However, server args is also an option. + if a.RestoreResourcePriorities != "" { + args = append(args, fmt.Sprintf("--restore-resource-priorities=%s", a.RestoreResourcePriorities)) // stringArray + } + if a.StoreValidationFrequency != nil { + args = append(args, fmt.Sprintf("--store-validation-frequency=%s", a.StoreValidationFrequency.String())) // duration + } + if a.ResourceTerminatingTimeout != nil { + args = append(args, fmt.Sprintf("--terminating-resource-timeout=%s", a.ResourceTerminatingTimeout.String())) // duration + } + if a.AddDirHeader != nil { + args = append(args, fmt.Sprintf("--add_dir_header=%s", strconv.FormatBool(*a.AddDirHeader))) // optionalBool + } + if a.AlsoToStderr != nil { + args = append(args, fmt.Sprintf("--alsologtostderr=%s", strconv.FormatBool(*a.AlsoToStderr))) // alsologtostderr + } + if a.Colorized != nil { + args = append(args, fmt.Sprintf("--colorized=%s", strconv.FormatBool(*a.Colorized))) // optionalBool + } + // features set outside Args + // args = append(args, "--kubeconfig") // string + // args = append(args, "--kubecontext") // string + if a.TraceLocation != "" { + args = append(args, fmt.Sprintf("--log_backtrace_at=%s", a.TraceLocation)) // traceLocation + } + if a.LogDir != "" { + args = append(args, fmt.Sprintf("--log_dir=%s", a.LogDir)) // string + } + if a.LogFile != "" { + args = append(args, fmt.Sprintf("--log_file=%s", a.LogFile)) // string + } + if a.LogFileMaxSizeMB != nil { + args = append(args, fmt.Sprintf("--log_file_max_size=%d", *a.LogFileMaxSizeMB)) // uint + } + if a.ToStderr != nil { + args = append(args, fmt.Sprintf("--logtostderr=%s", strconv.FormatBool(*a.ToStderr))) // optionalBool + } + // args = append(args, "--namespace") // string + if a.SkipHeaders != nil { + args = append(args, fmt.Sprintf("--skip_headers=%s", strconv.FormatBool(*a.SkipHeaders))) // optionalBool + } + if a.SkipLogHeaders != nil { + args = append(args, fmt.Sprintf("--skip_log_headers=%s", strconv.FormatBool(*a.SkipLogHeaders))) // optionalBool + } + if a.StderrThreshold != nil { + args = append(args, fmt.Sprintf("--stderrthreshold=%d", *a.StderrThreshold)) // severity + } + if a.Verbosity != nil { + args = append(args, fmt.Sprintf("--v=%d", *a.Verbosity)) // count + } + if a.Vmodule != "" { + args = append(args, fmt.Sprintf("--vmodule=%s", a.Vmodule)) // string + } + return args, nil +} diff --git a/pkg/velero/server/config.go b/pkg/velero/server/config.go new file mode 100644 index 0000000000..890504d58f --- /dev/null +++ b/pkg/velero/server/config.go @@ -0,0 +1,94 @@ +package server + +import ( + "time" + + "github.com/vmware-tanzu/velero/pkg/client" + vServer "github.com/vmware-tanzu/velero/pkg/cmd/server" +) + +// This package is used to store ServerConfig struct and note information about flags for velero server and how they are set. +// The options you can set in `velero server` is a combination of ServerConfig, featureFlagSet + +// ServerConfig holds almost all the configuration for the Velero server. +// https://github.com/openshift/velero/blob/dd02df5cd5751263fce6d1ebd48ea11423b0cd16/pkg/cmd/server/server.go#L112-L129 +// +kubebuilder:object:generate=true +type ServerConfig struct { + // pluginDir will be fixed to /plugins + // pluginDir + + // The address to expose prometheus metrics + // +optional + MetricsAddress string `json:"metrics-address,omitempty"` + // defaultBackupLocation will be defined outside of server config in DataProtectionApplication + // defaultBackupLocation string + + // How often to ensure all Velero backups in object storage exist as Backup API objects in the cluster. This is the default sync period if none is explicitly specified for a backup storage location. + // +optional + BackupSyncPeriod *time.Duration `json:"backup-sync-period,omitempty"` + // How long pod volume file system backups/restores should be allowed to run before timing out. (default 4h0m0s) + // +optional + PodVolumeOperationTimeout *time.Duration `json:"fs-backup-timeout,omitempty"` + // How long to wait on persistent volumes and namespaces to terminate during a restore before timing out. + // +optional + ResourceTerminatingTimeout *time.Duration `json:"terminating-resource-timeout,omitempty"` + // default 720h0m0s + // +optional + DefaultBackupTTL *time.Duration `json:"default-backup-ttl,omitempty"` + // How often to verify if the storage is valid. Optional. Set this to `0s` to disable sync. Default 1 minute. + // +optional + StoreValidationFrequency *time.Duration `json:"store-validation-frequency,omitempty"` + // Desired order of resource restores, the priority list contains two parts which are split by "-" element. The resources before "-" element are restored first as high priorities, the resources after "-" element are restored last as low priorities, and any resource not in the list will be restored alphabetically between the high and low priorities. (default customresourcedefinitions,namespaces,storageclasses,volumesnapshotbackups.datamover.oadp.openshift.io,volumesnapshotclass.snapshot.storage.k8s.io,volumesnapshotcontents.snapshot.storage.k8s.io,volumesnapshots.snapshot.storage.k8s.io,persistentvolumes,persistentvolumeclaims,serviceaccounts,secrets,configmaps,limitranges,pods,replicasets.apps,clusterclasses.cluster.x-k8s.io,services,-,clusterbootstraps.run.tanzu.vmware.com,clusters.cluster.x-k8s.io,clusterresourcesets.addons.cluster.x-k8s.io) + // +optional + RestoreResourcePriorities string `json:"restore-resource-priorities,omitempty"` + // defaultVolumeSnapshotLocations will be defined outside of server config in DataProtectionApplication + // defaultVolumeSnapshotLocations map[string]string + + // DEPRECATED: this flag will be removed in v2.0. Use read-only backup storage locations instead. + // +optional + // RestoreOnly *bool `json:"restore-only,omitempty"` + + // List of controllers to disable on startup. Valid values are backup,backup-operations,backup-deletion,backup-finalizer,backup-sync,download-request,gc,backup-repo,restore,restore-operations,schedule,server-status-request + // +kubebuilder:validation:Enum=backup;backup-operations;backup-deletion;backup-finalizer;backup-sync;download-request;gc;backup-repo;restore;restore-operations;schedule;server-status-request + // +optional + DisabledControllers []string `json:"disabled-controllers,omitempty"` + // Maximum number of requests per second by the server to the Kubernetes API once the burst limit has been reached. + // this will be validated as a valid float32 + // +optional + ClientQPS *string `json:"client-qps,omitempty"` + // Maximum number of requests by the server to the Kubernetes API in a short period of time. + // +optional + ClientBurst *int `json:"client-burst,omitempty"` + // Page size of requests by the server to the Kubernetes API when listing objects during a backup. Set to 0 to disable paging. + // +optional + ClientPageSize *int `json:"client-page-size,omitempty"` + // The address to expose the pprof profiler. + // +optional + ProfilerAddress string `json:"profiler-address,omitempty"` + // How often to check status on backup/restore operations after backup/restore processing. + // +optional + ItemOperationSyncFrequency *time.Duration `json:"item-operation-sync-frequency,omitempty"` + // The format for log output. Valid values are text, json. (default text) + // +kubebuilder:validation:Enum=text;json + // +optional + FormatFlag string `json:"log-format,omitempty"` + // How often 'maintain' is run for backup repositories by default. + // +optional + RepoMaintenanceFrequency *time.Duration `json:"default-repo-maintain-frequency,omitempty"` + // How long to wait by default before backups can be garbage collected. (default 720h0m0s) + // +optional + GarbageCollectionFrequency *time.Duration `json:"garbage-collection-frequency,omitempty"` + // Backup all volumes with pod volume file system backup by default. + // +optional + DefaultVolumesToFsBackup *bool `json:"default-volumes-to-fs-backup,omitempty"` + // uploaderType, oadp only support restic at the moment + + // How long to wait on asynchronous BackupItemActions and RestoreItemActions to complete before timing out. (default 1h0m0s) + DefaultItemOperationTimeout *time.Duration `json:"default-item-operation-timeout,omitempty"` + // How long to wait for resource processes which are not covered by other specific timeout parameters. Default is 10 minutes. (default 10m0s) + ResourceTimeout *time.Duration `json:"resource-timeout,omitempty"` + // Max concurrent connections number that Velero can create with kube-apiserver. Default is 30. (default 30) + MaxConcurrentK8SConnections *int `json:"max-concurrent-k8s-connections,omitempty"` +} + +var VeleroServerCommand = vServer.NewCommand(client.NewFactory("velero-server", client.VeleroConfig{})).Flags() diff --git a/pkg/velero/server/zz_generated.deepcopy.go b/pkg/velero/server/zz_generated.deepcopy.go new file mode 100644 index 0000000000..8ec3693567 --- /dev/null +++ b/pkg/velero/server/zz_generated.deepcopy.go @@ -0,0 +1,155 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright 2021. + +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 controller-gen. DO NOT EDIT. + +package server + +import ( + timex "time" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Args) DeepCopyInto(out *Args) { + *out = *in + in.ServerConfig.DeepCopyInto(&out.ServerConfig) + in.GlobalFlags.DeepCopyInto(&out.GlobalFlags) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Args. +func (in *Args) DeepCopy() *Args { + if in == nil { + return nil + } + out := new(Args) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GlobalFlags) DeepCopyInto(out *GlobalFlags) { + *out = *in + in.VeleroConfig.DeepCopyInto(&out.VeleroConfig) + in.LoggingT.DeepCopyInto(&out.LoggingT) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GlobalFlags. +func (in *GlobalFlags) DeepCopy() *GlobalFlags { + if in == nil { + return nil + } + out := new(GlobalFlags) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServerConfig) DeepCopyInto(out *ServerConfig) { + *out = *in + if in.BackupSyncPeriod != nil { + in, out := &in.BackupSyncPeriod, &out.BackupSyncPeriod + *out = new(timex.Duration) + **out = **in + } + if in.PodVolumeOperationTimeout != nil { + in, out := &in.PodVolumeOperationTimeout, &out.PodVolumeOperationTimeout + *out = new(timex.Duration) + **out = **in + } + if in.ResourceTerminatingTimeout != nil { + in, out := &in.ResourceTerminatingTimeout, &out.ResourceTerminatingTimeout + *out = new(timex.Duration) + **out = **in + } + if in.DefaultBackupTTL != nil { + in, out := &in.DefaultBackupTTL, &out.DefaultBackupTTL + *out = new(timex.Duration) + **out = **in + } + if in.StoreValidationFrequency != nil { + in, out := &in.StoreValidationFrequency, &out.StoreValidationFrequency + *out = new(timex.Duration) + **out = **in + } + if in.DisabledControllers != nil { + in, out := &in.DisabledControllers, &out.DisabledControllers + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ClientQPS != nil { + in, out := &in.ClientQPS, &out.ClientQPS + *out = new(string) + **out = **in + } + if in.ClientBurst != nil { + in, out := &in.ClientBurst, &out.ClientBurst + *out = new(int) + **out = **in + } + if in.ClientPageSize != nil { + in, out := &in.ClientPageSize, &out.ClientPageSize + *out = new(int) + **out = **in + } + if in.ItemOperationSyncFrequency != nil { + in, out := &in.ItemOperationSyncFrequency, &out.ItemOperationSyncFrequency + *out = new(timex.Duration) + **out = **in + } + if in.RepoMaintenanceFrequency != nil { + in, out := &in.RepoMaintenanceFrequency, &out.RepoMaintenanceFrequency + *out = new(timex.Duration) + **out = **in + } + if in.GarbageCollectionFrequency != nil { + in, out := &in.GarbageCollectionFrequency, &out.GarbageCollectionFrequency + *out = new(timex.Duration) + **out = **in + } + if in.DefaultVolumesToFsBackup != nil { + in, out := &in.DefaultVolumesToFsBackup, &out.DefaultVolumesToFsBackup + *out = new(bool) + **out = **in + } + if in.DefaultItemOperationTimeout != nil { + in, out := &in.DefaultItemOperationTimeout, &out.DefaultItemOperationTimeout + *out = new(timex.Duration) + **out = **in + } + if in.ResourceTimeout != nil { + in, out := &in.ResourceTimeout, &out.ResourceTimeout + *out = new(timex.Duration) + **out = **in + } + if in.MaxConcurrentK8SConnections != nil { + in, out := &in.MaxConcurrentK8SConnections, &out.MaxConcurrentK8SConnections + *out = new(int) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServerConfig. +func (in *ServerConfig) DeepCopy() *ServerConfig { + if in == nil { + return nil + } + out := new(ServerConfig) + in.DeepCopyInto(out) + return out +}