diff --git a/config/crd/bases/pxc.percona.com_perconaxtradbclusterbackups.yaml b/config/crd/bases/pxc.percona.com_perconaxtradbclusterbackups.yaml index 69a50324df..e70cde1a86 100644 --- a/config/crd/bases/pxc.percona.com_perconaxtradbclusterbackups.yaml +++ b/config/crd/bases/pxc.percona.com_perconaxtradbclusterbackups.yaml @@ -244,6 +244,94 @@ spec: latestRestorableTime: format: date-time type: string + pvc: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object s3: properties: bucket: diff --git a/config/crd/bases/pxc.percona.com_perconaxtradbclusterrestores.yaml b/config/crd/bases/pxc.percona.com_perconaxtradbclusterrestores.yaml index 14755b83ce..3db43153df 100644 --- a/config/crd/bases/pxc.percona.com_perconaxtradbclusterrestores.yaml +++ b/config/crd/bases/pxc.percona.com_perconaxtradbclusterrestores.yaml @@ -116,6 +116,94 @@ spec: latestRestorableTime: format: date-time type: string + pvc: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object s3: properties: bucket: @@ -327,6 +415,94 @@ spec: latestRestorableTime: format: date-time type: string + pvc: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object s3: properties: bucket: diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index 95ba5f8eb1..6d0e6ee75d 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -248,6 +248,94 @@ spec: latestRestorableTime: format: date-time type: string + pvc: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object s3: properties: bucket: @@ -415,6 +503,94 @@ spec: latestRestorableTime: format: date-time type: string + pvc: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object s3: properties: bucket: @@ -626,6 +802,94 @@ spec: latestRestorableTime: format: date-time type: string + pvc: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object s3: properties: bucket: diff --git a/deploy/crd.yaml b/deploy/crd.yaml index da372bb5b9..bece937fe6 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -248,6 +248,94 @@ spec: latestRestorableTime: format: date-time type: string + pvc: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object s3: properties: bucket: @@ -415,6 +503,94 @@ spec: latestRestorableTime: format: date-time type: string + pvc: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object s3: properties: bucket: @@ -626,6 +802,94 @@ spec: latestRestorableTime: format: date-time type: string + pvc: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object s3: properties: bucket: diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index 04ff3f608d..7246088a7b 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -248,6 +248,94 @@ spec: latestRestorableTime: format: date-time type: string + pvc: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object s3: properties: bucket: @@ -415,6 +503,94 @@ spec: latestRestorableTime: format: date-time type: string + pvc: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object s3: properties: bucket: @@ -626,6 +802,94 @@ spec: latestRestorableTime: format: date-time type: string + pvc: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object s3: properties: bucket: diff --git a/e2e-tests/demand-backup-cloud/conf/client.yml b/e2e-tests/demand-backup-cloud/conf/client.yml deleted file mode 100644 index f06191950c..0000000000 --- a/e2e-tests/demand-backup-cloud/conf/client.yml +++ /dev/null @@ -1,26 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: backup-client -spec: - replicas: 1 - selector: - matchLabels: - name: backup-client - template: - metadata: - labels: - name: backup-client - spec: - containers: - - name: backup-client - command: ["bash", "-c", "sleep 100500"] - image: -backup - imagePullPolicy: IfNotPresent - volumeMounts: - - mountPath: /backup - name: backup - volumes: - - name: backup - persistentVolumeClaim: - claimName: xb-on-demand-backup-pvc diff --git a/e2e-tests/demand-backup-encrypted-with-tls/conf/client.yml b/e2e-tests/demand-backup-encrypted-with-tls/conf/client.yml index f06191950c..32b1c22ac5 100644 --- a/e2e-tests/demand-backup-encrypted-with-tls/conf/client.yml +++ b/e2e-tests/demand-backup-encrypted-with-tls/conf/client.yml @@ -23,4 +23,4 @@ spec: volumes: - name: backup persistentVolumeClaim: - claimName: xb-on-demand-backup-pvc + claimName: -backup-pvc diff --git a/e2e-tests/demand-backup-encrypted-with-tls/run b/e2e-tests/demand-backup-encrypted-with-tls/run index 2d5616874d..87bf0a9d65 100755 --- a/e2e-tests/demand-backup-encrypted-with-tls/run +++ b/e2e-tests/demand-backup-encrypted-with-tls/run @@ -29,7 +29,7 @@ main() { run_backup "$cluster" "on-demand-backup-pvc" run_recovery_check "$cluster" "on-demand-backup-pvc" kubectl_bin delete -f "$test_dir/conf/restore-on-demand-backup-pvc.yaml" - check_pvc_md5 + check_pvc_md5 "on-demand-backup-pvc" table_must_be_encrypted "$cluster" "myApp" keyring_plugin_must_be_in_use "$cluster" diff --git a/e2e-tests/demand-backup/conf/client.yml b/e2e-tests/demand-backup/conf/client.yml index f06191950c..32b1c22ac5 100644 --- a/e2e-tests/demand-backup/conf/client.yml +++ b/e2e-tests/demand-backup/conf/client.yml @@ -23,4 +23,4 @@ spec: volumes: - name: backup persistentVolumeClaim: - claimName: xb-on-demand-backup-pvc + claimName: -backup-pvc diff --git a/e2e-tests/demand-backup/conf/on-demand-backup-pvc-with-finalizer.yml b/e2e-tests/demand-backup/conf/on-demand-backup-pvc-with-finalizer.yml new file mode 100644 index 0000000000..3bc8eca83b --- /dev/null +++ b/e2e-tests/demand-backup/conf/on-demand-backup-pvc-with-finalizer.yml @@ -0,0 +1,9 @@ +apiVersion: pxc.percona.com/v1 +kind: PerconaXtraDBClusterBackup +metadata: + finalizers: + - percona.com/delete-backup + name: on-demand-backup-pvc-with-finalizer +spec: + pxcCluster: demand-backup + storageName: pvc diff --git a/e2e-tests/demand-backup/conf/restore-on-demand-backup-pvc-bsource.yaml b/e2e-tests/demand-backup/conf/restore-on-demand-backup-pvc-bsource.yaml index bc059e7043..905440ef09 100644 --- a/e2e-tests/demand-backup/conf/restore-on-demand-backup-pvc-bsource.yaml +++ b/e2e-tests/demand-backup/conf/restore-on-demand-backup-pvc-bsource.yaml @@ -5,7 +5,7 @@ metadata: spec: pxcCluster: demand-backup backupSource: - destination: pvc/xb-on-demand-backup-pvc-bsource + destination: storageName: pvc resources: requests: diff --git a/e2e-tests/demand-backup/run b/e2e-tests/demand-backup/run index 7dafaa6c3b..e35265c4d6 100755 --- a/e2e-tests/demand-backup/run +++ b/e2e-tests/demand-backup/run @@ -7,6 +7,52 @@ test_dir=$(realpath $(dirname $0)) set_debug +check_finalizer_for_fs() { + local backup_name="$1" + local finalizer_flag="off" + + desc "Checking finalizers on backup $backup_name" + # Check if pxc-backup has the finalizer "percona.com/delete-backup" + if kubectl get pxc-backup "$backup_name" -o jsonpath='{.metadata.finalizers}' | grep -q "percona.com/delete-backup"; then + finalizer_flag="on" + fi + + echo "Finalizer is $finalizer_flag" + + echo "Looking for PVCs containing '$backup_name'" + pvc=$(kubectl get pvc --no-headers -o custom-columns=":metadata.name" | grep "$backup_name") + + if [[ -z "$pvc" ]]; then + echo "No PVCs found with substring '$backup_name' before the backup deletion. Something wrong with backup" + return 1 + fi + + echo "Deleting backup $backup_name ..." + kubectl delete pxc-backup "$backup_name" + + sleep 5 + + pvc=$(kubectl get pvc --no-headers -o custom-columns=":metadata.name" | grep "$backup_name" || true) + + echo "Checking PVC $pvc existence and finalizers" + + if [[ -z "$pvc" && "$finalizer_flag" == "off" ]]; then + echo "Error: No PVCs found with substring '$backup_name'. PVC was deleted even though finalizer is OFF." + exit 1 + + elif [[ -z "$pvc" && "$finalizer_flag" == "on" ]]; then + echo "Correct: No PVCs found with substring '$backup_name' because finalizer is ON and PVC was deleted." + + elif [[ -n "$pvc" && "$finalizer_flag" == "on" ]]; then + echo "Error: PVC exists: $pvc (finalizer_flag=$finalizer_flag). Finalizer should delete PVC but did NOT." + exit 1 + + else + echo "PVC exists: $pvc (finalizer_flag=$finalizer_flag)" + fi + +} + main() { create_infra $namespace @@ -19,7 +65,12 @@ main() { run_backup "$cluster" "on-demand-backup-pvc" run_recovery_check "$cluster" "on-demand-backup-pvc" compare_kubectl job/restore-job-on-demand-backup-pvc-demand-backup - check_pvc_md5 + + check_pvc_md5 "on-demand-backup-pvc" + check_finalizer_for_fs "on-demand-backup-pvc" + + run_backup "$cluster" "on-demand-backup-pvc-with-finalizer" + check_finalizer_for_fs "on-demand-backup-pvc-with-finalizer" run_backup "$cluster" "on-demand-backup-pvc-bsource" run_recovery_check "$cluster" "on-demand-backup-pvc-bsource" diff --git a/e2e-tests/functions b/e2e-tests/functions index c14da1a65e..3dd578d011 100755 --- a/e2e-tests/functions +++ b/e2e-tests/functions @@ -911,18 +911,23 @@ EOF } cat_config() { - cat "$1" \ - | $sed -e "s#apiVersion: pxc.percona.com/v.*\$#apiVersion: $API#" \ - | $sed -e "s#image:.*-pxc\([0-9]*.[0-9]*\)\{0,1\}\$#image: $IMAGE_PXC#" \ - | $sed -e "s#image:.*\/percona-xtradb-cluster:.*\$#image: $IMAGE_PXC#" \ - | $sed -e "s#image:.*-init\$#image: $IMAGE#" \ - | $sed -e "s#image:.*-pmm\$#image: $IMAGE_PMM_CLIENT#" \ - | $sed -e "s#image:.*-backup\$#image: $IMAGE_BACKUP#" \ - | $sed -e "s#image:.*-proxysql\$#image: $IMAGE_PROXY#" \ - | $sed -e "s#image:.*-haproxy\$#image: $IMAGE_HAPROXY#" \ - | $sed -e "s#image:.*-logcollector\$#image: $IMAGE_LOGCOLLECTOR#" \ - | $sed -e "s~minio-service.#namespace~minio-service.$namespace~" \ - | $sed -e "s#apply:.*#apply: Never#" + local input_file="$1" + local pvc_name="$2" + + cat "$input_file" \ + | $sed -e "s#apiVersion: pxc.percona.com/v.*\$#apiVersion: $API#" \ + | $sed -e "s#image:.*-pxc\([0-9]*.[0-9]*\)\{0,1\}\$#image: $IMAGE_PXC#" \ + | $sed -e "s#image:.*\/percona-xtradb-cluster:.*\$#image: $IMAGE_PXC#" \ + | $sed -e "s#image:.*-init\$#image: $IMAGE#" \ + | $sed -e "s#image:.*-pmm\$#image: $IMAGE_PMM_CLIENT#" \ + | $sed -e "s#image:.*-backup\$#image: $IMAGE_BACKUP#" \ + | $sed -e "s#image:.*-proxysql\$#image: $IMAGE_PROXY#" \ + | $sed -e "s#image:.*-haproxy\$#image: $IMAGE_HAPROXY#" \ + | $sed -e "s#image:.*-logcollector\$#image: $IMAGE_LOGCOLLECTOR#" \ + | $sed -e "s~minio-service.#namespace~minio-service.$namespace~" \ + | $sed -e "s#apply:.*#apply: Never#" \ + | $sed -e "s#claimName:..*-backup-pvc\$#claimName: $pvc_name#" \ + } apply_secrets() { @@ -938,11 +943,14 @@ apply_secrets() { } apply_config() { + local config_file="$1" + local pvc_name="${2:-}" + if [ -z "$SKIP_REMOTE_BACKUPS" ]; then - cat_config "$1" \ + cat_config "$config_file" "$pvc_name" \ | kubectl_bin apply -f - else - cat_config "$1" \ + cat_config "$config_file" "$pvc_name"\ | yq eval 'del(.spec.backup.schedule.[1])' - \ | kubectl_bin apply -f - fi @@ -980,7 +988,7 @@ spinup_pxc() { kubectl_bin apply -f $secretsFile apply_config "$pxcClientFile" if [[ $IMAGE_PXC =~ 5\.7 ]] && [[ $cluster == 'demand-backup' || $cluster == 'demand-backup-cloud' ]]; then - cat_config "$config" \ + cat_config "$config"\ | $sed '/\[sst\]/,+1d' \ | $sed 's|compress=lz4|compress|' \ | kubectl_bin apply -f - @@ -1108,8 +1116,10 @@ retry() { } check_pvc_md5() { + local backup_name="$1" desc 'check backup file md5sum' - apply_config "$test_dir/conf/client.yml" + pvc_name=$(get_pvc_name_for_backup "$backup_name") || exit 1 + apply_config "$test_dir/conf/client.yml" "$pvc_name" sleep 10 bak_client_pod=$( kubectl_bin get pods \ @@ -1137,10 +1147,12 @@ run_recovery_check() { local cluster=$1 local backup=$2 local proxy=$(get_proxy_engine $cluster) - + pvc_name=$(get_pvc_name_for_backup "$backup") + dest="pvc/$pvc_name" log "run pxc-restore/${backup}" cat "$test_dir/conf/restore-${backup}.yaml" \ | $sed -e "s~minio-service.#namespace~minio-service.$namespace~" \ + | $sed -e "s##${dest}#g" \ | kubectl_bin apply -f - wait_backup_restore ${backup} kubectl_bin logs job/restore-job-${backup}-${cluster} @@ -1976,7 +1988,6 @@ run_recovery_check_pitr() { local time_now=$5 local dest=$6 local gtid=$7 - desc 'recover backup' $restore cat "$test_dir/conf/${restore}.yaml" \ | $sed -e "s//${time_now}/g" \ @@ -2018,3 +2029,17 @@ run_recovery_check_pitr() { compare_mysql_cmd $compare "SELECT * from test.test;" "-h $cluster-pxc-2.$cluster-pxc -uroot -proot_password" kubectl_bin delete -f "$test_dir/conf/${restore}.yaml" } + +get_pvc_name_for_backup() { + local backup_name="$1" + + local destination=$(kubectl_bin get pxc-backup "$backup_name" -o jsonpath='{.status.destination}') + if [[ -z "$destination" ]]; then + echo "No destination found in backup $backup_name" + return 1 + fi + local pvc_name="${destination#pvc/}" + + echo "$pvc_name" +} + diff --git a/e2e-tests/one-pod/conf/client.yml b/e2e-tests/one-pod/conf/client.yml index f06191950c..32b1c22ac5 100644 --- a/e2e-tests/one-pod/conf/client.yml +++ b/e2e-tests/one-pod/conf/client.yml @@ -23,4 +23,4 @@ spec: volumes: - name: backup persistentVolumeClaim: - claimName: xb-on-demand-backup-pvc + claimName: -backup-pvc diff --git a/e2e-tests/one-pod/run b/e2e-tests/one-pod/run index cf9557b1b0..a0048756e4 100755 --- a/e2e-tests/one-pod/run +++ b/e2e-tests/one-pod/run @@ -36,22 +36,6 @@ spinup_pxc() { done } -check_pvc_md5() { - desc 'check backup file md5sum' - apply_config "$test_dir/conf/client.yml" - sleep 10 - bak_client_pod=$( - kubectl_bin get pods \ - --selector=name=backup-client \ - -o 'jsonpath={.items[].metadata.name}' - ) - wait_pod $bak_client_pod - kubectl_bin exec $bak_client_pod -- \ - bash -c "cd /backup; md5sum -c md5sum.txt" - kubectl_bin delete \ - -f $test_dir/conf/client.yml -} - run_backup() { local cluster=$1 local backup1=$2 @@ -96,7 +80,7 @@ main() { run_backup "$cluster" "on-demand-backup-pvc" run_recovery_check "$cluster" "on-demand-backup-pvc" - check_pvc_md5 + check_pvc_md5 "on-demand-backup-pvc" if [ -z "$SKIP_REMOTE_BACKUPS" ]; then run_backup "$cluster" "on-demand-backup-aws-s3" diff --git a/e2e-tests/restore-to-encrypted-cluster/conf/client.yml b/e2e-tests/restore-to-encrypted-cluster/conf/client.yml index f06191950c..32b1c22ac5 100644 --- a/e2e-tests/restore-to-encrypted-cluster/conf/client.yml +++ b/e2e-tests/restore-to-encrypted-cluster/conf/client.yml @@ -23,4 +23,4 @@ spec: volumes: - name: backup persistentVolumeClaim: - claimName: xb-on-demand-backup-pvc + claimName: -backup-pvc diff --git a/e2e-tests/restore-to-encrypted-cluster/run b/e2e-tests/restore-to-encrypted-cluster/run index 19b9cee47f..32d0db88c6 100755 --- a/e2e-tests/restore-to-encrypted-cluster/run +++ b/e2e-tests/restore-to-encrypted-cluster/run @@ -23,7 +23,7 @@ main() { vault1="vault-service-1-${RANDOM}" start_vault $vault1 run_recovery_check "$cluster" "on-demand-backup-pvc" - check_pvc_md5 + check_pvc_md5 "on-demand-backup-pvc" keyring_plugin_must_be_in_use "$cluster" table_must_not_be_encrypted "$cluster" "myApp" diff --git a/e2e-tests/security-context/run b/e2e-tests/security-context/run index b2a56bcc0b..a2483856ea 100755 --- a/e2e-tests/security-context/run +++ b/e2e-tests/security-context/run @@ -5,6 +5,7 @@ set -o errexit test_dir=$(realpath $(dirname $0)) . ${test_dir}/../functions +compare_dir="$test_dir/compare/" set_debug create_infra $namespace @@ -34,7 +35,7 @@ pfx="-changes" apply_config "$test_dir/conf/$cluster$pfx.yml" sleep 30 -desc 'check if service and statefulset chenged to expected config' +desc 'check if service and statefulset changed to expected config' compare_kubectl statefulset/$cluster-pxc $pfx compare_kubectl statefulset/$cluster-proxysql $pfx @@ -44,6 +45,16 @@ desc 'run pvc backup' backup="on-demand-backup-pvc" kubectl_bin apply -f "$test_dir/conf/$cluster-$backup.yml" wait_backup $backup +pvc_name=$(get_pvc_name_for_backup $backup) + +echo "$compare_dir" +for file in "$compare_dir"*; do + cat "$file" \ + | $sed -E "s#(claimName: xb-on-demand-backup-pvc)(-[0-9]{14}-[a-f0-9]{8})?#claimName: $pvc_name#" \ + > "${file}.patched" + mv "${file}.patched" "$file" +done + compare_kubectl job.batch/xb-$backup kubectl_bin config set-context "$(kubectl_bin config current-context)" --namespace="$namespace" diff --git a/pkg/apis/pxc/v1/pxc_backup_types.go b/pkg/apis/pxc/v1/pxc_backup_types.go index c08cfdbb8a..1fb3debd50 100644 --- a/pkg/apis/pxc/v1/pxc_backup_types.go +++ b/pkg/apis/pxc/v1/pxc_backup_types.go @@ -4,6 +4,7 @@ import ( "path" "strings" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "sigs.k8s.io/controller-runtime/pkg/client/apiutil" @@ -60,22 +61,23 @@ type PXCBackupSpec struct { } type PXCBackupStatus struct { - State PXCBackupState `json:"state,omitempty"` - Error string `json:"error,omitempty"` - CompletedAt *metav1.Time `json:"completed,omitempty"` - LastScheduled *metav1.Time `json:"lastscheduled,omitempty"` - Destination PXCBackupDestination `json:"destination,omitempty"` - StorageName string `json:"storageName,omitempty"` - S3 *BackupStorageS3Spec `json:"s3,omitempty"` - Azure *BackupStorageAzureSpec `json:"azure,omitempty"` - StorageType BackupStorageType `json:"storage_type"` - Image string `json:"image,omitempty"` - SSLSecretName string `json:"sslSecretName,omitempty"` - SSLInternalSecretName string `json:"sslInternalSecretName,omitempty"` - VaultSecretName string `json:"vaultSecretName,omitempty"` - Conditions []metav1.Condition `json:"conditions,omitempty"` - VerifyTLS *bool `json:"verifyTLS,omitempty"` - LatestRestorableTime *metav1.Time `json:"latestRestorableTime,omitempty"` + State PXCBackupState `json:"state,omitempty"` + Error string `json:"error,omitempty"` + CompletedAt *metav1.Time `json:"completed,omitempty"` + LastScheduled *metav1.Time `json:"lastscheduled,omitempty"` + Destination PXCBackupDestination `json:"destination,omitempty"` + StorageName string `json:"storageName,omitempty"` + S3 *BackupStorageS3Spec `json:"s3,omitempty"` + Azure *BackupStorageAzureSpec `json:"azure,omitempty"` + PVC *corev1.PersistentVolumeClaimSpec `json:"pvc,omitempty"` + StorageType BackupStorageType `json:"storage_type"` + Image string `json:"image,omitempty"` + SSLSecretName string `json:"sslSecretName,omitempty"` + SSLInternalSecretName string `json:"sslInternalSecretName,omitempty"` + VaultSecretName string `json:"vaultSecretName,omitempty"` + Conditions []metav1.Condition `json:"conditions,omitempty"` + VerifyTLS *bool `json:"verifyTLS,omitempty"` + LatestRestorableTime *metav1.Time `json:"latestRestorableTime,omitempty"` } type PXCBackupDestination string @@ -156,6 +158,8 @@ func (status *PXCBackupStatus) GetStorageType(cluster *PerconaXtraDBCluster) Bac return BackupStorageS3 case status.Azure != nil: return BackupStorageAzure + case status.PVC != nil: + return BackupStorageFilesystem } return "" @@ -198,3 +202,11 @@ func (cr *PerconaXtraDBClusterBackup) SetFailedStatusWithError(err error) { cr.Status.State = BackupFailed cr.Status.Error = err.Error() } + +func (status *PXCBackupStatus) SetFsPvcFromPVC(pvc *corev1.PersistentVolumeClaim) { + if status == nil || pvc == nil { + return + } + + status.PVC = pvc.Spec.DeepCopy() +} diff --git a/pkg/apis/pxc/v1/zz_generated.deepcopy.go b/pkg/apis/pxc/v1/zz_generated.deepcopy.go index b2b559c4a2..ff13629659 100644 --- a/pkg/apis/pxc/v1/zz_generated.deepcopy.go +++ b/pkg/apis/pxc/v1/zz_generated.deepcopy.go @@ -494,6 +494,11 @@ func (in *PXCBackupStatus) DeepCopyInto(out *PXCBackupStatus) { *out = new(BackupStorageAzureSpec) **out = **in } + if in.PVC != nil { + in, out := &in.PVC, &out.PVC + *out = new(corev1.PersistentVolumeClaimSpec) + (*in).DeepCopyInto(*out) + } if in.Conditions != nil { in, out := &in.Conditions, &out.Conditions *out = make([]metav1.Condition, len(*in)) diff --git a/pkg/controller/pxc/backup.go b/pkg/controller/pxc/backup.go index 41fa5f36cb..7a9cef230b 100644 --- a/pkg/controller/pxc/backup.go +++ b/pkg/controller/pxc/backup.go @@ -228,7 +228,7 @@ func (r *ReconcilePerconaXtraDBCluster) createBackupJob(ctx context.Context, cr func backupFinalizers(cr *api.PerconaXtraDBCluster, backupJob api.PXCScheduledBackupSchedule, storageType api.BackupStorageType) []string { switch storageType { - case api.BackupStorageS3, api.BackupStorageAzure: + case api.BackupStorageS3, api.BackupStorageAzure, api.BackupStorageFilesystem: if cr.CompareVersionWith("1.18.0") >= 0 && !backupJob.GetRetention().DeleteFromStorage { return []string{} } diff --git a/pkg/controller/pxcbackup/controller.go b/pkg/controller/pxcbackup/controller.go index 4f960a9998..8b6f6785ff 100644 --- a/pkg/controller/pxcbackup/controller.go +++ b/pkg/controller/pxcbackup/controller.go @@ -301,11 +301,6 @@ func (r *ReconcilePerconaXtraDBClusterBackup) createBackupJob( cr.Status.Destination.SetPVCDestination(pvc.Name) - // Set PerconaXtraDBClusterBackup instance as the owner and controller - if err := k8s.SetControllerReference(cr, pvc, r.scheme); err != nil { - return nil, errors.Wrap(err, "setControllerReference") - } - // Check if this PVC already exists err = r.client.Get(ctx, types.NamespacedName{Name: pvc.Name, Namespace: pvc.Namespace}, pvc) if err != nil && k8sErrors.IsNotFound(err) { @@ -322,6 +317,9 @@ func (r *ReconcilePerconaXtraDBClusterBackup) createBackupJob( if err != nil { return nil, errors.Wrap(err, "set storage FS") } + + cr.Status.SetFsPvcFromPVC(pvc) + case api.BackupStorageS3: if storage.S3 == nil { return nil, errors.New("s3 storage is not specified") @@ -422,7 +420,7 @@ func (r *ReconcilePerconaXtraDBClusterBackup) runBackupFinalizers(ctx context.Co var err error switch f { case naming.FinalizerDeleteBackup: - if (cr.Status.S3 == nil && cr.Status.Azure == nil) || cr.Status.Destination == "" { + if (cr.Status.S3 == nil && cr.Status.Azure == nil && cr.Status.PVC == nil) || cr.Status.Destination == "" { continue } @@ -434,6 +432,8 @@ func (r *ReconcilePerconaXtraDBClusterBackup) runBackupFinalizers(ctx context.Co err = r.runS3BackupFinalizer(ctx, cr) case api.BackupStorageAzure: err = r.runAzureBackupFinalizer(ctx, cr) + case api.BackupStorageFilesystem: + err = r.runFilesystemBackupFinalizer(ctx, cr) default: continue } @@ -525,6 +525,19 @@ func (r *ReconcilePerconaXtraDBClusterBackup) runAzureBackupFinalizer(ctx contex return nil } +func (r *ReconcilePerconaXtraDBClusterBackup) runFilesystemBackupFinalizer(ctx context.Context, cr *api.PerconaXtraDBClusterBackup) error { + log := logf.FromContext(ctx) + + backupName := cr.Status.Destination.BackupName() + log.Info("Deleting backup from fs-pvc", "name", cr.Name, "backupName", backupName) + err := r.deleteBackupPVC(ctx, cr.Namespace, backupName) + + if err != nil { + return errors.Wrapf(err, "failed to delete backup %s", cr.Name) + } + return nil +} + func (r *ReconcilePerconaXtraDBClusterBackup) runReleaseLockFinalizer(ctx context.Context, cr *api.PerconaXtraDBClusterBackup) error { err := k8s.ReleaseLease(ctx, r.client, naming.BackupLeaseName(cr.Spec.PXCCluster), cr.Namespace, naming.BackupHolderId(cr)) if k8sErrors.IsNotFound(err) || errors.Is(err, k8s.ErrNotTheHolder) { @@ -617,6 +630,7 @@ func (r *ReconcilePerconaXtraDBClusterBackup) updateJobStatus( StorageName: storageName, S3: storage.S3, Azure: storage.Azure, + PVC: bcp.Status.PVC, StorageType: storage.Type, Image: bcp.Status.Image, SSLSecretName: bcp.Status.SSLSecretName, @@ -865,3 +879,22 @@ func (r *ReconcilePerconaXtraDBClusterBackup) cleanUpSuspendedJob( return nil } + +func (r *ReconcilePerconaXtraDBClusterBackup) deleteBackupPVC(ctx context.Context, backupNamespace, backupPVCName string) error { + log := logf.FromContext(ctx) + log.Info("Deleting backup PVC", "namespace", backupNamespace, "pvc", backupPVCName) + + pvc := &corev1.PersistentVolumeClaim{} + err := r.client.Get(ctx, types.NamespacedName{Name: backupPVCName, Namespace: backupNamespace}, pvc) + if err != nil { + return errors.Wrap(err, "get backup PVC by name") + } + + err = r.client.Delete(ctx, pvc, &client.DeleteOptions{Preconditions: &metav1.Preconditions{UID: &pvc.UID}}) + if err != nil { + return errors.Wrapf(err, "delete backup PVC %s", pvc.Name) + } + + log.Info("Deleted backup PVC", "namespace", backupNamespace, "pvc", backupPVCName) + return nil +} diff --git a/pkg/pxc/backup/volume.go b/pkg/pxc/backup/volume.go index 4ddbc66850..33ecaf32f1 100644 --- a/pkg/pxc/backup/volume.go +++ b/pkg/pxc/backup/volume.go @@ -1,6 +1,9 @@ package backup import ( + "fmt" + "strings" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -14,13 +17,26 @@ func NewPVC(cr *api.PerconaXtraDBClusterBackup, cluster *api.PerconaXtraDBCluste if cluster.CompareVersionWith("1.16.0") >= 0 { ls = naming.LabelsCluster(cluster) } + + base := naming.BackupJobName(cr.Name, false) + + ts := cr.CreationTimestamp.UTC().Format("20060102150405") + + uidSuffix := strings.ToLower(string(cr.UID)) + if len(uidSuffix) > 8 { + uidSuffix = uidSuffix[:8] + } + + // Final name: xb--- + name := fmt.Sprintf("%s-%s-%s", base, ts, uidSuffix) + return &corev1.PersistentVolumeClaim{ TypeMeta: metav1.TypeMeta{ APIVersion: "v1", Kind: "PersistentVolumeClaim", }, ObjectMeta: metav1.ObjectMeta{ - Name: naming.BackupJobName(cr.Name, false), + Name: name, Namespace: cr.Namespace, Labels: ls, },