diff --git a/pkg/cluster/resources.go b/pkg/cluster/resources.go index 8a95f67c0..10d0d1bde 100644 --- a/pkg/cluster/resources.go +++ b/pkg/cluster/resources.go @@ -2,6 +2,8 @@ package cluster import ( "fmt" + "strconv" + "strings" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" @@ -119,26 +121,54 @@ func (c *Cluster) createStatefulSet() (*v1beta1.StatefulSet, error) { return statefulSet, nil } -func (c *Cluster) scaleDown(newStatefulSet *v1beta1.StatefulSet) error { - podName := fmt.Sprintf("%s-0", c.Statefulset.Name) //TODO: +func getPodNumb(podName string) (int32, error) { + parts := strings.Split(podName, "-") + if len(parts) == 0 { + return 0, fmt.Errorf("no postfix") + } + + postfix := parts[len(parts)-1] + res, err := strconv.ParseInt(postfix, 10, 64) + if err != nil { + return 0, fmt.Errorf("couldn not parse postfix: %v", err) + } + + return int32(res), nil +} + +func (c *Cluster) preScaleDown(newStatefulSet *v1beta1.StatefulSet) error { + masterPod, err := c.getRolePods(Master) + if err != nil { + return fmt.Errorf("could not get master pod: %v", err) + } + + podNum, err := getPodNumb(masterPod[0].Name) + if err != nil { + return fmt.Errorf("could not get pod number: %v", err) + } + + //Check if scale down affects current master pod + if (*c.Statefulset.Spec.Replicas < podNum+1) || + (*newStatefulSet.Spec.Replicas > podNum+1) { + return nil + } + + podName := fmt.Sprintf("%s-0", c.Statefulset.Name) masterCandidatePod, err := c.KubeClient.Pods(c.OpConfig.Namespace).Get(podName, metav1.GetOptions{}) if err != nil { return fmt.Errorf("could not get master candidate pod: %v", err) } - //TODO: check if the pod is master pod + if c.podSpiloRole(masterCandidatePod) == string(Master) { + return nil + } // some sanity check if !util.MapContains(masterCandidatePod.Labels, c.OpConfig.ClusterLabels) || - !util.MapContains(masterCandidatePod.Labels, map[string]string{c.OpConfig.ClusterNameLabel:c.Name}) { + !util.MapContains(masterCandidatePod.Labels, map[string]string{c.OpConfig.ClusterNameLabel: c.Name}) { return fmt.Errorf("pod %q does not belong to cluster", podName) } - masterPod, err := c.getRolePods(Master) - if err != nil { - return fmt.Errorf("could not get master pod: %v", err) - } - if err := c.patroni.Failover(&masterPod[0], masterCandidatePod.Name); err != nil { return fmt.Errorf("could not failover: %v", err) } @@ -153,6 +183,12 @@ func (c *Cluster) updateStatefulSet(newStatefulSet *v1beta1.StatefulSet) error { } statefulSetName := util.NameFromMeta(c.Statefulset.ObjectMeta) + //scale down + if *c.Statefulset.Spec.Replicas > *newStatefulSet.Spec.Replicas { + if err := c.preScaleDown(newStatefulSet); err != nil { + return fmt.Errorf("could not scale down: %v", err) + } + } c.logger.Debugf("updating statefulset") patchData, err := specPatch(newStatefulSet.Spec) @@ -160,11 +196,6 @@ func (c *Cluster) updateStatefulSet(newStatefulSet *v1beta1.StatefulSet) error { return fmt.Errorf("could not form patch for the statefulset %q: %v", statefulSetName, err) } - //Scale down - if *c.Statefulset.Spec.Replicas > *newStatefulSet.Spec.Replicas { - c.scaleDown(newStatefulSet) - } - statefulSet, err := c.KubeClient.StatefulSets(c.Statefulset.Namespace).Patch( c.Statefulset.Name, types.MergePatchType,