Merge branch 'master' into storage-resize-fixes
This commit is contained in:
		
						commit
						abe7b39619
					
				| 
						 | 
					@ -56,12 +56,24 @@ NOCLEANUP=True ./run.sh main tests.test_e2e.EndToEndTestCase.test_lazy_spilo_upg
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Inspecting Kind
 | 
					## Inspecting Kind
 | 
				
			||||||
 | 
					
 | 
				
			||||||
If you want to inspect Kind/Kubernetes cluster, use the following script to exec into the K8s setup and then use `kubectl`
 | 
					If you want to inspect Kind/Kubernetes cluster, switch `kubeconfig` file and context
 | 
				
			||||||
 | 
					```bash
 | 
				
			||||||
 | 
					# save the old config in case you have it
 | 
				
			||||||
 | 
					export KUBECONFIG_SAVED=$KUBECONFIG
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# use the one created by e2e tests
 | 
				
			||||||
 | 
					export KUBECONFIG=/tmp/kind-config-postgres-operator-e2e-tests
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# this kubeconfig defines a single context
 | 
				
			||||||
 | 
					kubectl config use-context kind-postgres-operator-e2e-tests
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					or use the following script to exec into the K8s setup and then use `kubectl`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```bash
 | 
					```bash
 | 
				
			||||||
./exec_into_env.sh
 | 
					./exec_into_env.sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# use kube ctl
 | 
					# use kubectl
 | 
				
			||||||
kubectl get pods
 | 
					kubectl get pods
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# watch relevant objects
 | 
					# watch relevant objects
 | 
				
			||||||
| 
						 | 
					@ -71,6 +83,14 @@ kubectl get pods
 | 
				
			||||||
./scripts/get_logs.sh
 | 
					./scripts/get_logs.sh
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you want to inspect the state of the `kind` cluster manually with a single command, add a `context` flag
 | 
				
			||||||
 | 
					```bash
 | 
				
			||||||
 | 
					kubectl get pods --context kind-kind
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					or set the context for a few commands at once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Cleaning up Kind
 | 
					## Cleaning up Kind
 | 
				
			||||||
 | 
					
 | 
				
			||||||
To cleanup kind and start fresh
 | 
					To cleanup kind and start fresh
 | 
				
			||||||
| 
						 | 
					@ -79,6 +99,12 @@ To cleanup kind and start fresh
 | 
				
			||||||
e2e/run.sh cleanup
 | 
					e2e/run.sh cleanup
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					That also helps in case you see the
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					ERROR: no nodes found for cluster "postgres-operator-e2e-tests"
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					that happens when the `kind` cluster was deleted manually but its configuraiton file was not.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Covered use cases
 | 
					## Covered use cases
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The current tests are all bundled in [`test_e2e.py`](tests/test_e2e.py):
 | 
					The current tests are all bundled in [`test_e2e.py`](tests/test_e2e.py):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,9 +11,11 @@ from datetime import datetime
 | 
				
			||||||
from kubernetes import client, config
 | 
					from kubernetes import client, config
 | 
				
			||||||
from kubernetes.client.rest import ApiException
 | 
					from kubernetes.client.rest import ApiException
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def to_selector(labels):
 | 
					def to_selector(labels):
 | 
				
			||||||
    return ",".join(["=".join(l) for l in labels.items()])
 | 
					    return ",".join(["=".join(l) for l in labels.items()])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class K8sApi:
 | 
					class K8sApi:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self):
 | 
					    def __init__(self):
 | 
				
			||||||
| 
						 | 
					@ -181,10 +183,10 @@ class K8s:
 | 
				
			||||||
    def count_pdbs_with_label(self, labels, namespace='default'):
 | 
					    def count_pdbs_with_label(self, labels, namespace='default'):
 | 
				
			||||||
        return len(self.api.policy_v1_beta1.list_namespaced_pod_disruption_budget(
 | 
					        return len(self.api.policy_v1_beta1.list_namespaced_pod_disruption_budget(
 | 
				
			||||||
            namespace, label_selector=labels).items)
 | 
					            namespace, label_selector=labels).items)
 | 
				
			||||||
  
 | 
					
 | 
				
			||||||
    def count_running_pods(self, labels='application=spilo,cluster-name=acid-minimal-cluster', namespace='default'):
 | 
					    def count_running_pods(self, labels='application=spilo,cluster-name=acid-minimal-cluster', namespace='default'):
 | 
				
			||||||
        pods = self.api.core_v1.list_namespaced_pod(namespace, label_selector=labels).items
 | 
					        pods = self.api.core_v1.list_namespaced_pod(namespace, label_selector=labels).items
 | 
				
			||||||
        return len(list(filter(lambda x: x.status.phase=='Running', pods)))
 | 
					        return len(list(filter(lambda x: x.status.phase == 'Running', pods)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def wait_for_pod_failover(self, failover_targets, labels, namespace='default'):
 | 
					    def wait_for_pod_failover(self, failover_targets, labels, namespace='default'):
 | 
				
			||||||
        pod_phase = 'Failing over'
 | 
					        pod_phase = 'Failing over'
 | 
				
			||||||
| 
						 | 
					@ -210,9 +212,9 @@ class K8s:
 | 
				
			||||||
    def wait_for_logical_backup_job_creation(self):
 | 
					    def wait_for_logical_backup_job_creation(self):
 | 
				
			||||||
        self.wait_for_logical_backup_job(expected_num_of_jobs=1)
 | 
					        self.wait_for_logical_backup_job(expected_num_of_jobs=1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def delete_operator_pod(self, step="Delete operator deplyment"):
 | 
					    def delete_operator_pod(self, step="Delete operator pod"):
 | 
				
			||||||
        operator_pod = self.api.core_v1.list_namespaced_pod('default', label_selector="name=postgres-operator").items[0].metadata.name
 | 
					        # patching the pod template in the deployment restarts the operator pod
 | 
				
			||||||
        self.api.apps_v1.patch_namespaced_deployment("postgres-operator","default", {"spec":{"template":{"metadata":{"annotations":{"step":"{}-{}".format(step, time.time())}}}}})
 | 
					        self.api.apps_v1.patch_namespaced_deployment("postgres-operator","default", {"spec":{"template":{"metadata":{"annotations":{"step":"{}-{}".format(step, datetime.fromtimestamp(time.time()))}}}}})
 | 
				
			||||||
        self.wait_for_operator_pod_start()
 | 
					        self.wait_for_operator_pod_start()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def update_config(self, config_map_patch, step="Updating operator deployment"):
 | 
					    def update_config(self, config_map_patch, step="Updating operator deployment"):
 | 
				
			||||||
| 
						 | 
					@ -241,7 +243,7 @@ class K8s:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_operator_state(self):
 | 
					    def get_operator_state(self):
 | 
				
			||||||
        pod = self.get_operator_pod()
 | 
					        pod = self.get_operator_pod()
 | 
				
			||||||
        if pod == None:
 | 
					        if pod is None:
 | 
				
			||||||
            return None
 | 
					            return None
 | 
				
			||||||
        pod = pod.metadata.name
 | 
					        pod = pod.metadata.name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -251,7 +253,6 @@ class K8s:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return json.loads(r.stdout.decode())
 | 
					        return json.loads(r.stdout.decode())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    def get_patroni_running_members(self, pod="acid-minimal-cluster-0"):
 | 
					    def get_patroni_running_members(self, pod="acid-minimal-cluster-0"):
 | 
				
			||||||
        result = self.get_patroni_state(pod)
 | 
					        result = self.get_patroni_state(pod)
 | 
				
			||||||
        return list(filter(lambda x: "State" in x and x["State"] == "running", result))
 | 
					        return list(filter(lambda x: "State" in x and x["State"] == "running", result))
 | 
				
			||||||
| 
						 | 
					@ -260,9 +261,9 @@ class K8s:
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            deployment = self.api.apps_v1.read_namespaced_deployment(name, namespace)
 | 
					            deployment = self.api.apps_v1.read_namespaced_deployment(name, namespace)
 | 
				
			||||||
            return deployment.spec.replicas
 | 
					            return deployment.spec.replicas
 | 
				
			||||||
        except ApiException as e:
 | 
					        except ApiException:
 | 
				
			||||||
            return None
 | 
					            return None
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    def get_statefulset_image(self, label_selector="application=spilo,cluster-name=acid-minimal-cluster", namespace='default'):
 | 
					    def get_statefulset_image(self, label_selector="application=spilo,cluster-name=acid-minimal-cluster", namespace='default'):
 | 
				
			||||||
        ssets = self.api.apps_v1.list_namespaced_stateful_set(namespace, label_selector=label_selector, limit=1)
 | 
					        ssets = self.api.apps_v1.list_namespaced_stateful_set(namespace, label_selector=label_selector, limit=1)
 | 
				
			||||||
        if len(ssets.items) == 0:
 | 
					        if len(ssets.items) == 0:
 | 
				
			||||||
| 
						 | 
					@ -463,7 +464,6 @@ class K8sBase:
 | 
				
			||||||
        self.wait_for_logical_backup_job(expected_num_of_jobs=1)
 | 
					        self.wait_for_logical_backup_job(expected_num_of_jobs=1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def delete_operator_pod(self, step="Delete operator deplyment"):
 | 
					    def delete_operator_pod(self, step="Delete operator deplyment"):
 | 
				
			||||||
        operator_pod = self.api.core_v1.list_namespaced_pod('default', label_selector="name=postgres-operator").items[0].metadata.name
 | 
					 | 
				
			||||||
        self.api.apps_v1.patch_namespaced_deployment("postgres-operator","default", {"spec":{"template":{"metadata":{"annotations":{"step":"{}-{}".format(step, time.time())}}}}})
 | 
					        self.api.apps_v1.patch_namespaced_deployment("postgres-operator","default", {"spec":{"template":{"metadata":{"annotations":{"step":"{}-{}".format(step, time.time())}}}}})
 | 
				
			||||||
        self.wait_for_operator_pod_start()
 | 
					        self.wait_for_operator_pod_start()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -521,7 +521,7 @@ class K8sOperator(K8sBase):
 | 
				
			||||||
class K8sPostgres(K8sBase):
 | 
					class K8sPostgres(K8sBase):
 | 
				
			||||||
    def __init__(self, labels="cluster-name=acid-minimal-cluster", namespace="default"):
 | 
					    def __init__(self, labels="cluster-name=acid-minimal-cluster", namespace="default"):
 | 
				
			||||||
        super().__init__(labels, namespace)
 | 
					        super().__init__(labels, namespace)
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    def get_pg_nodes(self):
 | 
					    def get_pg_nodes(self):
 | 
				
			||||||
        master_pod_node = ''
 | 
					        master_pod_node = ''
 | 
				
			||||||
        replica_pod_nodes = []
 | 
					        replica_pod_nodes = []
 | 
				
			||||||
| 
						 | 
					@ -532,4 +532,4 @@ class K8sPostgres(K8sBase):
 | 
				
			||||||
            elif pod.metadata.labels.get('spilo-role') == 'replica':
 | 
					            elif pod.metadata.labels.get('spilo-role') == 'replica':
 | 
				
			||||||
                replica_pod_nodes.append(pod.spec.node_name)
 | 
					                replica_pod_nodes.append(pod.spec.node_name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return master_pod_node, replica_pod_nodes
 | 
					        return master_pod_node, replica_pod_nodes
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,15 +2,14 @@ import json
 | 
				
			||||||
import unittest
 | 
					import unittest
 | 
				
			||||||
import time
 | 
					import time
 | 
				
			||||||
import timeout_decorator
 | 
					import timeout_decorator
 | 
				
			||||||
import subprocess
 | 
					 | 
				
			||||||
import warnings
 | 
					 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import yaml
 | 
					import yaml
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from datetime import datetime
 | 
					from datetime import datetime
 | 
				
			||||||
from kubernetes import client, config
 | 
					from kubernetes import client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from tests.k8s_api import K8s
 | 
					from tests.k8s_api import K8s
 | 
				
			||||||
 | 
					from kubernetes.client.rest import ApiException
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SPILO_CURRENT = "registry.opensource.zalan.do/acid/spilo-12:1.6-p5"
 | 
					SPILO_CURRENT = "registry.opensource.zalan.do/acid/spilo-12:1.6-p5"
 | 
				
			||||||
SPILO_LAZY = "registry.opensource.zalan.do/acid/spilo-cdp-12:1.6-p114"
 | 
					SPILO_LAZY = "registry.opensource.zalan.do/acid/spilo-cdp-12:1.6-p114"
 | 
				
			||||||
| 
						 | 
					@ -89,17 +88,17 @@ class EndToEndTestCase(unittest.TestCase):
 | 
				
			||||||
        # remove existing local storage class and create hostpath class
 | 
					        # remove existing local storage class and create hostpath class
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            k8s.api.storage_v1_api.delete_storage_class("standard")
 | 
					            k8s.api.storage_v1_api.delete_storage_class("standard")
 | 
				
			||||||
        except:
 | 
					        except ApiException as e:
 | 
				
			||||||
            print("Storage class has already been remove")
 | 
					            print("Failed to delete the 'standard' storage class: {0}".format(e))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # operator deploys pod service account there on start up
 | 
					        # operator deploys pod service account there on start up
 | 
				
			||||||
        # needed for test_multi_namespace_support()
 | 
					        # needed for test_multi_namespace_support()
 | 
				
			||||||
        cls.namespace = "test"
 | 
					        cls.test_namespace = "test"
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            v1_namespace = client.V1Namespace(metadata=client.V1ObjectMeta(name=cls.namespace))
 | 
					            v1_namespace = client.V1Namespace(metadata=client.V1ObjectMeta(name=cls.test_namespace))
 | 
				
			||||||
            k8s.api.core_v1.create_namespace(v1_namespace)
 | 
					            k8s.api.core_v1.create_namespace(v1_namespace)
 | 
				
			||||||
        except:
 | 
					        except ApiException as e:
 | 
				
			||||||
            print("Namespace already present")
 | 
					            print("Failed to create the '{0}' namespace: {1}".format(cls.test_namespace, e))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # submit the most recent operator image built on the Docker host
 | 
					        # submit the most recent operator image built on the Docker host
 | 
				
			||||||
        with open("manifests/postgres-operator.yaml", 'r+') as f:
 | 
					        with open("manifests/postgres-operator.yaml", 'r+') as f:
 | 
				
			||||||
| 
						 | 
					@ -135,10 +134,8 @@ class EndToEndTestCase(unittest.TestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # make sure we start a new operator on every new run,
 | 
					        # make sure we start a new operator on every new run,
 | 
				
			||||||
        # this tackles the problem when kind is reused
 | 
					        # this tackles the problem when kind is reused
 | 
				
			||||||
        # and the Docker image is infact changed (dirty one)
 | 
					        # and the Docker image is in fact changed (dirty one)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # patch resync period, this can catch some problems with hanging e2e tests
 | 
					 | 
				
			||||||
        # k8s.update_config({"data": {"resync_period":"30s"}},step="TestSuite setup")
 | 
					 | 
				
			||||||
        k8s.update_config({}, step="TestSuite Startup")
 | 
					        k8s.update_config({}, step="TestSuite Startup")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        actual_operator_image = k8s.api.core_v1.list_namespaced_pod(
 | 
					        actual_operator_image = k8s.api.core_v1.list_namespaced_pod(
 | 
				
			||||||
| 
						 | 
					@ -170,9 +167,6 @@ class EndToEndTestCase(unittest.TestCase):
 | 
				
			||||||
            'connection-pooler': 'acid-minimal-cluster-pooler',
 | 
					            'connection-pooler': 'acid-minimal-cluster-pooler',
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        pod_selector = to_selector(pod_labels)
 | 
					 | 
				
			||||||
        service_selector = to_selector(service_labels)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # enable connection pooler
 | 
					        # enable connection pooler
 | 
				
			||||||
        k8s.api.custom_objects_api.patch_namespaced_custom_object(
 | 
					        k8s.api.custom_objects_api.patch_namespaced_custom_object(
 | 
				
			||||||
            'acid.zalan.do', 'v1', 'default',
 | 
					            'acid.zalan.do', 'v1', 'default',
 | 
				
			||||||
| 
						 | 
					@ -347,7 +341,7 @@ class EndToEndTestCase(unittest.TestCase):
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        k8s.update_config(patch_infrastructure_roles)
 | 
					        k8s.update_config(patch_infrastructure_roles)
 | 
				
			||||||
        self.eventuallyEqual(lambda: k8s.get_operator_state(), {"0":"idle"}, "Operator does not get in sync")
 | 
					        self.eventuallyEqual(lambda: k8s.get_operator_state(), {"0": "idle"}, "Operator does not get in sync")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            # check that new roles are represented in the config by requesting the
 | 
					            # check that new roles are represented in the config by requesting the
 | 
				
			||||||
| 
						 | 
					@ -604,17 +598,25 @@ class EndToEndTestCase(unittest.TestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        with open("manifests/complete-postgres-manifest.yaml", 'r+') as f:
 | 
					        with open("manifests/complete-postgres-manifest.yaml", 'r+') as f:
 | 
				
			||||||
            pg_manifest = yaml.safe_load(f)
 | 
					            pg_manifest = yaml.safe_load(f)
 | 
				
			||||||
            pg_manifest["metadata"]["namespace"] = self.namespace
 | 
					            pg_manifest["metadata"]["namespace"] = self.test_namespace
 | 
				
			||||||
            yaml.dump(pg_manifest, f, Dumper=yaml.Dumper)
 | 
					            yaml.dump(pg_manifest, f, Dumper=yaml.Dumper)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            k8s.create_with_kubectl("manifests/complete-postgres-manifest.yaml")
 | 
					            k8s.create_with_kubectl("manifests/complete-postgres-manifest.yaml")
 | 
				
			||||||
            k8s.wait_for_pod_start("spilo-role=master", self.namespace)
 | 
					            k8s.wait_for_pod_start("spilo-role=master", self.test_namespace)
 | 
				
			||||||
            self.assert_master_is_unique(self.namespace, "acid-test-cluster")
 | 
					            self.assert_master_is_unique(self.test_namespace, "acid-test-cluster")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        except timeout_decorator.TimeoutError:
 | 
					        except timeout_decorator.TimeoutError:
 | 
				
			||||||
            print('Operator log: {}'.format(k8s.get_operator_log()))
 | 
					            print('Operator log: {}'.format(k8s.get_operator_log()))
 | 
				
			||||||
            raise
 | 
					            raise
 | 
				
			||||||
 | 
					        finally:
 | 
				
			||||||
 | 
					            # delete the new cluster so that the k8s_api.get_operator_state works correctly in subsequent tests
 | 
				
			||||||
 | 
					            # ideally we should delete the 'test' namespace here but
 | 
				
			||||||
 | 
					            # the pods inside the namespace stuck in the Terminating state making the test time out
 | 
				
			||||||
 | 
					            k8s.api.custom_objects_api.delete_namespaced_custom_object(
 | 
				
			||||||
 | 
					                "acid.zalan.do", "v1", self.test_namespace, "postgresqls", "acid-test-cluster")
 | 
				
			||||||
 | 
					            time.sleep(5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @timeout_decorator.timeout(TEST_TIMEOUT_SEC)
 | 
					    @timeout_decorator.timeout(TEST_TIMEOUT_SEC)
 | 
				
			||||||
    def test_zz_node_readiness_label(self):
 | 
					    def test_zz_node_readiness_label(self):
 | 
				
			||||||
| 
						 | 
					@ -746,12 +748,12 @@ class EndToEndTestCase(unittest.TestCase):
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        k8s.api.custom_objects_api.patch_namespaced_custom_object(
 | 
					        k8s.api.custom_objects_api.patch_namespaced_custom_object(
 | 
				
			||||||
            "acid.zalan.do", "v1", "default", "postgresqls", "acid-minimal-cluster", pg_crd_annotations)
 | 
					            "acid.zalan.do", "v1", "default", "postgresqls", "acid-minimal-cluster", pg_crd_annotations)
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        annotations = {
 | 
					        annotations = {
 | 
				
			||||||
            "deployment-time": "2020-04-30 12:00:00",
 | 
					            "deployment-time": "2020-04-30 12:00:00",
 | 
				
			||||||
            "downscaler/downtime_replicas": "0",
 | 
					            "downscaler/downtime_replicas": "0",
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        self.eventuallyTrue(lambda: k8s.check_statefulset_annotations(cluster_label, annotations), "Annotations missing")
 | 
					        self.eventuallyTrue(lambda: k8s.check_statefulset_annotations(cluster_label, annotations), "Annotations missing")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -823,14 +825,14 @@ class EndToEndTestCase(unittest.TestCase):
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        k8s.update_config(patch_delete_annotations)
 | 
					        k8s.update_config(patch_delete_annotations)
 | 
				
			||||||
        self.eventuallyEqual(lambda: k8s.get_operator_state(), {"0":"idle"}, "Operator does not get in sync")
 | 
					        self.eventuallyEqual(lambda: k8s.get_operator_state(), {"0": "idle"}, "Operator does not get in sync")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            # this delete attempt should be omitted because of missing annotations
 | 
					            # this delete attempt should be omitted because of missing annotations
 | 
				
			||||||
            k8s.api.custom_objects_api.delete_namespaced_custom_object(
 | 
					            k8s.api.custom_objects_api.delete_namespaced_custom_object(
 | 
				
			||||||
                "acid.zalan.do", "v1", "default", "postgresqls", "acid-minimal-cluster")
 | 
					                "acid.zalan.do", "v1", "default", "postgresqls", "acid-minimal-cluster")
 | 
				
			||||||
            time.sleep(5)
 | 
					            time.sleep(5)
 | 
				
			||||||
            self.eventuallyEqual(lambda: k8s.get_operator_state(), {"0":"idle"}, "Operator does not get in sync")
 | 
					            self.eventuallyEqual(lambda: k8s.get_operator_state(), {"0": "idle"}, "Operator does not get in sync")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # check that pods and services are still there
 | 
					            # check that pods and services are still there
 | 
				
			||||||
            k8s.wait_for_running_pods(cluster_label, 2)
 | 
					            k8s.wait_for_running_pods(cluster_label, 2)
 | 
				
			||||||
| 
						 | 
					@ -841,7 +843,7 @@ class EndToEndTestCase(unittest.TestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # wait a little before proceeding
 | 
					            # wait a little before proceeding
 | 
				
			||||||
            time.sleep(10)
 | 
					            time.sleep(10)
 | 
				
			||||||
            self.eventuallyEqual(lambda: k8s.get_operator_state(), {"0":"idle"}, "Operator does not get in sync")
 | 
					            self.eventuallyEqual(lambda: k8s.get_operator_state(), {"0": "idle"}, "Operator does not get in sync")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # add annotations to manifest
 | 
					            # add annotations to manifest
 | 
				
			||||||
            delete_date = datetime.today().strftime('%Y-%m-%d')
 | 
					            delete_date = datetime.today().strftime('%Y-%m-%d')
 | 
				
			||||||
| 
						 | 
					@ -855,7 +857,7 @@ class EndToEndTestCase(unittest.TestCase):
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            k8s.api.custom_objects_api.patch_namespaced_custom_object(
 | 
					            k8s.api.custom_objects_api.patch_namespaced_custom_object(
 | 
				
			||||||
                "acid.zalan.do", "v1", "default", "postgresqls", "acid-minimal-cluster", pg_patch_delete_annotations)
 | 
					                "acid.zalan.do", "v1", "default", "postgresqls", "acid-minimal-cluster", pg_patch_delete_annotations)
 | 
				
			||||||
            self.eventuallyEqual(lambda: k8s.get_operator_state(), {"0":"idle"}, "Operator does not get in sync")
 | 
					            self.eventuallyEqual(lambda: k8s.get_operator_state(), {"0": "idle"}, "Operator does not get in sync")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # wait a little before proceeding
 | 
					            # wait a little before proceeding
 | 
				
			||||||
            time.sleep(20)
 | 
					            time.sleep(20)
 | 
				
			||||||
| 
						 | 
					@ -882,7 +884,7 @@ class EndToEndTestCase(unittest.TestCase):
 | 
				
			||||||
            print('Operator log: {}'.format(k8s.get_operator_log()))
 | 
					            print('Operator log: {}'.format(k8s.get_operator_log()))
 | 
				
			||||||
            raise
 | 
					            raise
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        #reset configmap
 | 
					        # reset configmap
 | 
				
			||||||
        patch_delete_annotations = {
 | 
					        patch_delete_annotations = {
 | 
				
			||||||
            "data": {
 | 
					            "data": {
 | 
				
			||||||
                "delete_annotation_date_key": "",
 | 
					                "delete_annotation_date_key": "",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -626,14 +626,14 @@ func (c *Cluster) Update(oldSpec, newSpec *acidv1.Postgresql) error {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}()
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if oldSpec.Spec.PostgresqlParam.PgVersion >= newSpec.Spec.PostgresqlParam.PgVersion {
 | 
						if oldSpec.Spec.PostgresqlParam.PgVersion > newSpec.Spec.PostgresqlParam.PgVersion {
 | 
				
			||||||
		c.logger.Warningf("postgresql version change(%q -> %q) has no effect",
 | 
							c.logger.Warningf("postgresql version change(%q -> %q) has no effect",
 | 
				
			||||||
			oldSpec.Spec.PostgresqlParam.PgVersion, newSpec.Spec.PostgresqlParam.PgVersion)
 | 
								oldSpec.Spec.PostgresqlParam.PgVersion, newSpec.Spec.PostgresqlParam.PgVersion)
 | 
				
			||||||
		c.eventRecorder.Eventf(c.GetReference(), v1.EventTypeWarning, "PostgreSQL", "postgresql version change(%q -> %q) has no effect",
 | 
							c.eventRecorder.Eventf(c.GetReference(), v1.EventTypeWarning, "PostgreSQL", "postgresql version change(%q -> %q) has no effect",
 | 
				
			||||||
			oldSpec.Spec.PostgresqlParam.PgVersion, newSpec.Spec.PostgresqlParam.PgVersion)
 | 
								oldSpec.Spec.PostgresqlParam.PgVersion, newSpec.Spec.PostgresqlParam.PgVersion)
 | 
				
			||||||
		// we need that hack to generate statefulset with the old version
 | 
							// we need that hack to generate statefulset with the old version
 | 
				
			||||||
		newSpec.Spec.PostgresqlParam.PgVersion = oldSpec.Spec.PostgresqlParam.PgVersion
 | 
							newSpec.Spec.PostgresqlParam.PgVersion = oldSpec.Spec.PostgresqlParam.PgVersion
 | 
				
			||||||
	} else {
 | 
						} else if oldSpec.Spec.PostgresqlParam.PgVersion < newSpec.Spec.PostgresqlParam.PgVersion {
 | 
				
			||||||
		c.logger.Infof("postgresql version increased (%q -> %q), major version upgrade can be done manually after StatefulSet Sync",
 | 
							c.logger.Infof("postgresql version increased (%q -> %q), major version upgrade can be done manually after StatefulSet Sync",
 | 
				
			||||||
			oldSpec.Spec.PostgresqlParam.PgVersion, newSpec.Spec.PostgresqlParam.PgVersion)
 | 
								oldSpec.Spec.PostgresqlParam.PgVersion, newSpec.Spec.PostgresqlParam.PgVersion)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue