message:
reduce number of configmaps update
Update configmap only if it's changed to reduce number of unneeded updates and etcd load

diff:
@@ -4,6 +4,7 @@ import (
"container/heap"
"context"
"fmt"
+ "reflect"
"github.com/pkg/errors"
batchv1beta1 "k8s.io/api/batch/v1beta1"
@@ -45,19 +46,23 @@ func (r *ReconcilePerconaXtraDBCluster) reconcileBackups(cr *api.PerconaXtraDBCl
// Check if this Job already exists
currentBcpJob := new(batchv1beta1.CronJob)
- err = r.client.Get(context.TODO(), types.NamespacedName{Name: bcpjob.Name, Namespace: bcpjob.Namespace}, currentBcpJob)
- if err != nil && k8serrors.IsNotFound(err) {
- // reqLogger.Info("Creating a new backup job", "Namespace", bcpjob.Namespace, "Name", bcpjob.Name)
+ err = r.client.Get(context.TODO(), types.NamespacedName{
+ Name: bcpjob.Name,
+ Namespace: bcpjob.Namespace,
+ }, currentBcpJob)
+ if err != nil && !k8serrors.IsNotFound(err) {
+ return errors.Wrapf(err, "create scheduled backup %s", bcp.Name)
+ }
+
+ if k8serrors.IsNotFound(err) {
err = r.client.Create(context.TODO(), bcpjob)
if err != nil {
- return fmt.Errorf("create scheduled backup '%s': %v", bcp.Name, err)
+ return errors.Wrapf(err, "create scheduled backup %s", bcp.Name)
}
- } else if err != nil {
- return fmt.Errorf("create scheduled backup '%s': %v", bcp.Name, err)
- } else {
+ } else if !reflect.DeepEqual(currentBcpJob.Spec, bcpjob.Spec) {
err = r.client.Update(context.TODO(), bcpjob)
if err != nil {
- return fmt.Errorf("update backup schedule '%s': %v", bcp.Name, err)
+ return errors.Wrapf(err, "update backup schedule %s", bcp.Name)
}
}
}

diff:
@@ -4,6 +4,7 @@ import (
"context"
"crypto/md5"
"fmt"
+ "reflect"
"strings"
"sync"
"sync/atomic"
@@ -11,6 +12,7 @@ import (
"github.com/pkg/errors"
"github.com/robfig/cron/v3"
+ appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
policyv1beta1 "k8s.io/api/policy/v1beta1"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
@@ -286,8 +288,7 @@ func (r *ReconcilePerconaXtraDBCluster) Reconcile(request reconcile.Request) (re
pxc.MergeTemplateAnnotations(pxcSet.StatefulSet(), pxcAnnotations)
err = r.updatePod(pxcSet, o.Spec.PXC, o, inits)
if err != nil {
- err = fmt.Errorf("pxc upgrade error: %v", err)
- return reconcile.Result{}, err
+ return reconcile.Result{}, errors.Wrap(err, "pxc upgrade error")
}
for _, pxcService := range []*corev1.Service{pxc.NewServicePXC(o), pxc.NewServicePXCUnready(o)} {
@@ -297,12 +298,15 @@ func (r *ReconcilePerconaXtraDBCluster) Reconcile(request reconcile.Request) (re
return reconcile.Result{}, errors.Wrap(err, "failed to get current PXC service")
}
+ if reflect.DeepEqual(currentService.Spec.Ports, pxcService.Spec.Ports) {
+ continue
+ }
+
currentService.Spec.Ports = pxcService.Spec.Ports
err = r.client.Update(context.TODO(), currentService)
if err != nil {
- err = fmt.Errorf("PXC service upgrade error: %v", err)
- return reconcile.Result{}, err
+ return reconcile.Result{}, errors.Wrap(err, "PXC service upgrade error")
}
}
@@ -312,15 +316,13 @@ func (r *ReconcilePerconaXtraDBCluster) Reconcile(request reconcile.Request) (re
if o.Spec.HAProxy != nil && o.Spec.HAProxy.Enabled {
err = r.updatePod(haProxySet, o.Spec.HAProxy, o, nil)
if err != nil {
- err = fmt.Errorf("HAProxy upgrade error: %v", err)
- return reconcile.Result{}, err
+ return reconcile.Result{}, errors.Wrap(err, "HAProxy upgrade error")
}
currentService := &corev1.Service{}
err := r.client.Get(context.TODO(), types.NamespacedName{Name: haProxyService.Name, Namespace: haProxyService.Namespace}, currentService)
if err != nil {
- err = fmt.Errorf("failed to get HAProxy service: %v", err)
- return reconcile.Result{}, err
+ return reconcile.Result{}, errors.Wrap(err, "failed to get HAProxy service")
}
ports := []corev1.ServicePort{
@@ -376,8 +378,7 @@ func (r *ReconcilePerconaXtraDBCluster) Reconcile(request reconcile.Request) (re
currentServiceReplicas := &corev1.Service{}
err = r.client.Get(context.TODO(), types.NamespacedName{Name: haProxyServiceReplicas.Name, Namespace: haProxyServiceReplicas.Namespace}, currentServiceReplicas)
if err != nil {
- err = fmt.Errorf("failed to get HAProxyReplicas service: %v", err)
- return reconcile.Result{}, err
+ return reconcile.Result{}, errors.Wrap(err, "failed to get HAProxyReplicas service")
}
replicaPorts := []corev1.ServicePort{
@@ -409,18 +410,17 @@ func (r *ReconcilePerconaXtraDBCluster) Reconcile(request reconcile.Request) (re
err = r.client.Update(context.TODO(), currentServiceReplicas)
if err != nil {
- err = fmt.Errorf("HAProxyReplicas service upgrade error: %v", err)
- return reconcile.Result{}, err
+ return reconcile.Result{}, errors.Wrap(err, "HAProxyReplicas service upgrade error")
}
} else {
err = r.deleteStatefulSet(o.Namespace, haProxySet, false)
if err != nil {
- return reconcile.Result{}, err
+ return reconcile.Result{}, errors.Wrap(err, "delete HAProxy stateful set")
}
haProxyReplicasService := pxc.NewServiceHAProxyReplicas(o)
err = r.deleteServices([]*corev1.Service{haProxyService, haProxyReplicasService})
if err != nil {
- return reconcile.Result{}, err
+ return reconcile.Result{}, errors.Wrap(err, "delete HAProxy replica service")
}
}
@@ -787,22 +787,18 @@ func (r *ReconcilePerconaXtraDBCluster) reconcileConfigMap(cr *api.PerconaXtraDB
if cr.CompareVersionWith("1.3.0") >= 0 {
if len(limitMemory) > 0 || len(requestMemory) > 0 {
- autoConfigMap, err := config.NewAutoTuneConfigMap(cr, "auto-"+ls["app.kubernetes.io/instance"]+"-"+ls["app.kubernetes.io/component"])
+ configMap, err := config.NewAutoTuneConfigMap(cr, "auto-"+ls["app.kubernetes.io/instance"]+"-"+ls["app.kubernetes.io/component"])
if err != nil {
return errors.Wrap(err, "new auto-config map")
}
- err = setControllerReference(cr, autoConfigMap, r.scheme)
+ err = setControllerReference(cr, configMap, r.scheme)
if err != nil {
return errors.Wrap(err, "set auto-config controller ref")
}
- err = r.client.Create(context.TODO(), autoConfigMap)
- if err != nil && k8serrors.IsAlreadyExists(err) {
- err = r.client.Update(context.TODO(), autoConfigMap)
+
+ err = createOrUpdateConfigmap(r.client, configMap)
if err != nil {
- return errors.Wrap(err, "update AutoConfigMap")
- }
- } else if err != nil {
- return errors.Wrap(err, "create AutoConfigMap")
+ return errors.Wrap(err, "auto-config config map")
}
}
}
@@ -813,48 +809,36 @@ func (r *ReconcilePerconaXtraDBCluster) reconcileConfigMap(cr *api.PerconaXtraDB
if err != nil {
return errors.Wrap(err, "set controller ref")
}
- err = r.client.Create(context.TODO(), configMap)
- if err != nil && k8serrors.IsAlreadyExists(err) {
- err = r.client.Update(context.TODO(), configMap)
+
+ err = createOrUpdateConfigmap(r.client, configMap)
if err != nil {
- return errors.Wrap(err, "update ConfigMap")
- }
- } else if err != nil {
- return errors.Wrap(err, "create ConfigMap")
+ return errors.Wrap(err, "pxc config map")
}
}
- if cr.Spec.ProxySQL != nil && cr.Spec.ProxySQL.Configuration != "" {
+ if cr.Spec.ProxySQL != nil && cr.Spec.ProxySQL.Enabled && cr.Spec.ProxySQL.Configuration != "" {
configMap := config.NewConfigMap(cr, ls["app.kubernetes.io/instance"]+"-proxysql", "proxysql.cnf", cr.Spec.ProxySQL.Configuration)
err := setControllerReference(cr, configMap, r.scheme)
if err != nil {
return errors.Wrap(err, "set controller ref ProxySQL")
}
- err = r.client.Create(context.TODO(), configMap)
- if err != nil && k8serrors.IsAlreadyExists(err) {
- err = r.client.Update(context.TODO(), configMap)
+
+ err = createOrUpdateConfigmap(r.client, configMap)
if err != nil {
- return errors.Wrap(err, "update ConfigMap HAProxy")
- }
- } else if err != nil {
- return errors.Wrap(err, "create ConfigMap HAProxy")
+ return errors.Wrap(err, "proxysql config map")
}
}
- if cr.Spec.HAProxy != nil && cr.Spec.HAProxy.Configuration != "" {
+ if cr.Spec.HAProxy != nil && cr.Spec.HAProxy.Enabled && cr.Spec.HAProxy.Configuration != "" {
configMap := config.NewConfigMap(cr, ls["app.kubernetes.io/instance"]+"-haproxy", "haproxy-global.cfg", cr.Spec.HAProxy.Configuration)
err := setControllerReference(cr, configMap, r.scheme)
if err != nil {
return errors.Wrap(err, "set controller ref HAProxy")
}
- err = r.client.Create(context.TODO(), configMap)
- if err != nil && k8serrors.IsAlreadyExists(err) {
- err = r.client.Update(context.TODO(), configMap)
+
+ err = createOrUpdateConfigmap(r.client, configMap)
if err != nil {
- return errors.Wrap(err, "update ConfigMap HAProxy")
- }
- } else if err != nil {
- return errors.Wrap(err, "create ConfigMap HAProxy")
+ return errors.Wrap(err, "haproxy config map")
}
}
@@ -943,14 +927,26 @@ func (r *ReconcilePerconaXtraDBCluster) deleteStatefulSetPods(namespace string,
}
func (r *ReconcilePerconaXtraDBCluster) deleteStatefulSet(namespace string, sfs api.StatefulApp, deletePVC bool) error {
- err := r.client.Delete(context.TODO(), sfs.StatefulSet())
+ err := r.client.Get(context.TODO(), types.NamespacedName{
+ Name: sfs.StatefulSet().Name,
+ Namespace: namespace,
+ }, &appsv1.StatefulSet{})
+ if err != nil && !k8serrors.IsNotFound(err) {
+ return errors.Wrapf(err, "get statefulset: %s", sfs.StatefulSet().Name)
+ }
+
+ if k8serrors.IsNotFound(err) {
+ return nil
+ }
+
+ err = r.client.Delete(context.TODO(), sfs.StatefulSet())
if err != nil && !k8serrors.IsNotFound(err) {
- return fmt.Errorf("delete proxysql: %v", err)
+ return errors.Wrapf(err, "delete statefulset: %s", sfs.StatefulSet().Name)
}
if deletePVC {
err = r.deletePVC(namespace, sfs.Labels())
if err != nil {
- return fmt.Errorf("delete proxysql pvc: %v", err)
+ return errors.Wrapf(err, "delete pvc: %s", sfs.StatefulSet().Name)
}
}
@@ -959,9 +955,21 @@ func (r *ReconcilePerconaXtraDBCluster) deleteStatefulSet(namespace string, sfs
func (r *ReconcilePerconaXtraDBCluster) deleteServices(svcs []*corev1.Service) error {
for _, s := range svcs {
- err := r.client.Delete(context.TODO(), s)
+ err := r.client.Get(context.TODO(), types.NamespacedName{
+ Name: s.Name,
+ Namespace: s.Namespace,
+ }, &corev1.Service{})
if err != nil && !k8serrors.IsNotFound(err) {
- return fmt.Errorf("delete service: %v", err)
+ return errors.Wrapf(err, "get service: %s", s.Name)
+ }
+
+ if k8serrors.IsNotFound(err) {
+ continue
+ }
+
+ err = r.client.Delete(context.TODO(), s)
+ if err != nil {
+ return errors.Wrapf(err, "delete service: %s", s.Name)
}
}
return nil
@@ -1035,3 +1043,24 @@ func (r *ReconcilePerconaXtraDBCluster) resyncPXCUsersWithProxySQL(cr *api.Perco
atomic.StoreInt32(&r.syncUsersState, stateFree)
}()
}
+
+func createOrUpdateConfigmap(cl client.Client, configMap *corev1.ConfigMap) error {
+ currMap := &corev1.ConfigMap{}
+ err := cl.Get(context.TODO(), types.NamespacedName{
+ Namespace: configMap.Namespace,
+ Name: configMap.Name,
+ }, currMap)
+ if err != nil && !k8serrors.IsNotFound(err) {
+ return errors.Wrap(err, "get current configmap")
+ }
+
+ if k8serrors.IsNotFound(err) {
+ return cl.Create(context.TODO(), configMap)
+ }
+
+ if !reflect.DeepEqual(currMap.Data, configMap.Data) {
+ return cl.Update(context.TODO(), configMap)
+ }
+
+ return nil
+}

original_message:
K8SPXC-546: reduce number of configmaps update (#683)

Update configmap only if it's changed to reduce number of unneeded updates and etcd load


message: add graceful operator shutdown

change_type: MODIFY

diff:
@@ -8,21 +8,21 @@ import (
"runtime"
"strings"
- _ "github.com/Percona-Lab/percona-version-service/api"
certmgrscheme "github.com/jetstack/cert-manager/pkg/client/clientset/versioned/scheme"
"github.com/operator-framework/operator-sdk/pkg/k8sutil"
"github.com/operator-framework/operator-sdk/pkg/leader"
"github.com/operator-framework/operator-sdk/pkg/ready"
sdkVersion "github.com/operator-framework/operator-sdk/version"
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
+ "sigs.k8s.io/controller-runtime/pkg/cache"
"sigs.k8s.io/controller-runtime/pkg/client/config"
"sigs.k8s.io/controller-runtime/pkg/manager"
- "sigs.k8s.io/controller-runtime/pkg/cache"
logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
- "sigs.k8s.io/controller-runtime/pkg/runtime/signals"
+ _ "github.com/Percona-Lab/percona-version-service/api"
"github.com/percona/percona-xtradb-cluster-operator/pkg/apis"
"github.com/percona/percona-xtradb-cluster-operator/pkg/controller"
+ "github.com/percona/percona-xtradb-cluster-operator/pkg/k8s"
"github.com/percona/percona-xtradb-cluster-operator/pkg/webhook"
"github.com/percona/percona-xtradb-cluster-operator/version"
)
@@ -127,8 +127,10 @@ func main() {
log.Info("Starting the Cmd.")
+ stopCH := k8s.StartStopSignalHandler(mgr.GetClient(), strings.Split(namespace, ","))
+
// Start the Cmd
- if err := mgr.Start(signals.SetupSignalHandler()); err != nil {
+ if err := mgr.Start(stopCH); err != nil {
log.Error(err, "manager exited non-zero")
os.Exit(1)
}

diff:
@@ -115,7 +115,7 @@ main() {
wait_for_delete pod/$cluster-pxc-3
desc 'stop operator'
- pumba_pod stop
+ pumba_pod "stop -t 10"
desc 'check if operator works fine: scale up from 3 to 4'
cat_config "$test_dir/conf/$cluster.yml" \
| sed -e 's/size: 3/size: 4/' \

change_type: ADD

diff:
+package k8s
+
+import (
+ "context"
+ "time"
+
+ api "github.com/percona/percona-xtradb-cluster-operator/pkg/apis/pxc/v1"
+ "github.com/pkg/errors"
+ k8serrors "k8s.io/apimachinery/pkg/api/errors"
+ "sigs.k8s.io/controller-runtime/pkg/client"
+ logf "sigs.k8s.io/controller-runtime/pkg/log"
+ "sigs.k8s.io/controller-runtime/pkg/manager/signals"
+)
+
+var log = logf.Log
+
+// StartStopSignalHandler starts gorutine which is waiting for
+// termination signal and returns chan for indication when operator
+// can really stop.
+func StartStopSignalHandler(client client.Client, namespaces []string) <-chan struct{} {
+ stopCH := make(chan struct{})
+ go handleStopSignal(client, namespaces, stopCH)
+ return stopCH
+}
+
+func handleStopSignal(client client.Client, namespaces []string, stopCH chan struct{}) {
+ <-signals.SetupSignalHandler()
+ stop(client, namespaces)
+ close(stopCH)
+}
+
+// Stop is used to understand, when we need to stop operator(usially SIGTERM)
+// to start cleanup process and delete required pxc clusters in current(operator)
+// namespace. See K8SPXC-529
+func stop(cl client.Client, namespaces []string) {
+ log.Info("Got stop signal, starting to list clusters")
+
+ readyToDelete := false
+
+ for !readyToDelete {
+ time.Sleep(5 * time.Second)
+ ready, err := checkClusters(cl, namespaces)
+ if err != nil {
+ log.Error(err, "delete clusters")
+ }
+ readyToDelete = ready
+ }
+}
+
+func checkClusters(cl client.Client, namespaces []string) (bool, error) {
+ for _, ns := range namespaces {
+
+ clusterList := &api.PerconaXtraDBClusterList{}
+
+ err := cl.List(context.TODO(), clusterList, &client.ListOptions{
+ Namespace: ns,
+ })
+ if err != nil {
+ if k8serrors.IsNotFound(err) {
+ continue
+ }
+ return false, errors.Wrapf(err, "list clusters in namespace: %s", ns)
+ }
+
+ if !isClustersReadyToDelete(clusterList.Items) {
+ return false, nil
+ }
+ }
+ return true, nil
+}
+
+func isClustersReadyToDelete(list []api.PerconaXtraDBCluster) bool {
+ for _, v := range list {
+ if v.ObjectMeta.DeletionTimestamp != nil && len(v.Finalizers) != 0 {
+ return false
+ }
+ }
+ return true
+}

license: Apache License 2.0

repo: percona/percona-xtradb-cluster-operator

original_message: K8SPXC-529: add graceful operator shutdown (#689)


diff:
@@ -15,7 +15,7 @@ spec:
sslSecretName: my-cluster-ssl
sslInternalSecretName: my-cluster-ssl-internal
logCollectorSecretName: my-log-collector-secrets
-# disableHookValidation: true
+# enableCRValidationWebhook: true
# tls:
# SANs:
# - pxc-1.example.com

diff:
@@ -14,7 +14,7 @@ spec:
vaultSecretName: keyring-secret-vault
sslSecretName: my-cluster-ssl
sslInternalSecretName: my-cluster-ssl-internal
-# disableHookValidation: true
+ enableCRValidationWebhook: true
# tls:
# SANs:
# - pxc-1.example.com

diff:
@@ -6,6 +6,7 @@ spec:
secretsName: my-cluster-secrets
sslSecretName: some-name-ssl
sslInternalSecretName: some-name-ssl-internal
+ enableCRValidationWebhook: true
pxc:
size: 3
image: -pxc

diff:
@@ -37,7 +37,7 @@ type PerconaXtraDBClusterSpec struct {
UpgradeOptions UpgradeOptions `json:"upgradeOptions,omitempty"`
AllowUnsafeConfig bool `json:"allowUnsafeConfigurations,omitempty"`
InitImage string `json:"initImage,omitempty"`
- DisableHookValidation bool `json:"disableHookValidation,omitempty"`
+ EnableCRValidationWebhook *bool `json:"enableCRValidationWebhook,omitempty"`
}
type PXCSpec struct {
@@ -643,6 +643,11 @@ func (cr *PerconaXtraDBCluster) CheckNSetDefaults(serverVersion *version.ServerV
cr.setSecurityContext()
+ if cr.Spec.EnableCRValidationWebhook == nil {
+ falseVal := false
+ cr.Spec.EnableCRValidationWebhook = &falseVal
+ }
+
return CRVerChanged || changed, nil
}

diff:
@@ -226,7 +226,7 @@ func (h *hook) ServeHTTP(w http.ResponseWriter, r *http.Request) {
return
}
- if cr.Spec.DisableHookValidation {
+ if cr.Spec.EnableCRValidationWebhook == nil || !*cr.Spec.EnableCRValidationWebhook {
err = sendResponse(req.Request.UID, req.TypeMeta, w, nil)
if err != nil {
log.Log.Error(err, "Can't send validation response")

original_message: K8SPXC-595: Change disableHookValidation field in cr (#721)


message: add owner references to webhook

diff:
@@ -10,9 +10,11 @@ import (
"github.com/pkg/errors"
admission "k8s.io/api/admission/v1"
admissionregistration "k8s.io/api/admissionregistration/v1"
+ appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/client-go/util/cert"
@@ -31,24 +33,44 @@ var hookPath = "/validate-percona-xtradbcluster"
type hook struct {
cl client.Client
+ scheme *runtime.Scheme
caBunlde []byte
namespace string
}
func (h *hook) Start(i <-chan struct{}) error {
- err := h.createService()
+ err := h.setup()
if err != nil {
- log.Log.Info("Can't create service", "err", err.Error())
+ log.Log.Info("failed to setup webhook", "err", err.Error())
}
- err = h.createWebhook()
+ <-i
+ return nil
+}
+
+func (h *hook) setup() error {
+ operatorDeployment, err := h.operatorDeployment()
if err != nil {
- log.Log.Info("Can't create webhook", "error", err.Error())
+ return errors.Wrap(err, "failed to get operator deployment")
+ }
+
+ ref, err := k8s.OwnerRef(operatorDeployment, h.scheme)
+ if err != nil {
+ return errors.Wrap(err, "failed to get deployment owner ref")
+ }
+
+ err = h.createService(ref)
+ if err != nil {
+ return errors.Wrap(err, "Can't create service")
+ }
+
+ err = h.createWebhook(ref)
+ if err != nil {
+ return errors.Wrap(err, "can't create webhook")
}
- <-i
return nil
}
-func (h *hook) createService() error {
+func (h *hook) createService(ownerRef metav1.OwnerReference) error {
opPod, err := k8s.OperatorPod(h.cl)
if err != nil {
return errors.Wrap(err, "get operator pod")
@@ -58,6 +80,7 @@ func (h *hook) createService() error {
Name: "percona-xtradb-cluster-operator",
Namespace: h.namespace,
Labels: map[string]string{"name": "percona-xtradb-cluster-operator"},
+ OwnerReferences: []metav1.OwnerReference{ownerRef},
},
Spec: corev1.ServiceSpec{
Ports: []corev1.ServicePort{{Port: 443, TargetPort: intstr.FromInt(9443)}},
@@ -77,6 +100,7 @@ func (h *hook) createService() error {
}
service.Spec.Selector = opPod.Labels
+ service.ObjectMeta.OwnerReferences = []metav1.OwnerReference{ownerRef}
return h.cl.Update(context.TODO(), service)
}
return err
@@ -84,12 +108,13 @@ func (h *hook) createService() error {
return nil
}
-func (h *hook) createWebhook() error {
+func (h *hook) createWebhook(ownerRef metav1.OwnerReference) error {
failPolicy := admissionregistration.Fail
sideEffects := admissionregistration.SideEffectClassNone
hook := &admissionregistration.ValidatingWebhookConfiguration{
ObjectMeta: metav1.ObjectMeta{
Name: "percona-xtradbcluster-webhook",
+ OwnerReferences: []metav1.OwnerReference{ownerRef},
},
Webhooks: []admissionregistration.ValidatingWebhook{
{
@@ -118,7 +143,12 @@ func (h *hook) createWebhook() error {
},
},
}
+
err := h.cl.Create(context.TODO(), hook)
+ if k8serrors.IsForbidden(err) {
+ return nil
+ }
+
if err != nil && k8serrors.IsAlreadyExists(err) {
hook := &admissionregistration.ValidatingWebhookConfiguration{}
err := h.cl.Get(context.TODO(), types.NamespacedName{
@@ -129,6 +159,7 @@ func (h *hook) createWebhook() error {
}
hook.Webhooks[0].ClientConfig.CABundle = h.caBunlde
+ hook.ObjectMeta.OwnerReferences = []metav1.OwnerReference{ownerRef}
return h.cl.Update(context.TODO(), hook)
}
return err
@@ -152,7 +183,12 @@ func SetupWebhook(mgr manager.Manager) error {
return errors.Wrap(err, "prepare hook tls certs")
}
- h := &hook{cl: mgr.GetClient(), caBunlde: ca, namespace: namespace}
+ h := &hook{
+ cl: mgr.GetClient(),
+ scheme: mgr.GetScheme(),
+ caBunlde: ca,
+ namespace: namespace,
+ }
srv := mgr.GetWebhookServer()
srv.Port = 9443
@@ -266,3 +302,12 @@ func sendResponse(uid types.UID, meta metav1.TypeMeta, w http.ResponseWriter, er
}
return nil
}
+
+func (h *hook) operatorDeployment() (*appsv1.Deployment, error) {
+ deployment := &appsv1.Deployment{}
+ err := h.cl.Get(context.TODO(), types.NamespacedName{
+ Name: "percona-xtradb-cluster-operator",
+ Namespace: h.namespace,
+ }, deployment)
+ return deployment, err
+}

original_message: add owner references to webhook


change_type: DELETE

diff:
-apiVersion: batch/v1beta1
-kind: CronJob
-metadata:
- annotations:
- testName: scheduled-backup
- labels:
- backupWorker: "True"
- cluster: scheduled-backup
- schedule: N_N_N_N_N
- type: cron
- name: each-min-pvc
- ownerReferences:
- - controller: true
- kind: PerconaXtraDBCluster
- name: scheduled-backup
-spec:
- concurrencyPolicy: Allow
- failedJobsHistoryLimit: 1
- jobTemplate:
- metadata:
- ownerReferences:
- - apiVersion: batch/v1beta1
- kind: CronJob
- name: each-min-pvc
- spec:
- template:
- metadata:
- annotations:
- testName: scheduled-backup
- labels:
- backupWorker: "True"
- cluster: scheduled-backup
- schedule: N_N_N_N_N
- type: cron
- spec:
- affinity:
- nodeAffinity:
- requiredDuringSchedulingIgnoredDuringExecution:
- nodeSelectorTerms:
- - matchExpressions:
- - key: backupWorker
- operator: In
- values:
- - "True"
- containers:
- - args:
- - sh
- - -c
- - "\n\t\t\t\t\t\t\tcat <<-EOF | kubectl apply -f -\n\t\t\t\t\t\t\t\t\tapiVersion: pxc.percona.com/v1\n\t\t\t\t\t\t\t\t\tkind: PerconaXtraDBClusterBackup\n\t\t\t\t\t\t\t\t\tmetadata:\n\t\t\t\t\t\t\t\t\t name: \"cron-${pxcCluster:0:16}-pvc-$(date -u \"+%Y%m%d%H%M%S\")-${suffix}\"\n\t\t\t\t\t\t\t\t\t labels:\n\t\t\t\t\t\t\t\t\t ancestor: \"each-min-pvc\"\n\t\t\t\t\t\t\t\t\t cluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t type: \"cron\"\n\t\t\t\t\t\t\t\t\tspec:\n\t\t\t\t\t\t\t\t\t pxcCluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t storageName: \"pvc\"\n\t\t\t\t\t\t\tEOF\n\t\t\t\t\t\t\t"
- env:
- - name: pxcCluster
- value: scheduled-backup
- imagePullPolicy: Always
- name: run-backup
- resources:
- requests:
- cpu: 600m
- memory: 1G
- terminationMessagePath: /dev/termination-log
- terminationMessagePolicy: File
- dnsPolicy: ClusterFirst
- nodeSelector:
- backupWorker: "True"
- priorityClassName: high-priority
- restartPolicy: Never
- schedulerName: default-scheduler
- securityContext:
- supplementalGroups:
- - 1001
- serviceAccount: percona-xtradb-cluster-operator
- serviceAccountName: percona-xtradb-cluster-operator
- terminationGracePeriodSeconds: 30
- tolerations:
- - effect: NoSchedule
- key: backupWorker
- operator: Equal
- value: "True"
- schedule: '* * * * *'
- successfulJobsHistoryLimit: 1
- suspend: false

diff:
-apiVersion: batch/v1beta1
-kind: CronJob
-metadata:
- annotations:
- testName: scheduled-backup
- labels:
- backupWorker: "True"
- cluster: scheduled-backup
- schedule: N_N_N_N_N
- type: cron
- name: each-min-pvc
- ownerReferences:
- - controller: true
- kind: PerconaXtraDBCluster
- name: scheduled-backup
-spec:
- concurrencyPolicy: Allow
- failedJobsHistoryLimit: 1
- jobTemplate:
- metadata:
- ownerReferences:
- - apiVersion: batch/v1beta1
- kind: CronJob
- name: each-min-pvc
- spec:
- template:
- metadata:
- annotations:
- testName: scheduled-backup
- labels:
- backupWorker: "True"
- cluster: scheduled-backup
- schedule: N_N_N_N_N
- type: cron
- spec:
- affinity:
- nodeAffinity:
- requiredDuringSchedulingIgnoredDuringExecution:
- nodeSelectorTerms:
- - matchExpressions:
- - key: backupWorker
- operator: In
- values:
- - "True"
- containers:
- - args:
- - sh
- - -c
- - "\n\t\t\t\t\t\t\tcat <<-EOF | kubectl apply -f -\n\t\t\t\t\t\t\t\t\tapiVersion: pxc.percona.com/v1\n\t\t\t\t\t\t\t\t\tkind: PerconaXtraDBClusterBackup\n\t\t\t\t\t\t\t\t\tmetadata:\n\t\t\t\t\t\t\t\t\t name: \"cron-${pxcCluster:0:16}-pvc-$(date -u \"+%Y%m%d%H%M%S\")-${suffix}\"\n\t\t\t\t\t\t\t\t\t labels:\n\t\t\t\t\t\t\t\t\t ancestor: \"each-min-pvc\"\n\t\t\t\t\t\t\t\t\t cluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t type: \"cron\"\n\t\t\t\t\t\t\t\t\tspec:\n\t\t\t\t\t\t\t\t\t pxcCluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t storageName: \"pvc\"\n\t\t\t\t\t\t\tEOF\n\t\t\t\t\t\t\t"
- env:
- - name: pxcCluster
- value: scheduled-backup
- imagePullPolicy: Always
- name: run-backup
- resources:
- requests:
- cpu: 600m
- memory: 1G
- terminationMessagePath: /dev/termination-log
- terminationMessagePolicy: File
- dnsPolicy: ClusterFirst
- nodeSelector:
- backupWorker: "True"
- priorityClassName: high-priority
- restartPolicy: Never
- schedulerName: default-scheduler
- securityContext:
- fsGroup: 1001
- supplementalGroups:
- - 1001
- serviceAccount: percona-xtradb-cluster-operator
- serviceAccountName: percona-xtradb-cluster-operator
- terminationGracePeriodSeconds: 30
- tolerations:
- - effect: NoSchedule
- key: backupWorker
- operator: Equal
- value: "True"
- schedule: '* * * * *'
- successfulJobsHistoryLimit: 1
- suspend: false

diff:
+apiVersion: batch/v1beta1
+kind: CronJob
+metadata:
+ annotations:
+ testName: scheduled-backup
+ labels:
+ backupWorker: "True"
+ cluster: scheduled-backup
+ schedule: N_N_N_N_N
+ type: cron
+ name: f875c-each-min-aws-s3
+ ownerReferences:
+ - controller: true
+ kind: PerconaXtraDBCluster
+ name: scheduled-backup
+spec:
+ concurrencyPolicy: Allow
+ failedJobsHistoryLimit: 1
+ jobTemplate:
+ metadata:
+ ownerReferences:
+ - apiVersion: batch/v1beta1
+ kind: CronJob
+ name: f875c-each-min-aws-s3
+ spec:
+ template:
+ metadata:
+ annotations:
+ testName: scheduled-backup
+ labels:
+ backupWorker: "True"
+ cluster: scheduled-backup
+ schedule: N_N_N_N_N
+ type: cron
+ spec:
+ affinity:
+ nodeAffinity:
+ requiredDuringSchedulingIgnoredDuringExecution:
+ nodeSelectorTerms:
+ - matchExpressions:
+ - key: backupWorker
+ operator: In
+ values:
+ - "True"
+ containers:
+ - args:
+ - sh
+ - -c
+ - "\n\t\t\t\t\t\t\tcat <<-EOF | kubectl apply -f -\n\t\t\t\t\t\t\t\t\tapiVersion: pxc.percona.com/v1\n\t\t\t\t\t\t\t\t\tkind: PerconaXtraDBClusterBackup\n\t\t\t\t\t\t\t\t\tmetadata:\n\t\t\t\t\t\t\t\t\t name: \"cron-${pxcCluster:0:16}-aws-s3-$(date -u \"+%Y%m%d%H%M%S\")-${suffix}\"\n\t\t\t\t\t\t\t\t\t labels:\n\t\t\t\t\t\t\t\t\t ancestor: \"f875c-each-min-aws-s3\"\n\t\t\t\t\t\t\t\t\t cluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t type: \"cron\"\n\t\t\t\t\t\t\t\t\tspec:\n\t\t\t\t\t\t\t\t\t pxcCluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t storageName: \"aws-s3\"\n\t\t\t\t\t\t\tEOF\n\t\t\t\t\t\t\t"
+ env:
+ - name: pxcCluster
+ value: scheduled-backup
+ imagePullPolicy: Always
+ name: run-backup
+ resources:
+ requests:
+ cpu: 600m
+ memory: 1G
+ terminationMessagePath: /dev/termination-log
+ terminationMessagePolicy: File
+ dnsPolicy: ClusterFirst
+ nodeSelector:
+ backupWorker: "True"
+ priorityClassName: high-priority
+ restartPolicy: Never
+ schedulerName: default-scheduler
+ securityContext:
+ supplementalGroups:
+ - 1001
+ serviceAccount: percona-xtradb-cluster-operator
+ serviceAccountName: percona-xtradb-cluster-operator
+ terminationGracePeriodSeconds: 30
+ tolerations:
+ - effect: NoSchedule
+ key: backupWorker
+ operator: Equal
+ value: "True"
+ schedule: '* * * * *'
+ successfulJobsHistoryLimit: 1
+ suspend: false

diff:
+apiVersion: batch/v1beta1
+kind: CronJob
+metadata:
+ annotations:
+ testName: scheduled-backup
+ labels:
+ backupWorker: "True"
+ cluster: scheduled-backup
+ schedule: N_N_N_N_N
+ type: cron
+ name: f875c-each-min-aws-s3
+ ownerReferences:
+ - controller: true
+ kind: PerconaXtraDBCluster
+ name: scheduled-backup
+spec:
+ concurrencyPolicy: Allow
+ failedJobsHistoryLimit: 1
+ jobTemplate:
+ metadata:
+ ownerReferences:
+ - apiVersion: batch/v1beta1
+ kind: CronJob
+ name: f875c-each-min-aws-s3
+ spec:
+ template:
+ metadata:
+ annotations:
+ testName: scheduled-backup
+ labels:
+ backupWorker: "True"
+ cluster: scheduled-backup
+ schedule: N_N_N_N_N
+ type: cron
+ spec:
+ affinity:
+ nodeAffinity:
+ requiredDuringSchedulingIgnoredDuringExecution:
+ nodeSelectorTerms:
+ - matchExpressions:
+ - key: backupWorker
+ operator: In
+ values:
+ - "True"
+ containers:
+ - args:
+ - sh
+ - -c
+ - "\n\t\t\t\t\t\t\tcat <<-EOF | kubectl apply -f -\n\t\t\t\t\t\t\t\t\tapiVersion: pxc.percona.com/v1\n\t\t\t\t\t\t\t\t\tkind: PerconaXtraDBClusterBackup\n\t\t\t\t\t\t\t\t\tmetadata:\n\t\t\t\t\t\t\t\t\t name: \"cron-${pxcCluster:0:16}-aws-s3-$(date -u \"+%Y%m%d%H%M%S\")-${suffix}\"\n\t\t\t\t\t\t\t\t\t labels:\n\t\t\t\t\t\t\t\t\t ancestor: \"f875c-each-min-aws-s3\"\n\t\t\t\t\t\t\t\t\t cluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t type: \"cron\"\n\t\t\t\t\t\t\t\t\tspec:\n\t\t\t\t\t\t\t\t\t pxcCluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t storageName: \"aws-s3\"\n\t\t\t\t\t\t\tEOF\n\t\t\t\t\t\t\t"
+ env:
+ - name: pxcCluster
+ value: scheduled-backup
+ imagePullPolicy: Always
+ name: run-backup
+ resources:
+ requests:
+ cpu: 600m
+ memory: 1G
+ terminationMessagePath: /dev/termination-log
+ terminationMessagePolicy: File
+ dnsPolicy: ClusterFirst
+ nodeSelector:
+ backupWorker: "True"
+ priorityClassName: high-priority
+ restartPolicy: Never
+ schedulerName: default-scheduler
+ securityContext:
+ fsGroup: 1001
+ supplementalGroups:
+ - 1001
+ serviceAccount: percona-xtradb-cluster-operator
+ serviceAccountName: percona-xtradb-cluster-operator
+ terminationGracePeriodSeconds: 30
+ tolerations:
+ - effect: NoSchedule
+ key: backupWorker
+ operator: Equal
+ value: "True"
+ schedule: '* * * * *'
+ successfulJobsHistoryLimit: 1
+ suspend: false

change_type: RENAME

diff:
@@ -8,7 +8,7 @@ metadata:
cluster: scheduled-backup
schedule: N_N_N_N_N
type: cron
- name: each-min-gcp-cs
+ name: f875c-each-min-gcp-cs
ownerReferences:
- controller: true
kind: PerconaXtraDBCluster
@@ -21,7 +21,7 @@ spec:
ownerReferences:
- apiVersion: batch/v1beta1
kind: CronJob
- name: each-min-gcp-cs
+ name: f875c-each-min-gcp-cs
spec:
template:
metadata:
@@ -46,7 +46,7 @@ spec:
- args:
- sh
- -c
- - "\n\t\t\t\t\t\t\tcat <<-EOF | kubectl apply -f -\n\t\t\t\t\t\t\t\t\tapiVersion: pxc.percona.com/v1\n\t\t\t\t\t\t\t\t\tkind: PerconaXtraDBClusterBackup\n\t\t\t\t\t\t\t\t\tmetadata:\n\t\t\t\t\t\t\t\t\t name: \"cron-${pxcCluster:0:16}-gcp-cs-$(date -u \"+%Y%m%d%H%M%S\")-${suffix}\"\n\t\t\t\t\t\t\t\t\t labels:\n\t\t\t\t\t\t\t\t\t ancestor: \"each-min-gcp-cs\"\n\t\t\t\t\t\t\t\t\t cluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t type: \"cron\"\n\t\t\t\t\t\t\t\t\tspec:\n\t\t\t\t\t\t\t\t\t pxcCluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t storageName: \"gcp-cs\"\n\t\t\t\t\t\t\tEOF\n\t\t\t\t\t\t\t"
+ - "\n\t\t\t\t\t\t\tcat <<-EOF | kubectl apply -f -\n\t\t\t\t\t\t\t\t\tapiVersion: pxc.percona.com/v1\n\t\t\t\t\t\t\t\t\tkind: PerconaXtraDBClusterBackup\n\t\t\t\t\t\t\t\t\tmetadata:\n\t\t\t\t\t\t\t\t\t name: \"cron-${pxcCluster:0:16}-gcp-cs-$(date -u \"+%Y%m%d%H%M%S\")-${suffix}\"\n\t\t\t\t\t\t\t\t\t labels:\n\t\t\t\t\t\t\t\t\t ancestor: \"f875c-each-min-gcp-cs\"\n\t\t\t\t\t\t\t\t\t cluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t type: \"cron\"\n\t\t\t\t\t\t\t\t\tspec:\n\t\t\t\t\t\t\t\t\t pxcCluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t storageName: \"gcp-cs\"\n\t\t\t\t\t\t\tEOF\n\t\t\t\t\t\t\t"
env:
- name: pxcCluster
value: scheduled-backup

diff:
@@ -8,7 +8,7 @@ metadata:
cluster: scheduled-backup
schedule: N_N_N_N_N
type: cron
- name: each-min-minio
+ name: f875c-each-min-minio
ownerReferences:
- controller: true
kind: PerconaXtraDBCluster
@@ -21,7 +21,7 @@ spec:
ownerReferences:
- apiVersion: batch/v1beta1
kind: CronJob
- name: each-min-minio
+ name: f875c-each-min-minio
spec:
template:
metadata:
@@ -46,7 +46,7 @@ spec:
- args:
- sh
- -c
- - "\n\t\t\t\t\t\t\tcat <<-EOF | kubectl apply -f -\n\t\t\t\t\t\t\t\t\tapiVersion: pxc.percona.com/v1\n\t\t\t\t\t\t\t\t\tkind: PerconaXtraDBClusterBackup\n\t\t\t\t\t\t\t\t\tmetadata:\n\t\t\t\t\t\t\t\t\t name: \"cron-${pxcCluster:0:16}-minio-$(date -u \"+%Y%m%d%H%M%S\")-${suffix}\"\n\t\t\t\t\t\t\t\t\t labels:\n\t\t\t\t\t\t\t\t\t ancestor: \"each-min-minio\"\n\t\t\t\t\t\t\t\t\t cluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t type: \"cron\"\n\t\t\t\t\t\t\t\t\tspec:\n\t\t\t\t\t\t\t\t\t pxcCluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t storageName: \"minio\"\n\t\t\t\t\t\t\tEOF\n\t\t\t\t\t\t\t"
+ - "\n\t\t\t\t\t\t\tcat <<-EOF | kubectl apply -f -\n\t\t\t\t\t\t\t\t\tapiVersion: pxc.percona.com/v1\n\t\t\t\t\t\t\t\t\tkind: PerconaXtraDBClusterBackup\n\t\t\t\t\t\t\t\t\tmetadata:\n\t\t\t\t\t\t\t\t\t name: \"cron-${pxcCluster:0:16}-minio-$(date -u \"+%Y%m%d%H%M%S\")-${suffix}\"\n\t\t\t\t\t\t\t\t\t labels:\n\t\t\t\t\t\t\t\t\t ancestor: \"f875c-each-min-minio\"\n\t\t\t\t\t\t\t\t\t cluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t type: \"cron\"\n\t\t\t\t\t\t\t\t\tspec:\n\t\t\t\t\t\t\t\t\t pxcCluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t storageName: \"minio\"\n\t\t\t\t\t\t\tEOF\n\t\t\t\t\t\t\t"
env:
- name: pxcCluster
value: scheduled-backup

diff:
@@ -8,7 +8,7 @@ metadata:
cluster: scheduled-backup
schedule: N_N_N_N_N
type: cron
- name: each-min-aws-s3
+ name: f875c-each-min-pvc
ownerReferences:
- controller: true
kind: PerconaXtraDBCluster
@@ -21,7 +21,7 @@ spec:
ownerReferences:
- apiVersion: batch/v1beta1
kind: CronJob
- name: each-min-aws-s3
+ name: f875c-each-min-pvc
spec:
template:
metadata:
@@ -46,7 +46,7 @@ spec:
- args:
- sh
- -c
- - "\n\t\t\t\t\t\t\tcat <<-EOF | kubectl apply -f -\n\t\t\t\t\t\t\t\t\tapiVersion: pxc.percona.com/v1\n\t\t\t\t\t\t\t\t\tkind: PerconaXtraDBClusterBackup\n\t\t\t\t\t\t\t\t\tmetadata:\n\t\t\t\t\t\t\t\t\t name: \"cron-${pxcCluster:0:16}-aws-s3-$(date -u \"+%Y%m%d%H%M%S\")-${suffix}\"\n\t\t\t\t\t\t\t\t\t labels:\n\t\t\t\t\t\t\t\t\t ancestor: \"each-min-aws-s3\"\n\t\t\t\t\t\t\t\t\t cluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t type: \"cron\"\n\t\t\t\t\t\t\t\t\tspec:\n\t\t\t\t\t\t\t\t\t pxcCluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t storageName: \"aws-s3\"\n\t\t\t\t\t\t\tEOF\n\t\t\t\t\t\t\t"
+ - "\n\t\t\t\t\t\t\tcat <<-EOF | kubectl apply -f -\n\t\t\t\t\t\t\t\t\tapiVersion: pxc.percona.com/v1\n\t\t\t\t\t\t\t\t\tkind: PerconaXtraDBClusterBackup\n\t\t\t\t\t\t\t\t\tmetadata:\n\t\t\t\t\t\t\t\t\t name: \"cron-${pxcCluster:0:16}-pvc-$(date -u \"+%Y%m%d%H%M%S\")-${suffix}\"\n\t\t\t\t\t\t\t\t\t labels:\n\t\t\t\t\t\t\t\t\t ancestor: \"f875c-each-min-pvc\"\n\t\t\t\t\t\t\t\t\t cluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t type: \"cron\"\n\t\t\t\t\t\t\t\t\tspec:\n\t\t\t\t\t\t\t\t\t pxcCluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t storageName: \"pvc\"\n\t\t\t\t\t\t\tEOF\n\t\t\t\t\t\t\t"
env:
- name: pxcCluster
value: scheduled-backup

diff:
@@ -177,10 +177,10 @@ main() {
if [ -n "$OPERATOR_NS" ]; then
kubectl_bin config set-context "$(kubectl_bin config current-context)" --namespace="$OPERATOR_NS"
fi
- compare_kubectl cronjob/each-min-pvc
- compare_kubectl cronjob/each-min-aws-s3
- compare_kubectl cronjob/each-min-minio
- compare_kubectl cronjob/each-min-gcp-cs
+ compare_kubectl cronjob/f875c-each-min-pvc
+ compare_kubectl cronjob/f875c-each-min-aws-s3
+ compare_kubectl cronjob/f875c-each-min-minio
+ compare_kubectl cronjob/f875c-each-min-gcp-cs
kubectl_bin config set-context "$(kubectl_bin config current-context)" --namespace="$namespace"
sleep 300

diff:
@@ -7,7 +7,7 @@ metadata:
cluster: sec-context
schedule: 0_NE1_N_N_N
type: cron
- name: each-hour-pvc
+ name: adc5a-each-hour-pvc
ownerReferences:
- controller: true
kind: PerconaXtraDBCluster
@@ -20,7 +20,7 @@ spec:
ownerReferences:
- apiVersion: batch/v1beta1
kind: CronJob
- name: each-hour-pvc
+ name: adc5a-each-hour-pvc
spec:
template:
metadata:
@@ -35,7 +35,7 @@ spec:
- args:
- sh
- -c
- - "\n\t\t\t\t\t\t\tcat <<-EOF | kubectl apply -f -\n\t\t\t\t\t\t\t\t\tapiVersion: pxc.percona.com/v1\n\t\t\t\t\t\t\t\t\tkind: PerconaXtraDBClusterBackup\n\t\t\t\t\t\t\t\t\tmetadata:\n\t\t\t\t\t\t\t\t\t name: \"cron-${pxcCluster:0:16}-pvc-$(date -u \"+%Y%m%d%H%M%S\")-${suffix}\"\n\t\t\t\t\t\t\t\t\t labels:\n\t\t\t\t\t\t\t\t\t ancestor: \"each-hour-pvc\"\n\t\t\t\t\t\t\t\t\t cluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t type: \"cron\"\n\t\t\t\t\t\t\t\t\tspec:\n\t\t\t\t\t\t\t\t\t pxcCluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t storageName: \"pvc\"\n\t\t\t\t\t\t\tEOF\n\t\t\t\t\t\t\t"
+ - "\n\t\t\t\t\t\t\tcat <<-EOF | kubectl apply -f -\n\t\t\t\t\t\t\t\t\tapiVersion: pxc.percona.com/v1\n\t\t\t\t\t\t\t\t\tkind: PerconaXtraDBClusterBackup\n\t\t\t\t\t\t\t\t\tmetadata:\n\t\t\t\t\t\t\t\t\t name: \"cron-${pxcCluster:0:16}-pvc-$(date -u \"+%Y%m%d%H%M%S\")-${suffix}\"\n\t\t\t\t\t\t\t\t\t labels:\n\t\t\t\t\t\t\t\t\t ancestor: \"adc5a-each-hour-pvc\"\n\t\t\t\t\t\t\t\t\t cluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t type: \"cron\"\n\t\t\t\t\t\t\t\t\tspec:\n\t\t\t\t\t\t\t\t\t pxcCluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t storageName: \"pvc\"\n\t\t\t\t\t\t\tEOF\n\t\t\t\t\t\t\t"
env:
- name: pxcCluster
value: sec-context

diff:
@@ -50,7 +50,7 @@ compare_kubectl job.batch/xb-$backup
if [ -n "$OPERATOR_NS" ]; then
kubectl_bin config set-context "$(kubectl_bin config current-context)" --namespace="$OPERATOR_NS"
fi
-compare_kubectl cronjob/each-hour-pvc
+compare_kubectl cronjob/adc5a-each-hour-pvc
kubectl_bin config set-context "$(kubectl_bin config current-context)" --namespace="$namespace"
desc 'run pvc restore'

diff:
@@ -3,6 +3,8 @@ package pxc
import (
"container/heap"
"context"
+ "crypto/sha1"
+ "encoding/hex"
"fmt"
"reflect"
@@ -31,6 +33,7 @@ func (r *ReconcilePerconaXtraDBCluster) reconcileBackups(cr *api.PerconaXtraDBCl
if cr.Spec.Backup != nil {
bcpObj := backup.New(cr)
+ backupNamePrefix := backupJobClusterPrefix(cr.Name)
if cr.Status.Status == api.AppStateReady && cr.Spec.Backup.PITR.Enabled && !cr.Spec.Pause {
binlogCollector, err := deployment.GetBinlogCollectorDeployment(cr)
@@ -63,6 +66,7 @@ func (r *ReconcilePerconaXtraDBCluster) reconcileBackups(cr *api.PerconaXtraDBCl
}
for _, bcp := range cr.Spec.Backup.Schedule {
+ bcp.Name = backupNamePrefix + "-" + bcp.Name
backups[bcp.Name] = bcp
strg, ok := cr.Spec.Backup.Storages[bcp.StorageName]
if !ok {
@@ -138,6 +142,12 @@ func (r *ReconcilePerconaXtraDBCluster) reconcileBackups(cr *api.PerconaXtraDBCl
return nil
}
+func backupJobClusterPrefix(clusterName string) string {
+ h := sha1.New()
+ h.Write([]byte(clusterName))
+ return hex.EncodeToString(h.Sum(nil))[:5]
+}
+
// oldScheduledBackups returns list of the most old pxc-bakups that execeed `keep` limit
func (r *ReconcilePerconaXtraDBCluster) oldScheduledBackups(cr *api.PerconaXtraDBCluster, ancestor string, keep int) ([]api.PerconaXtraDBClusterBackup, error) {
bcpList := api.PerconaXtraDBClusterBackupList{}

original_message: K8SPXC-542: add cluster hash prefix to backup job name (#720)


message: improve pitr

diff:
@@ -43,7 +43,7 @@ type Config struct {
}
const (
- lastSetFileName string = "last-binlog-set" // name for object where the last binlog set will stored
+ lastSetFilePrefix string = "last-binlog-set-" // filename prefix for object where the last binlog set will stored
gtidPostfix string = "-gtid-set" // filename postfix for files with GTID set
)
@@ -59,19 +59,8 @@ func New(c Config) (*Collector, error) {
return nil, errors.Wrap(err, "new storage manager")
}
- // get last binlog set stored on S3
- lastSetObject, err := s3.GetObject(lastSetFileName)
- if err != nil {
- return nil, errors.Wrap(err, "get last set content")
- }
- lastSet, err := ioutil.ReadAll(lastSetObject)
- if err != nil && minio.ToErrorResponse(errors.Cause(err)).Code != "NoSuchKey" {
- return nil, errors.Wrap(err, "read last gtid set")
- }
-
return &Collector{
storage: s3,
- lastSet: string(lastSet),
pxcUser: c.PXCUser,
pxcServiceName: c.PXCServiceName,
}, nil
@@ -84,6 +73,10 @@ func (c *Collector) Run() error {
}
defer c.close()
+ // remove last set because we always
+ // read it from aws file
+ c.lastSet = ""
+
err = c.CollectBinLogs()
if err != nil {
return errors.Wrap(err, "collect binlog files")
@@ -92,6 +85,19 @@ func (c *Collector) Run() error {
return nil
}
+func (c *Collector) lastGTIDSet(sourceID string) (string, error) {
+ // get last binlog set stored on S3
+ lastSetObject, err := c.storage.GetObject(lastSetFilePrefix + sourceID)
+ if err != nil {
+ return "", errors.Wrap(err, "get last set content")
+ }
+ lastSet, err := ioutil.ReadAll(lastSetObject)
+ if err != nil && minio.ToErrorResponse(errors.Cause(err)).Code != "NoSuchKey" {
+ return "", errors.Wrap(err, "read last gtid set")
+ }
+ return string(lastSet), nil
+}
+
func (c *Collector) newDB() error {
file, err := os.Open("/etc/mysql/mysql-users-secret/xtrabackup")
if err != nil {
@@ -122,48 +128,119 @@ func (c *Collector) close() error {
return c.db.Close()
}
+func (c *Collector) CurrentSourceID(logs []pxc.Binlog) (string, error) {
+ var (
+ gtidSet string
+ i int
+ err error
+ )
+ for gtidSet == "" && i < len(logs) {
+ gtidSet, err = c.db.GetGTIDSet(logs[i].Name)
+ if err != nil {
+ return gtidSet, err
+ }
+ i++
+ }
+ return strings.Split(gtidSet, ":")[0], nil
+}
+
+func (c *Collector) removeEmptyBinlogs(logs []pxc.Binlog) ([]pxc.Binlog, error) {
+ result := make([]pxc.Binlog, 0)
+ for _, v := range logs {
+ set, err := c.db.GetGTIDSet(v.Name)
+ if err != nil {
+ return nil, errors.Wrap(err, "get GTID set")
+ }
+ // we don't upload binlog without gtid
+ // because it is empty and doesn't have any information
+ if set != "" {
+ v.GTIDSet = set
+ result = append(result, v)
+ }
+ }
+ return result, nil
+}
+
+func (c *Collector) filterBinLogs(logs []pxc.Binlog, lastBinlogName string) ([]pxc.Binlog, error) {
+ if lastBinlogName == "" {
+ return c.removeEmptyBinlogs(logs)
+ }
+
+ logsLen := len(logs)
+
+ startIndex := 0
+ for logs[startIndex].Name != lastBinlogName && startIndex < logsLen {
+ startIndex++
+ }
+
+ if startIndex == logsLen {
+ return nil, nil
+ }
+
+ set, err := c.db.GetGTIDSet(logs[startIndex].Name)
+ if err != nil {
+ return nil, errors.Wrap(err, "get gtid set of last uploaded binlog")
+ }
+ // we don't need to reupload last file
+ // if gtid set is not changed
+ if set == c.lastSet {
+ startIndex++
+ }
+
+ return c.removeEmptyBinlogs(logs[startIndex:])
+}
+
func (c *Collector) CollectBinLogs() error {
list, err := c.db.GetBinLogList()
if err != nil {
return errors.Wrap(err, "get binlog list")
}
+ sourceID, err := c.CurrentSourceID(list)
+ if err != nil {
+ return errors.Wrap(err, "get current source id")
+ }
+
+ if sourceID == "" {
+ log.Println("No binlogs to upload")
+ return nil
+ }
+
+ c.lastSet, err = c.lastGTIDSet(sourceID)
+ if err != nil {
+ return errors.Wrap(err, "get last uploaded gtid set")
+ }
+
+ lastUploadedBinlogName := ""
+
+ if c.lastSet != "" {
// get last uploaded binlog file name
- lastUploadedBinlogName, err := c.db.GetBinLogName(c.lastSet)
+ lastUploadedBinlogName, err = c.db.GetBinLogName(c.lastSet)
if err != nil {
return errors.Wrap(err, "get last uploaded binlog name by gtid set")
}
- upload := false
- // if there are no uploaded files we going to upload every binlog file
- if len(lastUploadedBinlogName) == 0 {
- upload = true
+ if lastUploadedBinlogName == "" {
+ log.Println("Gap detected in the binary logs. Binary logs will be uploaded anyway, but full backup needed for consistent recovery.")
+ }
}
- for _, binlog := range list {
- binlogSet := ""
- // this check is for uploading starting from needed file
- if binlog.Name == lastUploadedBinlogName {
- binlogSet, err = c.db.GetGTIDSet(binlog.Name)
+ list, err = c.filterBinLogs(list, lastUploadedBinlogName)
if err != nil {
- return errors.Wrap(err, "get binlog gtid set")
- }
- if c.lastSet != binlogSet {
- upload = true
+ return errors.Wrap(err, "filter empty binlogs")
}
+
+ if len(list) == 0 {
+ log.Println("No binlogs to upload")
+ return nil
}
- if upload {
+
+ for _, binlog := range list {
err = c.manageBinlog(binlog)
if err != nil {
return errors.Wrap(err, "manage binlog")
}
}
- // need this for start uploading files that goes after current
- if c.lastSet == binlogSet {
- upload = true
- }
- }
-
return nil
}
@@ -179,27 +256,18 @@ func mergeErrors(a, b error) error {
}
func (c *Collector) manageBinlog(binlog pxc.Binlog) (err error) {
- set, err := c.db.GetGTIDSet(binlog.Name)
- if err != nil {
- return errors.Wrap(err, "get GTID set")
- }
- // we don't upload binlog without gtid
- // because it is empty and doesn't have any information
- if len(set) == 0 {
- return nil
- }
binlogTmstmp, err := c.db.GetBinLogFirstTimestamp(binlog.Name)
if err != nil {
return errors.Wrapf(err, "get first timestamp for %s", binlog.Name)
}
- binlogName := fmt.Sprintf("binlog_%s_%x", binlogTmstmp, md5.Sum([]byte(set)))
+ binlogName := fmt.Sprintf("binlog_%s_%x", binlogTmstmp, md5.Sum([]byte(binlog.GTIDSet)))
var setBuffer bytes.Buffer
// no error handling because WriteString() always return nil error
// nolint:errcheck
- setBuffer.WriteString(set)
+ setBuffer.WriteString(binlog.GTIDSet)
tmpDir := os.TempDir() + "/"
@@ -267,13 +335,13 @@ func (c *Collector) manageBinlog(binlog pxc.Binlog) (err error) {
}
// no error handling because WriteString() always return nil error
// nolint:errcheck
- setBuffer.WriteString(set)
+ setBuffer.WriteString(binlog.GTIDSet)
- err = c.storage.PutObject(lastSetFileName, &setBuffer, int64(setBuffer.Len()))
+ err = c.storage.PutObject(lastSetFilePrefix+strings.Split(binlog.GTIDSet, ":")[0], &setBuffer, int64(setBuffer.Len()))
if err != nil {
return errors.Wrap(err, "put last-set object")
}
- c.lastSet = set
+ c.lastSet = binlog.GTIDSet
return nil
}

diff:
@@ -81,6 +81,7 @@ type Binlog struct {
Name string
Size int64
Encrypted string
+ GTIDSet string
}
// GetBinLogList return binary log files list
@@ -144,7 +145,7 @@ func (p *PXC) GetBinLogName(gtidSet string) (string, error) {
return "", errors.Wrap(err, "create function")
}
}
- var binlog string
+ var binlog sql.NullString
row := p.db.QueryRow("SELECT get_binlog_by_gtid_set(?)", gtidSet)
err = row.Scan(&binlog)
@@ -152,7 +153,7 @@ func (p *PXC) GetBinLogName(gtidSet string) (string, error) {
return "", errors.Wrap(err, "scan binlog")
}
- return strings.TrimPrefix(binlog, "./"), nil
+ return strings.TrimPrefix(binlog.String, "./"), nil
}
// GetBinLogFirstTimestamp return binary log file first timestamp

diff:
@@ -315,6 +315,7 @@ func (r *Recoverer) setBinlogs() error {
}
reverse(list)
binlogs := []string{}
+ sourceID := strings.Split(r.startGTID, ":")[0]
for _, binlog := range list {
if strings.Contains(binlog, "-gtid-set") {
continue
@@ -329,6 +330,9 @@ func (r *Recoverer) setBinlogs() error {
return errors.Wrapf(err, "read %s gtid-set object", binlog)
}
binlogGTIDSet := string(content)
+ if sourceID != strings.Split(binlogGTIDSet, ":")[0] {
+ continue
+ }
binlogs = append(binlogs, binlog)
subResult, err := r.db.SubtractGTIDSet(r.startGTID, binlogGTIDSet)
if err != nil {
@@ -339,7 +343,7 @@ func (r *Recoverer) setBinlogs() error {
}
}
if len(binlogs) == 0 {
- return errors.Errorf("no objects for prefix %s", "binlog_")
+ return errors.Errorf("no objects for prefix binlog_ or with source_id=%s", sourceID)
}
reverse(binlogs)
r.binlogs = binlogs

original_message: K8SPXC-645: improve pitr (#790)


message: Fix sed command

diff:
@@ -36,7 +36,7 @@ if oc get projects; then
esac
fi
-KUBE_VERSION=$(kubectl version -o json | jq -r '.serverVersion.major + "." + .serverVersion.minor' | sed -r 's/[^0-9.]+//g')
+KUBE_VERSION=$(kubectl version -o json | jq -r '.serverVersion.major + "." + .serverVersion.minor' | $sed -r 's/[^0-9.]+//g')
HELM_VERSION=$(helm version -c | $sed -re 's/.*SemVer:"([^"]+)".*/\1/; s/.*\bVersion:"([^"]+)".*/\1/')
if [ "${HELM_VERSION:0:2}" == "v2" ]; then

original_message: Fix sed command


diff:
@@ -270,7 +270,7 @@ func (r *ReconcilePerconaXtraDBClusterBackup) tryRunS3BackupFinalizerJob(cr *api
return nil
}
- if cr.Status.S3 == nil {
+ if cr.Status.S3 == nil || cr.Status.Destination == "" || !strings.HasPrefix(cr.Status.Destination, "s3://") {
removeS3Finalizer(cr)
return nil
}

original_message: add extra checks for s3 backup finalizer (#858)


message: improve recovery gtid check

diff:
@@ -90,6 +90,30 @@ func New(c Config) (*Recoverer, error) {
return nil, errors.Wrap(err, "get start GTID")
}
+ if c.RecoverType == string(Transaction) {
+ gtidSplitted := strings.Split(startGTID, ":")
+ if len(gtidSplitted) != 2 {
+ return nil, errors.New("Invalid start gtidset provided")
+ }
+ lastSetIdx := 1
+ setSplitted := strings.Split(gtidSplitted[1], "-")
+ if len(setSplitted) == 1 {
+ lastSetIdx = 0
+ }
+ lastSet := setSplitted[lastSetIdx]
+ lastSetInt, err := strconv.ParseInt(lastSet, 10, 64)
+ if err != nil {
+ return nil, errors.Wrap(err, "failed to cast last set value to in")
+ }
+ transactionNum, err := strconv.ParseInt(strings.Split(c.GTID, ":")[1], 10, 64)
+ if err != nil {
+ return nil, errors.Wrap(err, "failed to parse transaction num to restore")
+ }
+ if transactionNum < lastSetInt {
+ return nil, errors.New("Can't restore to transaction before backup")
+ }
+ }
+
return &Recoverer{
storage: s3,
recoverTime: c.RecoverTime,

original_message: improve recovery gtid check


message: change collector delay type

diff:
@@ -39,7 +39,7 @@ type Config struct {
S3BucketURL string `env:"S3_BUCKET_URL,required"`
S3Region string `env:"DEFAULT_REGION,required"`
BufferSize int64 `env:"BUFFER_SIZE"`
- CollectSpanSec int64 `env:"COLLECT_SPAN_SEC" envDefault:"60"`
+ CollectSpanSec float64 `env:"COLLECT_SPAN_SEC" envDefault:"60"`
}
const (

diff:
@@ -79,7 +79,7 @@ type PITRSpec struct {
Enabled bool `json:"enabled"`
StorageName string `json:"storageName"`
Resources *PodResources `json:"resources,omitempty"`
- TimeBetweenUploads int64 `json:"timeBetweenUploads,omitempty"`
+ TimeBetweenUploads float64 `json:"timeBetweenUploads,omitempty"`
}
type PXCScheduledBackupSchedule struct {

diff:
package deployment
import (
+ "fmt"
"strconv"
appsv1 "k8s.io/api/apps/v1"
@@ -17,7 +18,7 @@ func GetBinlogCollectorDeployment(cr *api.PerconaXtraDBCluster) (appsv1.Deployme
storage := cr.Spec.Backup.Storages[cr.Spec.Backup.PITR.StorageName]
binlogCollectorName := GetBinlogCollectorDeploymentName(cr)
pxcUser := "xtrabackup"
- sleepTime := strconv.FormatInt(cr.Spec.Backup.PITR.TimeBetweenUploads, 10)
+ sleepTime := fmt.Sprintf("%.2f", cr.Spec.Backup.PITR.TimeBetweenUploads)
bufferSize, err := getBufferSize(cr.Spec)
if err != nil {

original_message: change collector delay type


message: improve pitr test

diff:
+apiVersion: pxc.percona.com/v1
+kind: PerconaXtraDBClusterBackup
+metadata:
+ name: on-pitr-minio1
+spec:
+ pxcCluster: pitr
+ storageName: minio

diff:
@@ -61,7 +61,7 @@ spec:
pitr:
enabled: true
storageName: minio-binlogs
- timeBetweenUploads: 60
+ timeBetweenUploads: 55
storages:
pvc:
type: filesystem

diff:
+apiVersion: pxc.percona.com/v1
+kind: PerconaXtraDBClusterRestore
+metadata:
+ name: on-pitr-minio1
+spec:
+ pxcCluster: pitr
+ backupSource:
+ destination: <destination>
+ s3:
+ bucket: operator-testing
+ credentialsSecret: minio-secret
+ endpointUrl: http://minio-service:9000
+ region: us-east-1
+ pitr:
+ type: latest
+ backupSource:
+ s3:
+ bucket: operator-testing/binlogs
+ credentialsSecret: minio-secret
+ endpointUrl: http://minio-service:9000
+ region: us-east-1
+

diff:
@@ -70,7 +70,7 @@ write_test_data() {
}
-write_more_data() {
+write_data_for_pitr() {
local cluster=$1
local proxy=$(get_proxy "$cluster")
@@ -79,6 +79,15 @@ write_more_data() {
"-h $proxy -uroot -proot_password"
}
+write_more_data() {
+ local cluster=$1
+ local proxy=$(get_proxy "$cluster")
+
+ run_mysql \
+ 'INSERT test.test (id) VALUES (100506); INSERT test.test (id) VALUES (100507); INSERT test.test (id) VALUES (100508); INSERT test.test (id) VALUES (100509); INSERT test.test (id) VALUES (100510);' \
+ "-h $proxy -uroot -proot_password"
+}
+
main() {
create_infra $namespace
start_minio
@@ -95,7 +104,7 @@ main() {
gtid=$(run_mysql "SHOW BINLOG EVENTS IN 'binlog.000005';" "-h $proxy -uroot -proot_password" | grep Gtid | tail -c 43)
sleep 60
- write_more_data "$cluster"
+ write_data_for_pitr "$cluster"
sleep 80 # need to wait while collector catch new data
kubectl patch pxc pitr --type=merge -p '{"spec":{"backup":{"pitr":{"enabled":false}}}}'
@@ -109,6 +118,15 @@ main() {
run_recovery_check_pitr "$cluster" "restore-on-pitr-minio" "on-pitr-minio" "select-4" "" "$dest" ""
echo "done latest type"
+ desc 'check if we restore data from binlogs'
+ kubectl patch pxc pitr --type=merge -p '{"spec":{"backup":{"pitr":{"enabled":true}}}}'
+ sleep 20
+ run_backup "$cluster" "on-pitr-minio1"
+ write_more_data "$cluster"
+ dest=$(sed 's,/,\\/,g' <<<$(kubectl get pxc-backup on-pitr-minio1 -o jsonpath='{.status.destination}'))
+ sleep 80 # need to wait while collector catch new data
+ run_recovery_check_pitr "$cluster" "restore-on-pitr-minio1" "on-pitr-minio1" "select-5" "" "$dest" ""
+
destroy $namespace
}

original_message: improve pitr test


message: impove extend function

diff:
@@ -462,22 +462,29 @@ func (r *Recoverer) setBinlogs() error {
}
func getExtendGTIDSet(gtidSet, gtid string) (string, error) {
+ if gtidSet == gtid {
+ return gtid, nil
+ }
+
s := strings.Split(gtidSet, ":")
if len(s) < 2 {
return "", errors.Errorf("incorrect source in gtid set %s", gtidSet)
}
+ eidx := 1
e := strings.Split(s[1], "-")
- if len(e) < 2 {
- return "", errors.Errorf("incorrect id range in %s", gtidSet)
+ if len(e) == 1 {
+ eidx = 0
}
+
gs := strings.Split(gtid, ":")
if len(gs) < 2 {
return "", errors.Errorf("incorrect source in gtid set %s", gtid)
}
+
es := strings.Split(gs[1], "-")
- return gs[0] + ":" + es[0] + "-" + e[1], nil
+ return gs[0] + ":" + es[0] + "-" + e[eidx], nil
}
func reverse(list []string) {

original_message: impove extend function


message: improve object updates

diff:
@@ -439,7 +439,6 @@ func (r *ReconcilePerconaXtraDBCluster) Reconcile(request reconcile.Request) (re
proxysqlSet := statefulset.NewProxy(o)
pxc.MergeTemplateAnnotations(proxysqlSet.StatefulSet(), proxysqlAnnotations)
- proxysqlService := pxc.NewServiceProxySQL(o)
if o.Spec.ProxySQL != nil && o.Spec.ProxySQL.Enabled {
err = r.updatePod(proxysqlSet, o.Spec.ProxySQL, o, nil)
@@ -448,7 +447,7 @@ func (r *ReconcilePerconaXtraDBCluster) Reconcile(request reconcile.Request) (re
}
currentService := &corev1.Service{}
- err := r.client.Get(context.TODO(), types.NamespacedName{Name: proxysqlService.Name, Namespace: proxysqlService.Namespace}, currentService)
+ err := r.client.Get(context.TODO(), types.NamespacedName{Name: o.ProxySQLServiceNamespacedName().Name, Namespace: o.ProxySQLServiceNamespacedName().Namespace}, currentService)
if err != nil {
return reconcile.Result{}, errors.Wrap(err, "failed to get current proxysql service sate")
}
@@ -490,7 +489,7 @@ func (r *ReconcilePerconaXtraDBCluster) Reconcile(request reconcile.Request) (re
)
}
- err = r.client.Update(context.TODO(), currentService)
+ err = r.createOrUpdate(currentService)
if err != nil {
return reconcile.Result{}, errors.Wrap(err, "ProxySQL service upgrade error")
}
@@ -509,7 +508,7 @@ func (r *ReconcilePerconaXtraDBCluster) Reconcile(request reconcile.Request) (re
return reconcile.Result{}, err
}
proxysqlUnreadyService := pxc.NewServiceProxySQLUnready(o)
- err = r.deleteServices(proxysqlService, proxysqlUnreadyService)
+ err = r.deleteServices(pxc.NewServiceProxySQL(o), proxysqlUnreadyService)
if err != nil {
return reconcile.Result{}, err
}
@@ -878,13 +877,8 @@ func (r *ReconcilePerconaXtraDBCluster) reconcileConfigMap(cr *api.PerconaXtraDB
if err != nil {
return errors.Wrap(err, "set controller ref LogCollector")
}
- err = r.client.Create(context.TODO(), configMap)
- if err != nil && k8serrors.IsAlreadyExists(err) {
- err = r.client.Update(context.TODO(), configMap)
+ err = createOrUpdateConfigmap(r.client, configMap)
if err != nil {
- return errors.Wrap(err, "update ConfigMap LogCollector")
- }
- } else if err != nil {
return errors.Wrap(err, "create ConfigMap LogCollector")
}
}
@@ -897,7 +891,7 @@ func (r *ReconcilePerconaXtraDBCluster) reconcilePDB(spec *api.PodDisruptionBudg
return nil
}
- pdb := pxc.PodDisruptionBudget(spec, sfs, namespace)
+ pdb := pxc.PodDisruptionBudget(spec, sfs.Labels(), namespace)
err := setControllerReference(owner, pdb, r.scheme)
if err != nil {
return errors.Wrap(err, "set owner reference")
@@ -947,13 +941,14 @@ func (r *ReconcilePerconaXtraDBCluster) deleteStatefulSetPods(namespace string,
return errors.Wrap(err, "get StatefulSet")
}
+ if cSet.Spec.Replicas == nil || *cSet.Spec.Replicas != 1 {
dscaleTo := int32(1)
cSet.Spec.Replicas = &dscaleTo
err = r.client.Update(context.TODO(), cSet)
if err != nil {
return errors.Wrap(err, "downscale StatefulSet")
}
-
+ }
return errors.New("waiting for pods to be deleted")
}

diff:
@@ -7,9 +7,7 @@ import (
api "github.com/percona/percona-xtradb-cluster-operator/pkg/apis/pxc/v1"
)
-func PodDisruptionBudget(spec *api.PodDisruptionBudgetSpec, app api.StatefulApp, namespace string) *policyv1beta1.PodDisruptionBudget {
- labels := app.Labels()
-
+func PodDisruptionBudget(spec *api.PodDisruptionBudgetSpec, labels map[string]string, namespace string) *policyv1beta1.PodDisruptionBudget {
return &policyv1beta1.PodDisruptionBudget{
TypeMeta: metav1.TypeMeta{
APIVersion: "policy/v1beta1",

original_message: improve object updates


message: fix cronjob updates

diff:
-apiVersion: batch/v1beta1
-kind: CronJob
-metadata:
- annotations:
- testName: scheduled-backup
- labels:
- backupWorker: "True"
- cluster: scheduled-backup
- schedule: N_N_N_N_N
- type: cron
- name: f875c-each-min-aws-s3
- ownerReferences:
- - controller: true
- kind: PerconaXtraDBCluster
- name: scheduled-backup
-spec:
- concurrencyPolicy: Allow
- failedJobsHistoryLimit: 1
- jobTemplate:
- metadata:
- ownerReferences:
- - apiVersion: batch/v1beta1
- kind: CronJob
- name: f875c-each-min-aws-s3
- spec:
- template:
- metadata:
- annotations:
- testName: scheduled-backup
- labels:
- backupWorker: "True"
- cluster: scheduled-backup
- schedule: N_N_N_N_N
- type: cron
- spec:
- affinity:
- nodeAffinity:
- requiredDuringSchedulingIgnoredDuringExecution:
- nodeSelectorTerms:
- - matchExpressions:
- - key: backupWorker
- operator: In
- values:
- - "True"
- containers:
- - args:
- - sh
- - -c
- - "\n\t\t\t\t\t\t\tcat <<-EOF | kubectl apply -f -\n\t\t\t\t\t\t\t\t\tapiVersion: pxc.percona.com/v1\n\t\t\t\t\t\t\t\t\tkind: PerconaXtraDBClusterBackup\n\t\t\t\t\t\t\t\t\tmetadata:\n\t\t\t\t\t\t\t\t\t finalizers: [delete-s3-backup ]\n\t\t\t\t\t\t\t\t\t name: \"cron-${pxcCluster:0:16}-aws-s3-$(date -u \"+%Y%m%d%H%M%S\")-${suffix}\"\n\t\t\t\t\t\t\t\t\t labels:\n\t\t\t\t\t\t\t\t\t ancestor: \"f875c-each-min-aws-s3\"\n\t\t\t\t\t\t\t\t\t cluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t type: \"cron\"\n\t\t\t\t\t\t\t\t\tspec:\n\t\t\t\t\t\t\t\t\t pxcCluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t storageName: \"aws-s3\"\n\t\t\t\t\t\t\tEOF\n\t\t\t\t\t\t\t"
- env:
- - name: pxcCluster
- value: scheduled-backup
- imagePullPolicy: Always
- name: run-backup
- resources:
- requests:
- cpu: 600m
- memory: 1G
- terminationMessagePath: /dev/termination-log
- terminationMessagePolicy: File
- dnsPolicy: ClusterFirst
- nodeSelector:
- backupWorker: "True"
- priorityClassName: high-priority
- restartPolicy: Never
- schedulerName: default-scheduler
- securityContext:
- supplementalGroups:
- - 1001
- serviceAccount: percona-xtradb-cluster-operator
- serviceAccountName: percona-xtradb-cluster-operator
- terminationGracePeriodSeconds: 30
- tolerations:
- - effect: NoSchedule
- key: backupWorker
- operator: Equal
- value: "True"
- schedule: '* * * * *'
- successfulJobsHistoryLimit: 1
- suspend: false

diff:
-apiVersion: batch/v1beta1
-kind: CronJob
-metadata:
- annotations:
- testName: scheduled-backup
- labels:
- backupWorker: "True"
- cluster: scheduled-backup
- schedule: N_N_N_N_N
- type: cron
- name: f875c-each-min-aws-s3
- ownerReferences:
- - controller: true
- kind: PerconaXtraDBCluster
- name: scheduled-backup
-spec:
- concurrencyPolicy: Allow
- failedJobsHistoryLimit: 1
- jobTemplate:
- metadata:
- ownerReferences:
- - apiVersion: batch/v1beta1
- kind: CronJob
- name: f875c-each-min-aws-s3
- spec:
- template:
- metadata:
- annotations:
- testName: scheduled-backup
- labels:
- backupWorker: "True"
- cluster: scheduled-backup
- schedule: N_N_N_N_N
- type: cron
- spec:
- affinity:
- nodeAffinity:
- requiredDuringSchedulingIgnoredDuringExecution:
- nodeSelectorTerms:
- - matchExpressions:
- - key: backupWorker
- operator: In
- values:
- - "True"
- containers:
- - args:
- - sh
- - -c
- - "\n\t\t\t\t\t\t\tcat <<-EOF | kubectl apply -f -\n\t\t\t\t\t\t\t\t\tapiVersion: pxc.percona.com/v1\n\t\t\t\t\t\t\t\t\tkind: PerconaXtraDBClusterBackup\n\t\t\t\t\t\t\t\t\tmetadata:\n\t\t\t\t\t\t\t\t\t finalizers: [delete-s3-backup ]\n\t\t\t\t\t\t\t\t\t name: \"cron-${pxcCluster:0:16}-aws-s3-$(date -u \"+%Y%m%d%H%M%S\")-${suffix}\"\n\t\t\t\t\t\t\t\t\t labels:\n\t\t\t\t\t\t\t\t\t ancestor: \"f875c-each-min-aws-s3\"\n\t\t\t\t\t\t\t\t\t cluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t type: \"cron\"\n\t\t\t\t\t\t\t\t\tspec:\n\t\t\t\t\t\t\t\t\t pxcCluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t storageName: \"aws-s3\"\n\t\t\t\t\t\t\tEOF\n\t\t\t\t\t\t\t"
- env:
- - name: pxcCluster
- value: scheduled-backup
- imagePullPolicy: Always
- name: run-backup
- resources:
- requests:
- cpu: 600m
- memory: 1G
- terminationMessagePath: /dev/termination-log
- terminationMessagePolicy: File
- dnsPolicy: ClusterFirst
- nodeSelector:
- backupWorker: "True"
- priorityClassName: high-priority
- restartPolicy: Never
- schedulerName: default-scheduler
- securityContext:
- fsGroup: 1001
- supplementalGroups:
- - 1001
- serviceAccount: percona-xtradb-cluster-operator
- serviceAccountName: percona-xtradb-cluster-operator
- terminationGracePeriodSeconds: 30
- tolerations:
- - effect: NoSchedule
- key: backupWorker
- operator: Equal
- value: "True"
- schedule: '* * * * *'
- successfulJobsHistoryLimit: 1
- suspend: false

diff:
-apiVersion: batch/v1beta1
-kind: CronJob
-metadata:
- annotations:
- testName: scheduled-backup
- labels:
- backupWorker: "True"
- cluster: scheduled-backup
- schedule: N_N_N_N_N
- type: cron
- name: f875c-each-min-gcp-cs
- ownerReferences:
- - controller: true
- kind: PerconaXtraDBCluster
- name: scheduled-backup
-spec:
- concurrencyPolicy: Allow
- failedJobsHistoryLimit: 1
- jobTemplate:
- metadata:
- ownerReferences:
- - apiVersion: batch/v1beta1
- kind: CronJob
- name: f875c-each-min-gcp-cs
- spec:
- template:
- metadata:
- annotations:
- testName: scheduled-backup
- labels:
- backupWorker: "True"
- cluster: scheduled-backup
- schedule: N_N_N_N_N
- type: cron
- spec:
- affinity:
- nodeAffinity:
- requiredDuringSchedulingIgnoredDuringExecution:
- nodeSelectorTerms:
- - matchExpressions:
- - key: backupWorker
- operator: In
- values:
- - "True"
- containers:
- - args:
- - sh
- - -c
- - "\n\t\t\t\t\t\t\tcat <<-EOF | kubectl apply -f -\n\t\t\t\t\t\t\t\t\tapiVersion: pxc.percona.com/v1\n\t\t\t\t\t\t\t\t\tkind: PerconaXtraDBClusterBackup\n\t\t\t\t\t\t\t\t\tmetadata:\n\t\t\t\t\t\t\t\t\t finalizers: [delete-s3-backup ]\n\t\t\t\t\t\t\t\t\t name: \"cron-${pxcCluster:0:16}-gcp-cs-$(date -u \"+%Y%m%d%H%M%S\")-${suffix}\"\n\t\t\t\t\t\t\t\t\t labels:\n\t\t\t\t\t\t\t\t\t ancestor: \"f875c-each-min-gcp-cs\"\n\t\t\t\t\t\t\t\t\t cluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t type: \"cron\"\n\t\t\t\t\t\t\t\t\tspec:\n\t\t\t\t\t\t\t\t\t pxcCluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t storageName: \"gcp-cs\"\n\t\t\t\t\t\t\tEOF\n\t\t\t\t\t\t\t"
- env:
- - name: pxcCluster
- value: scheduled-backup
- imagePullPolicy: Always
- name: run-backup
- resources:
- requests:
- cpu: 600m
- memory: 1G
- terminationMessagePath: /dev/termination-log
- terminationMessagePolicy: File
- dnsPolicy: ClusterFirst
- nodeSelector:
- backupWorker: "True"
- priorityClassName: high-priority
- restartPolicy: Never
- schedulerName: default-scheduler
- securityContext:
- supplementalGroups:
- - 1001
- serviceAccount: percona-xtradb-cluster-operator
- serviceAccountName: percona-xtradb-cluster-operator
- terminationGracePeriodSeconds: 30
- tolerations:
- - effect: NoSchedule
- key: backupWorker
- operator: Equal
- value: "True"
- schedule: '* * * * *'
- successfulJobsHistoryLimit: 1
- suspend: false

diff:
-apiVersion: batch/v1beta1
-kind: CronJob
-metadata:
- annotations:
- testName: scheduled-backup
- labels:
- backupWorker: "True"
- cluster: scheduled-backup
- schedule: N_N_N_N_N
- type: cron
- name: f875c-each-min-gcp-cs
- ownerReferences:
- - controller: true
- kind: PerconaXtraDBCluster
- name: scheduled-backup
-spec:
- concurrencyPolicy: Allow
- failedJobsHistoryLimit: 1
- jobTemplate:
- metadata:
- ownerReferences:
- - apiVersion: batch/v1beta1
- kind: CronJob
- name: f875c-each-min-gcp-cs
- spec:
- template:
- metadata:
- annotations:
- testName: scheduled-backup
- labels:
- backupWorker: "True"
- cluster: scheduled-backup
- schedule: N_N_N_N_N
- type: cron
- spec:
- affinity:
- nodeAffinity:
- requiredDuringSchedulingIgnoredDuringExecution:
- nodeSelectorTerms:
- - matchExpressions:
- - key: backupWorker
- operator: In
- values:
- - "True"
- containers:
- - args:
- - sh
- - -c
- - "\n\t\t\t\t\t\t\tcat <<-EOF | kubectl apply -f -\n\t\t\t\t\t\t\t\t\tapiVersion: pxc.percona.com/v1\n\t\t\t\t\t\t\t\t\tkind: PerconaXtraDBClusterBackup\n\t\t\t\t\t\t\t\t\tmetadata:\n\t\t\t\t\t\t\t\t\t finalizers: [delete-s3-backup ]\n\t\t\t\t\t\t\t\t\t name: \"cron-${pxcCluster:0:16}-gcp-cs-$(date -u \"+%Y%m%d%H%M%S\")-${suffix}\"\n\t\t\t\t\t\t\t\t\t labels:\n\t\t\t\t\t\t\t\t\t ancestor: \"f875c-each-min-gcp-cs\"\n\t\t\t\t\t\t\t\t\t cluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t type: \"cron\"\n\t\t\t\t\t\t\t\t\tspec:\n\t\t\t\t\t\t\t\t\t pxcCluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t storageName: \"gcp-cs\"\n\t\t\t\t\t\t\tEOF\n\t\t\t\t\t\t\t"
- env:
- - name: pxcCluster
- value: scheduled-backup
- imagePullPolicy: Always
- name: run-backup
- resources:
- requests:
- cpu: 600m
- memory: 1G
- terminationMessagePath: /dev/termination-log
- terminationMessagePolicy: File
- dnsPolicy: ClusterFirst
- nodeSelector:
- backupWorker: "True"
- priorityClassName: high-priority
- restartPolicy: Never
- schedulerName: default-scheduler
- securityContext:
- fsGroup: 1001
- supplementalGroups:
- - 1001
- serviceAccount: percona-xtradb-cluster-operator
- serviceAccountName: percona-xtradb-cluster-operator
- terminationGracePeriodSeconds: 30
- tolerations:
- - effect: NoSchedule
- key: backupWorker
- operator: Equal
- value: "True"
- schedule: '* * * * *'
- successfulJobsHistoryLimit: 1
- suspend: false

diff:
-apiVersion: batch/v1beta1
-kind: CronJob
-metadata:
- annotations:
- testName: scheduled-backup
- labels:
- backupWorker: "True"
- cluster: scheduled-backup
- schedule: N_N_N_N_N
- type: cron
- name: f875c-each-min-minio
- ownerReferences:
- - controller: true
- kind: PerconaXtraDBCluster
- name: scheduled-backup
-spec:
- concurrencyPolicy: Allow
- failedJobsHistoryLimit: 1
- jobTemplate:
- metadata:
- ownerReferences:
- - apiVersion: batch/v1beta1
- kind: CronJob
- name: f875c-each-min-minio
- spec:
- template:
- metadata:
- annotations:
- testName: scheduled-backup
- labels:
- backupWorker: "True"
- cluster: scheduled-backup
- schedule: N_N_N_N_N
- type: cron
- spec:
- affinity:
- nodeAffinity:
- requiredDuringSchedulingIgnoredDuringExecution:
- nodeSelectorTerms:
- - matchExpressions:
- - key: backupWorker
- operator: In
- values:
- - "True"
- containers:
- - args:
- - sh
- - -c
- - "\n\t\t\t\t\t\t\tcat <<-EOF | kubectl apply -f -\n\t\t\t\t\t\t\t\t\tapiVersion: pxc.percona.com/v1\n\t\t\t\t\t\t\t\t\tkind: PerconaXtraDBClusterBackup\n\t\t\t\t\t\t\t\t\tmetadata:\n\t\t\t\t\t\t\t\t\t finalizers: [delete-s3-backup ]\n\t\t\t\t\t\t\t\t\t name: \"cron-${pxcCluster:0:16}-minio-$(date -u \"+%Y%m%d%H%M%S\")-${suffix}\"\n\t\t\t\t\t\t\t\t\t labels:\n\t\t\t\t\t\t\t\t\t ancestor: \"f875c-each-min-minio\"\n\t\t\t\t\t\t\t\t\t cluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t type: \"cron\"\n\t\t\t\t\t\t\t\t\tspec:\n\t\t\t\t\t\t\t\t\t pxcCluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t storageName: \"minio\"\n\t\t\t\t\t\t\tEOF\n\t\t\t\t\t\t\t"
- env:
- - name: pxcCluster
- value: scheduled-backup
- imagePullPolicy: Always
- name: run-backup
- resources:
- requests:
- cpu: 600m
- memory: 1G
- terminationMessagePath: /dev/termination-log
- terminationMessagePolicy: File
- dnsPolicy: ClusterFirst
- nodeSelector:
- backupWorker: "True"
- priorityClassName: high-priority
- restartPolicy: Never
- schedulerName: default-scheduler
- securityContext:
- supplementalGroups:
- - 1001
- serviceAccount: percona-xtradb-cluster-operator
- serviceAccountName: percona-xtradb-cluster-operator
- terminationGracePeriodSeconds: 30
- tolerations:
- - effect: NoSchedule
- key: backupWorker
- operator: Equal
- value: "True"
- schedule: '* * * * *'
- successfulJobsHistoryLimit: 1
- suspend: false

diff:
-apiVersion: batch/v1beta1
-kind: CronJob
-metadata:
- annotations:
- testName: scheduled-backup
- labels:
- backupWorker: "True"
- cluster: scheduled-backup
- schedule: N_N_N_N_N
- type: cron
- name: f875c-each-min-minio
- ownerReferences:
- - controller: true
- kind: PerconaXtraDBCluster
- name: scheduled-backup
-spec:
- concurrencyPolicy: Allow
- failedJobsHistoryLimit: 1
- jobTemplate:
- metadata:
- ownerReferences:
- - apiVersion: batch/v1beta1
- kind: CronJob
- name: f875c-each-min-minio
- spec:
- template:
- metadata:
- annotations:
- testName: scheduled-backup
- labels:
- backupWorker: "True"
- cluster: scheduled-backup
- schedule: N_N_N_N_N
- type: cron
- spec:
- affinity:
- nodeAffinity:
- requiredDuringSchedulingIgnoredDuringExecution:
- nodeSelectorTerms:
- - matchExpressions:
- - key: backupWorker
- operator: In
- values:
- - "True"
- containers:
- - args:
- - sh
- - -c
- - "\n\t\t\t\t\t\t\tcat <<-EOF | kubectl apply -f -\n\t\t\t\t\t\t\t\t\tapiVersion: pxc.percona.com/v1\n\t\t\t\t\t\t\t\t\tkind: PerconaXtraDBClusterBackup\n\t\t\t\t\t\t\t\t\tmetadata:\n\t\t\t\t\t\t\t\t\t finalizers: [delete-s3-backup ]\n\t\t\t\t\t\t\t\t\t name: \"cron-${pxcCluster:0:16}-minio-$(date -u \"+%Y%m%d%H%M%S\")-${suffix}\"\n\t\t\t\t\t\t\t\t\t labels:\n\t\t\t\t\t\t\t\t\t ancestor: \"f875c-each-min-minio\"\n\t\t\t\t\t\t\t\t\t cluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t type: \"cron\"\n\t\t\t\t\t\t\t\t\tspec:\n\t\t\t\t\t\t\t\t\t pxcCluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t storageName: \"minio\"\n\t\t\t\t\t\t\tEOF\n\t\t\t\t\t\t\t"
- env:
- - name: pxcCluster
- value: scheduled-backup
- imagePullPolicy: Always
- name: run-backup
- resources:
- requests:
- cpu: 600m
- memory: 1G
- terminationMessagePath: /dev/termination-log
- terminationMessagePolicy: File
- dnsPolicy: ClusterFirst
- nodeSelector:
- backupWorker: "True"
- priorityClassName: high-priority
- restartPolicy: Never
- schedulerName: default-scheduler
- securityContext:
- fsGroup: 1001
- supplementalGroups:
- - 1001
- serviceAccount: percona-xtradb-cluster-operator
- serviceAccountName: percona-xtradb-cluster-operator
- terminationGracePeriodSeconds: 30
- tolerations:
- - effect: NoSchedule
- key: backupWorker
- operator: Equal
- value: "True"
- schedule: '* * * * *'
- successfulJobsHistoryLimit: 1
- suspend: false

diff:
-apiVersion: batch/v1beta1
-kind: CronJob
-metadata:
- annotations:
- testName: scheduled-backup
- labels:
- backupWorker: "True"
- cluster: scheduled-backup
- schedule: N_N_N_N_N
- type: cron
- name: f875c-each-min-pvc
- ownerReferences:
- - controller: true
- kind: PerconaXtraDBCluster
- name: scheduled-backup
-spec:
- concurrencyPolicy: Allow
- failedJobsHistoryLimit: 1
- jobTemplate:
- metadata:
- ownerReferences:
- - apiVersion: batch/v1beta1
- kind: CronJob
- name: f875c-each-min-pvc
- spec:
- template:
- metadata:
- annotations:
- testName: scheduled-backup
- labels:
- backupWorker: "True"
- cluster: scheduled-backup
- schedule: N_N_N_N_N
- type: cron
- spec:
- affinity:
- nodeAffinity:
- requiredDuringSchedulingIgnoredDuringExecution:
- nodeSelectorTerms:
- - matchExpressions:
- - key: backupWorker
- operator: In
- values:
- - "True"
- containers:
- - args:
- - sh
- - -c
- - "\n\t\t\t\t\t\t\tcat <<-EOF | kubectl apply -f -\n\t\t\t\t\t\t\t\t\tapiVersion: pxc.percona.com/v1\n\t\t\t\t\t\t\t\t\tkind: PerconaXtraDBClusterBackup\n\t\t\t\t\t\t\t\t\tmetadata:\n\t\t\t\t\t\t\t\t\t finalizers: [ ]\n\t\t\t\t\t\t\t\t\t name: \"cron-${pxcCluster:0:16}-pvc-$(date -u \"+%Y%m%d%H%M%S\")-${suffix}\"\n\t\t\t\t\t\t\t\t\t labels:\n\t\t\t\t\t\t\t\t\t ancestor: \"f875c-each-min-pvc\"\n\t\t\t\t\t\t\t\t\t cluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t type: \"cron\"\n\t\t\t\t\t\t\t\t\tspec:\n\t\t\t\t\t\t\t\t\t pxcCluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t storageName: \"pvc\"\n\t\t\t\t\t\t\tEOF\n\t\t\t\t\t\t\t"
- env:
- - name: pxcCluster
- value: scheduled-backup
- imagePullPolicy: Always
- name: run-backup
- resources:
- requests:
- cpu: 600m
- memory: 1G
- terminationMessagePath: /dev/termination-log
- terminationMessagePolicy: File
- dnsPolicy: ClusterFirst
- nodeSelector:
- backupWorker: "True"
- priorityClassName: high-priority
- restartPolicy: Never
- schedulerName: default-scheduler
- securityContext:
- supplementalGroups:
- - 1001
- serviceAccount: percona-xtradb-cluster-operator
- serviceAccountName: percona-xtradb-cluster-operator
- terminationGracePeriodSeconds: 30
- tolerations:
- - effect: NoSchedule
- key: backupWorker
- operator: Equal
- value: "True"
- schedule: '* * * * *'
- successfulJobsHistoryLimit: 1
- suspend: false

diff:
-apiVersion: batch/v1beta1
-kind: CronJob
-metadata:
- annotations:
- testName: scheduled-backup
- labels:
- backupWorker: "True"
- cluster: scheduled-backup
- schedule: N_N_N_N_N
- type: cron
- name: f875c-each-min-pvc
- ownerReferences:
- - controller: true
- kind: PerconaXtraDBCluster
- name: scheduled-backup
-spec:
- concurrencyPolicy: Allow
- failedJobsHistoryLimit: 1
- jobTemplate:
- metadata:
- ownerReferences:
- - apiVersion: batch/v1beta1
- kind: CronJob
- name: f875c-each-min-pvc
- spec:
- template:
- metadata:
- annotations:
- testName: scheduled-backup
- labels:
- backupWorker: "True"
- cluster: scheduled-backup
- schedule: N_N_N_N_N
- type: cron
- spec:
- affinity:
- nodeAffinity:
- requiredDuringSchedulingIgnoredDuringExecution:
- nodeSelectorTerms:
- - matchExpressions:
- - key: backupWorker
- operator: In
- values:
- - "True"
- containers:
- - args:
- - sh
- - -c
- - "\n\t\t\t\t\t\t\tcat <<-EOF | kubectl apply -f -\n\t\t\t\t\t\t\t\t\tapiVersion: pxc.percona.com/v1\n\t\t\t\t\t\t\t\t\tkind: PerconaXtraDBClusterBackup\n\t\t\t\t\t\t\t\t\tmetadata:\n\t\t\t\t\t\t\t\t\t finalizers: [ ]\n\t\t\t\t\t\t\t\t\t name: \"cron-${pxcCluster:0:16}-pvc-$(date -u \"+%Y%m%d%H%M%S\")-${suffix}\"\n\t\t\t\t\t\t\t\t\t labels:\n\t\t\t\t\t\t\t\t\t ancestor: \"f875c-each-min-pvc\"\n\t\t\t\t\t\t\t\t\t cluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t type: \"cron\"\n\t\t\t\t\t\t\t\t\tspec:\n\t\t\t\t\t\t\t\t\t pxcCluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t storageName: \"pvc\"\n\t\t\t\t\t\t\tEOF\n\t\t\t\t\t\t\t"
- env:
- - name: pxcCluster
- value: scheduled-backup
- imagePullPolicy: Always
- name: run-backup
- resources:
- requests:
- cpu: 600m
- memory: 1G
- terminationMessagePath: /dev/termination-log
- terminationMessagePolicy: File
- dnsPolicy: ClusterFirst
- nodeSelector:
- backupWorker: "True"
- priorityClassName: high-priority
- restartPolicy: Never
- schedulerName: default-scheduler
- securityContext:
- fsGroup: 1001
- supplementalGroups:
- - 1001
- serviceAccount: percona-xtradb-cluster-operator
- serviceAccountName: percona-xtradb-cluster-operator
- terminationGracePeriodSeconds: 30
- tolerations:
- - effect: NoSchedule
- key: backupWorker
- operator: Equal
- value: "True"
- schedule: '* * * * *'
- successfulJobsHistoryLimit: 1
- suspend: false

diff:
@@ -170,15 +170,6 @@ main() {
label_node
sleep 20
- if [ -n "$OPERATOR_NS" ]; then
- kubectl_bin config set-context "$(kubectl_bin config current-context)" --namespace="$OPERATOR_NS"
- fi
- compare_kubectl cronjob/f875c-each-min-pvc
- compare_kubectl cronjob/f875c-each-min-minio
- if [ -z "$SKIP_BACKUPS_TO_AWS_GCP" ]; then
- compare_kubectl cronjob/f875c-each-min-aws-s3
- compare_kubectl cronjob/f875c-each-min-gcp-cs
- fi
kubectl_bin config set-context "$(kubectl_bin config current-context)" --namespace="$namespace"
sleep 300
@@ -203,20 +194,6 @@ main() {
POD_GCP_BACKUP=$(kubectl_bin get pods | grep ${JOB_GCP_BACKUP%-*} | awk '{print $1}')
fi
- compare_extrafields job ${JOB_PVC_BACKUP}
- compare_extrafields pod ${POD_PVC_BACKUP}
-
- compare_extrafields job ${JOB_MINIO_BACKUP}
- compare_extrafields pod ${POD_MINIO_BACKUP}
-
- if [ -z "$SKIP_BACKUPS_TO_AWS_GCP" ]; then
- compare_extrafields job ${JOB_AWS_BACKUP}
- compare_extrafields pod ${POD_AWS_BACKUP}
-
- compare_extrafields job ${JOB_GCP_BACKUP}
- compare_extrafields pod ${POD_GCP_BACKUP}
- fi
-
backup_name_pvc=$(get_backup_name "pvc")
backup_name_minio=$(get_backup_name "minio")
if [ -z "$SKIP_BACKUPS_TO_AWS_GCP" ]; then

diff:
-apiVersion: batch/v1beta1
-kind: CronJob
-metadata:
- annotations:
- openshift.io/scc: privileged
- labels:
- cluster: sec-context
- schedule: 0_NE1_N_N_N
- type: cron
- name: adc5a-each-hour-pvc
- ownerReferences:
- - controller: true
- kind: PerconaXtraDBCluster
- name: sec-context
-spec:
- concurrencyPolicy: Allow
- failedJobsHistoryLimit: 1
- jobTemplate:
- metadata:
- ownerReferences:
- - apiVersion: batch/v1beta1
- kind: CronJob
- name: adc5a-each-hour-pvc
- spec:
- template:
- metadata:
- annotations:
- openshift.io/scc: privileged
- labels:
- cluster: sec-context
- schedule: 0_NE1_N_N_N
- type: cron
- spec:
- containers:
- - args:
- - sh
- - -c
- - "\n\t\t\t\t\t\t\tcat <<-EOF | kubectl apply -f -\n\t\t\t\t\t\t\t\t\tapiVersion: pxc.percona.com/v1\n\t\t\t\t\t\t\t\t\tkind: PerconaXtraDBClusterBackup\n\t\t\t\t\t\t\t\t\tmetadata:\n\t\t\t\t\t\t\t\t\t finalizers: [ ]\n\t\t\t\t\t\t\t\t\t name: \"cron-${pxcCluster:0:16}-pvc-$(date -u \"+%Y%m%d%H%M%S\")-${suffix}\"\n\t\t\t\t\t\t\t\t\t labels:\n\t\t\t\t\t\t\t\t\t ancestor: \"adc5a-each-hour-pvc\"\n\t\t\t\t\t\t\t\t\t cluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t type: \"cron\"\n\t\t\t\t\t\t\t\t\tspec:\n\t\t\t\t\t\t\t\t\t pxcCluster: \"${pxcCluster}\"\n\t\t\t\t\t\t\t\t\t storageName: \"pvc\"\n\t\t\t\t\t\t\tEOF\n\t\t\t\t\t\t\t"
- env:
- - name: pxcCluster
- value: sec-context
- imagePullPolicy: Always
- name: run-backup
- resources: {}
- securityContext:
- privileged: true
- terminationMessagePath: /dev/termination-log
- terminationMessagePolicy: File
- dnsPolicy: ClusterFirst
- restartPolicy: Never
- schedulerName: default-scheduler
- securityContext:
- fsGroup: 1001
- supplementalGroups:
- - 1001
- - 1002
- - 1003
- serviceAccount: percona-xtradb-cluster-operator
- serviceAccountName: percona-xtradb-cluster-operator
- terminationGracePeriodSeconds: 30
- schedule: 0 */1 * * *
- successfulJobsHistoryLimit: 1
- suspend: false

diff:
@@ -45,10 +45,6 @@ kubectl_bin apply -f "$test_dir/conf/$cluster-$backup.yml"
wait_backup $backup
compare_kubectl job.batch/xb-$backup
-if [ -n "$OPERATOR_NS" ]; then
- kubectl_bin config set-context "$(kubectl_bin config current-context)" --namespace="$OPERATOR_NS"
-fi
-compare_kubectl cronjob/adc5a-each-hour-pvc
kubectl_bin config set-context "$(kubectl_bin config current-context)" --namespace="$namespace"
desc 'run pvc restore'

diff:
@@ -6,11 +6,14 @@ import (
"crypto/sha1"
"encoding/hex"
"fmt"
- "reflect"
+ "hash/crc32"
+ "strconv"
+ "strings"
+ "time"
"github.com/pkg/errors"
+ "github.com/robfig/cron/v3"
appsv1 "k8s.io/api/apps/v1"
- batchv1beta1 "k8s.io/api/batch/v1beta1"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
@@ -19,21 +22,20 @@ import (
api "github.com/percona/percona-xtradb-cluster-operator/pkg/apis/pxc/v1"
- "github.com/percona/percona-xtradb-cluster-operator/pkg/k8s"
"github.com/percona/percona-xtradb-cluster-operator/pkg/pxc/app/deployment"
- "github.com/percona/percona-xtradb-cluster-operator/pkg/pxc/backup"
)
+type BackupScheduleJob struct {
+ api.PXCScheduledBackupSchedule
+ JobID cron.EntryID
+}
+
func (r *ReconcilePerconaXtraDBCluster) reconcileBackups(cr *api.PerconaXtraDBCluster) error {
+ logger := r.logger("backup", cr.Namespace)
backups := make(map[string]api.PXCScheduledBackupSchedule)
- operatorPod, err := k8s.OperatorPod(r.client)
- if err != nil {
- return errors.Wrap(err, "get operator deployment")
- }
+ backupNamePrefix := backupJobClusterPrefix(cr.Name)
if cr.Spec.Backup != nil {
- bcpObj := backup.New(cr)
- backupNamePrefix := backupJobClusterPrefix(cr.Name)
if cr.Status.Status == api.AppStateReady && cr.Spec.Backup.PITR.Enabled && !cr.Spec.Pause {
binlogCollector, err := deployment.GetBinlogCollectorDeployment(cr)
@@ -59,86 +61,74 @@ func (r *ReconcilePerconaXtraDBCluster) reconcileBackups(cr *api.PerconaXtraDBCl
}
}
if !cr.Spec.Backup.PITR.Enabled || cr.Spec.Pause {
- err = r.deletePITR(cr)
+ err := r.deletePITR(cr)
if err != nil {
return errors.Wrap(err, "delete pitr")
}
}
- for _, bcp := range cr.Spec.Backup.Schedule {
+ for i, bcp := range cr.Spec.Backup.Schedule {
bcp.Name = backupNamePrefix + "-" + bcp.Name
backups[bcp.Name] = bcp
strg, ok := cr.Spec.Backup.Storages[bcp.StorageName]
if !ok {
- return fmt.Errorf("storage %s doesn't exist", bcp.StorageName)
- }
-
- bcpjob, err := bcpObj.Scheduled(&bcp, strg, operatorPod)
- if err != nil {
- return fmt.Errorf("unable to schedule backup: %w", err)
- }
- err = setControllerReference(cr, bcpjob, r.scheme)
- if err != nil {
- return fmt.Errorf("set owner ref to backup %s: %v", bcp.Name, err)
+ logger.Info("invalid storage name for backup", "backup name", cr.Spec.Backup.Schedule[i].Name, "storage name", bcp.StorageName)
+ continue
}
- // Check if this Job already exists
- currentBcpJob := new(batchv1beta1.CronJob)
- err = r.client.Get(context.TODO(), types.NamespacedName{
- Name: bcpjob.Name,
- Namespace: bcpjob.Namespace,
- }, currentBcpJob)
- if err != nil && !k8serrors.IsNotFound(err) {
- return errors.Wrapf(err, "create scheduled backup %s", bcp.Name)
+ sch := BackupScheduleJob{}
+ schRaw, ok := r.crons.backupJobs.Load(bcp.Name)
+ if ok {
+ sch = schRaw.(BackupScheduleJob)
}
- if k8serrors.IsNotFound(err) {
- err = r.client.Create(context.TODO(), bcpjob)
- if err != nil {
- return errors.Wrapf(err, "create scheduled backup %s", bcp.Name)
- }
- } else if !reflect.DeepEqual(currentBcpJob.Spec, bcpjob.Spec) {
- err = r.client.Update(context.TODO(), bcpjob)
+ if !ok || sch.PXCScheduledBackupSchedule.Schedule != bcp.Schedule ||
+ sch.PXCScheduledBackupSchedule.StorageName != bcp.StorageName {
+ r.log.Info("Creating or updating backup job", "name", bcp.Name, "schedule", bcp.Schedule)
+ r.deleteBackupJob(bcp.Name)
+ jobID, err := r.crons.crons.AddFunc(bcp.Schedule, r.createBackupJob(cr, bcp, strg.Type))
if err != nil {
- return errors.Wrapf(err, "update backup schedule %s", bcp.Name)
+ logger.Error(err, "can't parse cronjob schedule", "backup name", cr.Spec.Backup.Schedule[i].Name, "schedule", bcp.Schedule)
+ continue
}
+
+ r.crons.backupJobs.Store(bcp.Name, BackupScheduleJob{
+ PXCScheduledBackupSchedule: bcp,
+ JobID: jobID,
+ })
}
}
}
- // Reconcile backups list
- bcpList := batchv1beta1.CronJobList{}
- err = r.client.List(context.TODO(),
- &bcpList,
- &client.ListOptions{
- Namespace: operatorPod.ObjectMeta.Namespace,
- LabelSelector: labels.SelectorFromSet(map[string]string{
- "cluster": cr.Name,
- "type": "cron",
- }),
- },
- )
- if err != nil {
- return fmt.Errorf("get backups list: %v", err)
+ r.crons.backupJobs.Range(func(k, v interface{}) bool {
+ item := v.(BackupScheduleJob)
+ if !strings.HasPrefix(item.Name, backupNamePrefix) {
+ return true
}
-
- for _, item := range bcpList.Items {
if spec, ok := backups[item.Name]; ok {
if spec.Keep > 0 {
oldjobs, err := r.oldScheduledBackups(cr, item.Name, spec.Keep)
if err != nil {
- return fmt.Errorf("remove old backups: %v", err)
+ logger.Error(err, "failed to list old backups", "job name", item.Name)
+ return true
}
for _, todel := range oldjobs {
- _ = r.client.Delete(context.TODO(), &todel)
+ err = r.client.Delete(context.TODO(), &todel)
+ if err != nil {
+ logger.Error(err, "failed to delete old backup", "backup name", todel.Name)
}
}
- } else {
- _ = r.client.Delete(context.TODO(), &item)
+
}
+ } else {
+ r.log.Info("deleting outdated backup job", "name", item.Name)
+ r.deleteBackupJob(item.Name)
}
+ return true
+ })
+
return nil
}
@@ -192,6 +182,81 @@ func (r *ReconcilePerconaXtraDBCluster) oldScheduledBackups(cr *api.PerconaXtraD
return ret, nil
}
+func (r *ReconcilePerconaXtraDBCluster) createBackupJob(cr *api.PerconaXtraDBCluster, backupJob api.PXCScheduledBackupSchedule, storageType api.BackupStorageType) func() {
+ fins := []string{}
+ if storageType == api.BackupStorageS3 {
+ fins = append(fins, api.FinalizerDeleteS3Backup)
+ }
+
+ return func() {
+ localCr := &api.PerconaXtraDBCluster{}
+ err := r.client.Get(context.TODO(), types.NamespacedName{Name: cr.Name, Namespace: cr.Namespace}, localCr)
+ if k8serrors.IsNotFound(err) {
+ r.log.Info("cluster is not found, deleting the job",
+ "job name", jobName, "cluster", cr.Name, "namespace", cr.Namespace)
+ r.deleteBackupJob(backupJob.Name)
+ return
+ }
+
+ bcp := &api.PerconaXtraDBClusterBackup{
+ ObjectMeta: metav1.ObjectMeta{
+ Finalizers: fins,
+ Namespace: cr.Namespace,
+ Name: generateBackupName(cr, backupJob.StorageName) + "-" + strconv.FormatUint(uint64(crc32.ChecksumIEEE([]byte(backupJob.Schedule))), 32)[:5],
+ Labels: map[string]string{
+ "ancestor": backupJob.Name,
+ "cluster": cr.Name,
+ "type": "cron",
+ },
+ },
+ Spec: api.PXCBackupSpec{
+ PXCCluster: cr.Name,
+ StorageName: backupJob.StorageName,
+ },
+ }
+ err = r.client.Create(context.TODO(), bcp)
+ if err != nil {
+ r.log.Error(err, "failed to create backup")
+ }
+ }
+}
+
+func (r *ReconcilePerconaXtraDBCluster) deleteBackupJob(name string) {
+ job, ok := r.crons.backupJobs.LoadAndDelete(name)
+ if !ok {
+ return
+ }
+ r.crons.crons.Remove(job.(BackupScheduleJob).JobID)
+}
+
+func generateBackupName(cr *api.PerconaXtraDBCluster, storageName string) string {
+ result := "cron-"
+ if len(cr.Name) > 16 {
+ result += cr.Name[:16]
+ } else {
+ result += cr.Name
+ }
+ result += "-" + trimNameRight(storageName, 16) + "-"
+ tnow := time.Now()
+ result += fmt.Sprintf("%d%d%d%d%d%d", tnow.Year(), tnow.Month(), tnow.Day(), tnow.Hour(), tnow.Minute(), tnow.Second())
+ return result
+}
+
+func trimNameRight(name string, ln int) string {
+ if len(name) <= ln {
+ ln = len(name)
+ }
+
+ for ; ln > 0; ln-- {
+ if name[ln-1] >= 'a' && name[ln-1] <= 'z' ||
+ name[ln-1] >= '0' && name[ln-1] <= '9' {
+ break
+ }
+ }
+
+ return name[:ln]
+}
+
// A minHeap is a min-heap of backup jobs.
type minHeap []api.PerconaXtraDBClusterBackup

diff:
@@ -151,12 +151,13 @@ const (
type CronRegistry struct {
crons *cron.Cron
- jobs map[string]Shedule
+ ensureVersionJobs map[string]Schedule
+ backupJobs *sync.Map
}
-type Shedule struct {
+type Schedule struct {
ID int
- CronShedule string
+ CronSchedule string
}
const (
@@ -167,7 +168,8 @@ const (
func NewCronRegistry() CronRegistry {
c := CronRegistry{
crons: cron.New(),
- jobs: make(map[string]Shedule),
+ ensureVersionJobs: make(map[string]Schedule),
+ backupJobs: new(sync.Map),
}
c.crons.Start()

diff:
@@ -23,13 +23,13 @@ const never = "never"
const disabled = "disabled"
func (r *ReconcilePerconaXtraDBCluster) deleteEnsureVersion(jobName string) {
- r.crons.crons.Remove(cron.EntryID(r.crons.jobs[jobName].ID))
- delete(r.crons.jobs, jobName)
+ r.crons.crons.Remove(cron.EntryID(r.crons.ensureVersionJobs[jobName].ID))
+ delete(r.crons.ensureVersionJobs, jobName)
}
func (r *ReconcilePerconaXtraDBCluster) sheduleEnsurePXCVersion(cr *api.PerconaXtraDBCluster, vs VersionService) error {
jn := jobName(cr)
- schedule, ok := r.crons.jobs[jn]
+ schedule, ok := r.crons.ensureVersionJobs[jn]
if cr.Spec.UpdateStrategy != v1.SmartUpdateStatefulSetStrategyType ||
cr.Spec.UpgradeOptions.Schedule == "" ||
strings.ToLower(cr.Spec.UpgradeOptions.Apply) == never ||
@@ -40,14 +40,14 @@ func (r *ReconcilePerconaXtraDBCluster) sheduleEnsurePXCVersion(cr *api.PerconaX
return nil
}
- if ok && schedule.CronShedule == cr.Spec.UpgradeOptions.Schedule {
+ if ok && schedule.CronSchedule == cr.Spec.UpgradeOptions.Schedule {
return nil
}
logger := r.logger(cr.Name, cr.Namespace)
if ok {
- logger.Info("remove job because of new", "old", schedule.CronShedule, "new", cr.Spec.UpgradeOptions.Schedule)
+ logger.Info("remove job because of new", "old", schedule.CronSchedule, "new", cr.Spec.UpgradeOptions.Schedule)
r.deleteEnsureVersion(jn)
}
@@ -102,9 +102,9 @@ func (r *ReconcilePerconaXtraDBCluster) sheduleEnsurePXCVersion(cr *api.PerconaX
logger.Info("add new job", "name", jn, "schedule", cr.Spec.UpgradeOptions.Schedule)
- r.crons.jobs[jn] = Shedule{
+ r.crons.ensureVersionJobs[jn] = Schedule{
ID: int(id),
- CronShedule: cr.Spec.UpgradeOptions.Schedule,
+ CronSchedule: cr.Spec.UpgradeOptions.Schedule,
}
return nil

original_message: K8SPXC-701 fix cronjob updates (#841)


message: fix one pod test

diff:
@@ -161,32 +161,32 @@ func (r *ReconcilePerconaXtraDBClusterBackup) Reconcile(request reconcile.Reques
cluster, err := r.getClusterConfig(cr)
if err != nil {
logger.Error(err, "invalid backup cluster")
- return reconcile.Result{}, nil
+ return rr, nil
}
_, err = cluster.CheckNSetDefaults(r.serverVersion, logger)
if err != nil {
- return reconcile.Result{}, errors.Wrap(err, "wrong PXC options")
+ return rr, errors.Wrap(err, "wrong PXC options")
}
if cluster.Spec.Backup == nil {
- return reconcile.Result{}, errors.Wrap(err, "a backup image should be set in the PXC config")
+ return rr, errors.New("a backup image should be set in the PXC config")
}
if cluster.Status.PXC.Status != api.AppStateReady {
- return reconcile.Result{}, errors.Wrapf(err, "failed to run backup on cluster with status %s", cluster.Status.Status)
+ return rr, errors.Errorf("failed to run backup on cluster with status %s", cluster.Status.Status)
}
bcpStorage, ok := cluster.Spec.Backup.Storages[cr.Spec.StorageName]
if !ok {
- return reconcile.Result{}, errors.Wrapf(err, "bcpStorage %s doesn't exist", cr.Spec.StorageName)
+ return rr, errors.Errorf("bcpStorage %s doesn't exist", cr.Spec.StorageName)
}
bcp := backup.New(cluster)
job := bcp.Job(cr, cluster)
job.Spec, err = bcp.JobSpec(cr.Spec, cluster.Spec, job)
if err != nil {
- return reconcile.Result{}, errors.Wrap(err, "can't create job spec")
+ return rr, errors.Wrap(err, "can't create job spec")
}
var destination string
@@ -201,7 +201,7 @@ func (r *ReconcilePerconaXtraDBClusterBackup) Reconcile(request reconcile.Reques
// Set PerconaXtraDBClusterBackup instance as the owner and controller
if err := setControllerReference(cr, pvc, r.scheme); err != nil {
- return reconcile.Result{}, errors.Wrap(err, "setControllerReference")
+ return rr, errors.Wrap(err, "setControllerReference")
}
// Check if this PVC already exists
@@ -210,15 +210,15 @@ func (r *ReconcilePerconaXtraDBClusterBackup) Reconcile(request reconcile.Reques
logger.Info("Creating a new volume for backup", "Namespace", pvc.Namespace, "Name", pvc.Name)
err = r.client.Create(context.TODO(), pvc)
if err != nil {
- return reconcile.Result{}, errors.Wrap(err, "create backup pvc")
+ return rr, errors.Wrap(err, "create backup pvc")
}
} else if err != nil {
- return reconcile.Result{}, errors.Wrap(err, "get backup pvc")
+ return rr, errors.Wrap(err, "get backup pvc")
}
err := bcp.SetStoragePVC(&job.Spec, cluster, pvc.Name)
if err != nil {
- return reconcile.Result{}, errors.Wrap(err, "set storage FS")
+ return rr, errors.Wrap(err, "set storage FS")
}
case api.BackupStorageS3:
destination = bcpStorage.S3.Bucket + "/" + cr.Spec.PXCCluster + "-" + cr.CreationTimestamp.Time.Format("2006-01-02-15:04:05") + "-full"
@@ -228,7 +228,7 @@ func (r *ReconcilePerconaXtraDBClusterBackup) Reconcile(request reconcile.Reques
err := bcp.SetStorageS3(&job.Spec, cluster, bcpStorage.S3, destination)
if err != nil {
- return reconcile.Result{}, errors.Wrap(err, "set storage FS")
+ return rr, errors.Wrap(err, "set storage FS")
}
s3status = &bcpStorage.S3
@@ -236,12 +236,12 @@ func (r *ReconcilePerconaXtraDBClusterBackup) Reconcile(request reconcile.Reques
// Set PerconaXtraDBClusterBackup instance as the owner and controller
if err := setControllerReference(cr, job, r.scheme); err != nil {
- return reconcile.Result{}, errors.Wrap(err, "job/setControllerReference")
+ return rr, errors.Wrap(err, "job/setControllerReference")
}
err = r.client.Create(context.TODO(), job)
if err != nil && !k8sErrors.IsAlreadyExists(err) {
- return reconcile.Result{}, errors.Wrap(err, "create backup job")
+ return rr, errors.Wrap(err, "create backup job")
} else if err == nil {
logger.Info("Created a new backup job", "Namespace", job.Namespace, "Name", job.Name)
}

original_message: fix one pod test (#893)