diff --git a/Makefile b/Makefile index 9017f757..2a0d5a8a 100644 --- a/Makefile +++ b/Makefile @@ -116,6 +116,7 @@ generate: # sync crd generated to helm-chart echo '{{- if .Values.crd.create }}' > charts/zookeeper-operator/templates/zookeeper.pravega.io_zookeeperclusters_crd.yaml cat config/crd/bases/zookeeper.pravega.io_zookeeperclusters.yaml >> charts/zookeeper-operator/templates/zookeeper.pravega.io_zookeeperclusters_crd.yaml + cat config/crd/bases/zookeeper.pravega.io_zookeeperbackups.yaml >> charts/zookeeper-operator/templates/zookeeper.pravega.io_zookeeperclusters_crd.yaml echo '{{- end }}' >> charts/zookeeper-operator/templates/zookeeper.pravega.io_zookeeperclusters_crd.yaml diff --git a/README.md b/README.md index ad0e56be..ae033f7b 100644 --- a/README.md +++ b/README.md @@ -375,7 +375,7 @@ approach described in [article](https://www.elastic.co/blog/zookeeper-backup-a-t Exmaple CR of zookeeper backup: ```yaml apiVersion: "zookeeper.pravega.io/v1beta1" -kind: "ZookeeperCluster" +kind: "ZookeeperBackup" metadata: name: "example-backup" spec: diff --git a/api/v1beta1/zookeeperbackup_types.go b/api/v1beta1/zookeeperbackup_types.go index 69abf4c8..d0e10ebe 100644 --- a/api/v1beta1/zookeeperbackup_types.go +++ b/api/v1beta1/zookeeperbackup_types.go @@ -14,9 +14,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! -// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. - // ZookeeperBackupSpec defines the desired state of ZookeeperBackup type ZookeeperBackupSpec struct { // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster diff --git a/build_backup/backup.sh b/build_backup/backup.sh index 46783a5e..02606113 100755 --- a/build_backup/backup.sh +++ b/build_backup/backup.sh @@ -1,6 +1,6 @@ #!/bin/sh -echo "--------------- Check required parameters ---------------" +echo "--------------- Check required env variables ---------------" _req_envs=" Required parameters: \n BACKUPDIR: $BACKUPDIR \n @@ -14,6 +14,10 @@ if [ -z "$BACKUPDIR" ] || [ -z "$ZOOKEEPERDATADIR" ] || [ -z "$BACKUPS_TO_KEEP" exit 1 fi +echo "--------------- Check BACKUPS_TO_KEEP variable ---------------" +if ! [[ $BACKUPS_TO_KEEP =~ ^[0-9]+$ ]] ; + then echo "Error: $BACKUPS_TO_KEEP not a number" >&2; exit 1 +fi # Create backup directory if absent. # ---------------------------------- echo "--------------- Check backup/tmp dirs ---------------" @@ -53,7 +57,7 @@ BACKUPS_AMOUNT=`find . -path "*/zookeeper-*.tar.gz" -type f -printf "\n%AD %AT % TO_DELETE=$(( $BACKUPS_AMOUNT - $BACKUPS_TO_KEEP )) if [ $TO_DELETE -gt 0 ] ; then echo "Keeping only $BACKUPS_TO_KEEP full backups" - ls -t | tail -n -$TO_DELETE | xargs -d '\n' rm -rf + ls -t zookeeper-*.tar.gz | tail -n -$TO_DELETE | xargs -d '\n' rm -rf else echo "There are less backups than required, nothing to delete." fi diff --git a/charts/zookeeper-operator/templates/zookeeper.pravega.io_zookeeperclusters_crd.yaml b/charts/zookeeper-operator/templates/zookeeper.pravega.io_zookeeperclusters_crd.yaml index 03555d8d..217364cf 100644 --- a/charts/zookeeper-operator/templates/zookeeper.pravega.io_zookeeperclusters_crd.yaml +++ b/charts/zookeeper-operator/templates/zookeeper.pravega.io_zookeeperclusters_crd.yaml @@ -5849,4 +5849,86 @@ spec: storage: true subresources: status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.9.0 + creationTimestamp: null + name: zookeeperbackups.zookeeper.pravega.io +spec: + group: zookeeper.pravega.io + names: + kind: ZookeeperBackup + listKind: ZookeeperBackupList + plural: zookeeperbackups + singular: zookeeperbackup + scope: Namespaced + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + description: ZookeeperBackup is the Schema for the zookeeperbackups API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: ZookeeperBackupSpec defines the desired state of ZookeeperBackup + properties: + backupsToKeep: + default: "7" + description: Number of backups to store + type: string + dataCapacity: + default: 1Gi + description: Data Storage Capacity + type: string + dataStorageClass: + description: Data Storage Class name + type: string + image: + description: Image for backup procedure + properties: + pullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + enum: + - Always + - Never + - IfNotPresent + type: string + repository: + type: string + tag: + type: string + type: object + schedule: + default: 0 0 */1 * * + description: Schedule in Cron format + type: string + zookeeperCluster: + description: Name of the ZookeeperCluster to backup + type: string + required: + - zookeeperCluster + type: object + status: + description: ZookeeperBackupStatus defines the observed state of ZookeeperBackup + type: object + type: object + served: true + storage: true + subresources: + status: {} {{- end }} diff --git a/config/crd/bases/zookeeper.pravega.io_zookeeperbackups.yaml b/config/crd/bases/zookeeper.pravega.io_zookeeperbackups.yaml index 41f0033f..4dbba0c1 100644 --- a/config/crd/bases/zookeeper.pravega.io_zookeeperbackups.yaml +++ b/config/crd/bases/zookeeper.pravega.io_zookeeperbackups.yaml @@ -1,3 +1,4 @@ +--- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: @@ -14,63 +15,68 @@ spec: singular: zookeeperbackup scope: Namespaced versions: - - name: v1beta1 - schema: - openAPIV3Schema: - description: ZookeeperBackup is the Schema for the zookeeperbackups API - type: object - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: ZookeeperBackupSpec defines the desired state of ZookeeperBackup - type: object - required: - - zookeeperCluster - properties: - backupsToKeep: - description: Number of backups to store - type: string - default: "7" - dataCapacity: - description: Data Storage Capacity - type: string - default: 1Gi - dataStorageClass: - description: Data Storage Class name - type: string - image: - description: Image for backup procedure - type: object - properties: - pullPolicy: - description: PullPolicy describes a policy for if/when to pull a container image - type: string - enum: - - Always - - Never - - IfNotPresent - repository: - type: string - tag: - type: string - schedule: - description: Schedule in Cron format - type: string - default: 0 0 */1 * * - zookeeperCluster: - description: Name of the ZookeeperCluster to backup - type: string - status: - description: ZookeeperBackupStatus defines the observed state of ZookeeperBackup - type: object - served: true - storage: true - subresources: - status: {} + - name: v1beta1 + schema: + openAPIV3Schema: + description: ZookeeperBackup is the Schema for the zookeeperbackups API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: ZookeeperBackupSpec defines the desired state of ZookeeperBackup + properties: + backupsToKeep: + default: "7" + description: Number of backups to store + type: string + dataCapacity: + default: 1Gi + description: Data Storage Capacity + type: string + dataStorageClass: + description: Data Storage Class name + type: string + image: + description: Image for backup procedure + properties: + pullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + enum: + - Always + - Never + - IfNotPresent + type: string + repository: + type: string + tag: + type: string + type: object + schedule: + default: 0 0 */1 * * + description: Schedule in Cron format + type: string + zookeeperCluster: + description: Name of the ZookeeperCluster to backup + type: string + required: + - zookeeperCluster + type: object + status: + description: ZookeeperBackupStatus defines the observed state of ZookeeperBackup + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 5a016b46..330b5bc2 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -1,4 +1,3 @@ - --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole @@ -6,49 +5,49 @@ metadata: creationTimestamp: null name: manager-role rules: - - apiGroups: - - zookeeper.pravega.io.zookeeper.pravega.io - resources: - - zookeeperbackups - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - apiGroups: - - zookeeper.pravega.io.zookeeper.pravega.io - resources: - - zookeeperbackups/finalizers - verbs: - - update - - apiGroups: - - zookeeper.pravega.io.zookeeper.pravega.io - resources: - - zookeeperbackups/status - verbs: - - get - - patch - - update - - apiGroups: - - zookeeper.pravega.io.zookeeper.pravega.io - resources: - - zookeeperclusters - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - apiGroups: - - zookeeper.pravega.io.zookeeper.pravega.io - resources: - - zookeeperclusters/status - verbs: - - get - - patch - - update +- apiGroups: + - zookeeper.pravega.io.zookeeper.pravega.io + resources: + - zookeeperbackups + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - zookeeper.pravega.io.zookeeper.pravega.io + resources: + - zookeeperbackups/finalizers + verbs: + - update +- apiGroups: + - zookeeper.pravega.io.zookeeper.pravega.io + resources: + - zookeeperbackups/status + verbs: + - get + - patch + - update +- apiGroups: + - zookeeper.pravega.io.zookeeper.pravega.io + resources: + - zookeeperclusters + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - zookeeper.pravega.io.zookeeper.pravega.io + resources: + - zookeeperclusters/status + verbs: + - get + - patch + - update diff --git a/controllers/zookeeperbackup_controller.go b/controllers/zookeeperbackup_controller.go index 81751168..b13e41fb 100644 --- a/controllers/zookeeperbackup_controller.go +++ b/controllers/zookeeperbackup_controller.go @@ -95,6 +95,7 @@ func (r *ZookeeperBackupReconciler) Reconcile(_ context.Context, request reconci pvc := newPVCForZookeeperBackup(zookeeperBackup) // Set ZookeeperBackup instance as the owner and controller if err := controllerutil.SetControllerReference(zookeeperBackup, pvc, r.Scheme); err != nil { + r.Log.Error(err, fmt.Sprintf("Can't set reference for pvc '%s'", pvc.Name)) return reconcile.Result{}, err } if pvc.Annotations == nil { @@ -116,6 +117,7 @@ func (r *ZookeeperBackupReconciler) Reconcile(_ context.Context, request reconci pvc.Annotations["last-applied-hash"] = pvcHashStr err = r.Client.Create(context.TODO(), pvc) if err != nil { + r.Log.Error(err, fmt.Sprintf("Can't create pvc '%s'", pvc.Name)) return reconcile.Result{}, err } } else if err != nil { @@ -129,7 +131,7 @@ func (r *ZookeeperBackupReconciler) Reconcile(_ context.Context, request reconci r.Log.Info("Update PVC", "Namespace", pvc.Namespace, "Name", pvc.Name) err = r.Client.Update(context.TODO(), pvc) if err != nil { - r.Log.Error(err, "PVC cannot be updated") + r.Log.Error(err, fmt.Sprintf("PVC '%s' cannot be updated", pvc.Name)) return reconcile.Result{}, err } } @@ -143,7 +145,7 @@ func (r *ZookeeperBackupReconciler) Reconcile(_ context.Context, request reconci } // Check Zookeeper Cluster status - if foundZookeeperCluster.Status.Replicas != foundZookeeperCluster.Status.ReadyReplicas { + if foundZookeeperCluster.Spec.Replicas != foundZookeeperCluster.Status.ReadyReplicas { r.Log.Info(fmt.Sprintf("Not all cluster replicas are ready: %d/%d. Suspend CronJob", foundZookeeperCluster.Status.ReadyReplicas, foundZookeeperCluster.Status.Replicas)) *cronJob.Spec.Suspend = true @@ -156,8 +158,8 @@ func (r *ZookeeperBackupReconciler) Reconcile(_ context.Context, request reconci Name: svcAdminName, Namespace: foundZookeeperCluster.Namespace, }, foundSvcAdmin) - if err != nil && errors.IsNotFound(err) { - r.Log.Error(err, fmt.Sprintf("Zookeeper admin service '%s' not found", svcAdminName)) + if err != nil { + r.Log.Error(err, fmt.Sprintf("Can't get Zookeeper admin service '%s'", svcAdminName)) return reconcile.Result{}, err }