diff --git a/e2e-tests/run-pr.csv b/e2e-tests/run-pr.csv index 5b5bd09ba..df3c5d6d9 100644 --- a/e2e-tests/run-pr.csv +++ b/e2e-tests/run-pr.csv @@ -28,6 +28,7 @@ pgbouncer-mtls pg-tde pg-tde-wal-encrypt pitr +postgis scaling scheduled-backup self-healing diff --git a/e2e-tests/run-release.csv b/e2e-tests/run-release.csv index 0278ec4f5..64e629601 100644 --- a/e2e-tests/run-release.csv +++ b/e2e-tests/run-release.csv @@ -33,6 +33,7 @@ pgbouncer-mtls pg-tde pg-tde-wal-encrypt pitr +postgis scaling scheduled-backup self-healing diff --git a/e2e-tests/tests/postgis/00-assert.yaml b/e2e-tests/tests/postgis/00-assert.yaml new file mode 100644 index 000000000..ae5a062d8 --- /dev/null +++ b/e2e-tests/tests/postgis/00-assert.yaml @@ -0,0 +1,24 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: perconapgclusters.pgv2.percona.com +spec: + group: pgv2.percona.com + names: + kind: PerconaPGCluster + listKind: PerconaPGClusterList + plural: perconapgclusters + singular: perconapgcluster + scope: Namespaced +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +metadata: + name: check-operator-deploy-status +timeout: 120 +commands: + - script: kubectl assert exist-enhanced deployment percona-postgresql-operator -n ${OPERATOR_NS:-$NAMESPACE} --field-selector status.readyReplicas=1 diff --git a/e2e-tests/tests/postgis/00-deploy-operator.yaml b/e2e-tests/tests/postgis/00-deploy-operator.yaml new file mode 100644 index 000000000..1aaca58be --- /dev/null +++ b/e2e-tests/tests/postgis/00-deploy-operator.yaml @@ -0,0 +1,13 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 10 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + init_temp_dir # do this only in the first TestStep + + deploy_operator + deploy_client diff --git a/e2e-tests/tests/postgis/01-assert.yaml b/e2e-tests/tests/postgis/01-assert.yaml new file mode 100644 index 000000000..832d4c360 --- /dev/null +++ b/e2e-tests/tests/postgis/01-assert.yaml @@ -0,0 +1,115 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 180 +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + name: postgis-repo-host + labels: + postgres-operator.crunchydata.com/cluster: postgis + postgres-operator.crunchydata.com/data: pgbackrest + postgres-operator.crunchydata.com/pgbackrest: '' + postgres-operator.crunchydata.com/pgbackrest-dedicated: '' + ownerReferences: + - apiVersion: upstream.pgv2.percona.com/v1beta1 + kind: PostgresCluster + name: postgis + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 1 + readyReplicas: 1 + currentReplicas: 1 + updatedReplicas: 1 + collisionCount: 0 +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: postgis + postgres-operator.crunchydata.com/data: postgres + postgres-operator.crunchydata.com/instance-set: instance1 + ownerReferences: + - apiVersion: upstream.pgv2.percona.com/v1beta1 + kind: PostgresCluster + name: postgis + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 1 + readyReplicas: 1 + currentReplicas: 1 + updatedReplicas: 1 + collisionCount: 0 +--- +kind: Deployment +apiVersion: apps/v1 +metadata: + name: postgis-pgbouncer + labels: + postgres-operator.crunchydata.com/cluster: postgis + postgres-operator.crunchydata.com/role: pgbouncer + ownerReferences: + - apiVersion: upstream.pgv2.percona.com/v1beta1 + kind: PostgresCluster + name: postgis + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 3 + updatedReplicas: 3 + readyReplicas: 3 +--- +apiVersion: upstream.pgv2.percona.com/v1beta1 +kind: PostgresCluster +metadata: + name: postgis + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: postgis + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 3 + replicas: 3 + updatedReplicas: 3 + observedGeneration: 1 + pgbackrest: + repoHost: + apiVersion: apps/v1 + kind: StatefulSet + ready: true + repos: + - bound: true + name: repo1 + proxy: + pgBouncer: + readyReplicas: 3 + replicas: 3 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: postgis +status: + pgbouncer: + ready: 3 + size: 3 + postgres: + instances: + - name: instance1 + ready: 3 + size: 3 + ready: 3 + size: 3 + state: ready diff --git a/e2e-tests/tests/postgis/01-create-cluster.yaml b/e2e-tests/tests/postgis/01-create-cluster.yaml new file mode 100644 index 000000000..7b2effb26 --- /dev/null +++ b/e2e-tests/tests/postgis/01-create-cluster.yaml @@ -0,0 +1,12 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 100 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + postgres_image=$(get_container_image "postgis" "${PG_VER}") + get_cr | yq eval ".spec.image = \"${postgres_image}\"" - | kubectl -n "${NAMESPACE}" apply -f - diff --git a/e2e-tests/tests/postgis/02-assert.yaml b/e2e-tests/tests/postgis/02-assert.yaml new file mode 100644 index 000000000..24c6cb593 --- /dev/null +++ b/e2e-tests/tests/postgis/02-assert.yaml @@ -0,0 +1,28 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +apiVersion: upstream.pgv2.percona.com/v1beta1 +kind: PostgresCluster +metadata: + name: postgis +status: + instances: + - name: instance1 + readyReplicas: 3 + replicas: 3 + updatedReplicas: 3 + pgbackrest: + repoHost: + ready: true + proxy: + pgBouncer: + readyReplicas: 3 + replicas: 3 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: postgis +status: + state: ready diff --git a/e2e-tests/tests/postgis/02-enable-postgis.yaml b/e2e-tests/tests/postgis/02-enable-postgis.yaml new file mode 100644 index 000000000..2d2f802fe --- /dev/null +++ b/e2e-tests/tests/postgis/02-enable-postgis.yaml @@ -0,0 +1,23 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 360 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + PSQL_URI="postgres:$(get_psql_user_pass postgis-pguser-postgres)@$(get_psql_user_host postgis-pguser-postgres)/postgres" + + # Create a second DB before enable so auto-install covers both databases. + run_psql_local "CREATE DATABASE mygisdata;" "${PSQL_URI}" + + # Patch the underlying PostgresCluster to enable PostGIS. + # The Percona operator does not override postGISVersion on reconcile, + # so this setting is preserved and triggers PostGIS extension installation. + kubectl -n "${NAMESPACE}" patch postgrescluster postgis \ + --type=merge \ + --patch "{\"spec\":{\"postGISVersion\":\"${POSTGIS_VER}\"}}" + + wait_cluster_consistency postgis diff --git a/e2e-tests/tests/postgis/03-assert.yaml b/e2e-tests/tests/postgis/03-assert.yaml new file mode 100644 index 000000000..31df54b10 --- /dev/null +++ b/e2e-tests/tests/postgis/03-assert.yaml @@ -0,0 +1,16 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 30 +--- +kind: ConfigMap +apiVersion: v1 +metadata: + name: 03-check-postgis +data: + extensions_postgres: fuzzystrmatch,postgis,postgis_tiger_geocoder,postgis_topology + extensions_mygisdata: fuzzystrmatch,postgis,postgis_tiger_geocoder,postgis_topology + schemas: tiger,topology + geometry: geometry + geojson: '{"type":"Point","coordinates":[-118.4079,33.9434]}' + version_matches: "true" + image_is_gis: "true" diff --git a/e2e-tests/tests/postgis/03-check-postgis.yaml b/e2e-tests/tests/postgis/03-check-postgis.yaml new file mode 100644 index 000000000..cc2575f38 --- /dev/null +++ b/e2e-tests/tests/postgis/03-check-postgis.yaml @@ -0,0 +1,73 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 180 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + BASE_URI="postgres:$(get_psql_user_pass postgis-pguser-postgres)@$(get_psql_user_host postgis-pguser-postgres)" + + select_matching() { + local db=$1 + local sql=$2 + local pattern=$3 + + run_psql_local "${sql}" "${BASE_URI}/${db}" \ + | tr -d '[:blank:]' | grep -E "${pattern}" | sort | paste -sd, - + } + + get_extensions() { + select_matching "$1" \ + "SELECT extname FROM pg_extension ORDER BY extname;" \ + '^(fuzzystrmatch|postgis|postgis_tiger_geocoder|postgis_topology)$' + } + + check_extensions() { + [[ "$(get_extensions "$1")" == "fuzzystrmatch,postgis,postgis_tiger_geocoder,postgis_topology" ]] + } + + retry 24 5 check_extensions postgres + retry 24 5 check_extensions mygisdata + + extensions_postgres=$(get_extensions postgres) + extensions_mygisdata=$(get_extensions mygisdata) + + schemas=$(select_matching postgres \ + "SELECT nspname FROM pg_catalog.pg_namespace ORDER BY nspname;" \ + '^(tiger|topology)$') + + geometry=$(run_psql_local \ + "SELECT pg_typeof(ST_MakePoint(28.385200,-81.563900));" \ + "${BASE_URI}/postgres" | tr -d '[:space:]') + + geojson=$(run_psql_local \ + "SELECT ST_AsGeoJSON(ST_SetSRID(ST_MakePoint(-118.4079,33.9434),4326)::geography);" \ + "${BASE_URI}/postgres" | tr -d '[:space:]') + + version=$(run_psql_local \ + "SELECT left(postgis_version(),1);" \ + "${BASE_URI}/postgres" | tr -d '[:space:]') + spec_version=$(kubectl -n "${NAMESPACE}" get postgrescluster postgis -o jsonpath='{.spec.postGISVersion}') + version_matches=false + if [[ "${spec_version}" == "${POSTGIS_VER}" && "${version}" == "${POSTGIS_VER:0:1}" ]]; then + version_matches=true + fi + + primary=$(get_pod_by_role postgis primary name) + image=$(kubectl -n "${NAMESPACE}" get pod "${primary}" -o jsonpath='{.spec.containers[?(@.name=="database")].image}') + image_is_gis=false + if [[ "${image}" == *postgres-gis* ]]; then + image_is_gis=true + fi + + kubectl create configmap -n "${NAMESPACE}" 03-check-postgis \ + --from-literal=extensions_postgres="${extensions_postgres}" \ + --from-literal=extensions_mygisdata="${extensions_mygisdata}" \ + --from-literal=schemas="${schemas}" \ + --from-literal=geometry="${geometry}" \ + --from-literal=geojson="${geojson}" \ + --from-literal=version_matches="${version_matches}" \ + --from-literal=image_is_gis="${image_is_gis}" diff --git a/e2e-tests/tests/postgis/99-remove-cluster-gracefully.yaml b/e2e-tests/tests/postgis/99-remove-cluster-gracefully.yaml new file mode 100644 index 000000000..664de1d0e --- /dev/null +++ b/e2e-tests/tests/postgis/99-remove-cluster-gracefully.yaml @@ -0,0 +1,22 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +delete: +- apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + metadata: + name: postgis +- apiVersion: upstream.pgv2.percona.com/v1beta1 + kind: PostgresCluster + metadata: + name: postgis +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + remove_all_finalizers + check_operator_panic + destroy_operator + timeout: 60 diff --git a/e2e-tests/vars.sh b/e2e-tests/vars.sh index 635a90d79..ec63bac5f 100755 --- a/e2e-tests/vars.sh +++ b/e2e-tests/vars.sh @@ -56,6 +56,8 @@ export PMM_SERVER_VERSION=${PMM_SERVER_VERSION:-"9.9.9"} export IMAGE_PMM_CLIENT=${IMAGE_PMM_CLIENT:-"perconalab/pmm-client:3-dev-latest"} export IMAGE_PMM_SERVER=${IMAGE_PMM_SERVER:-"perconalab/pmm-server:3-dev-latest"} export IMAGE_LOGCOLLECTOR=${IMAGE_LOGCOLLECTOR:-"perconalab/fluentbit:main-logcollector"} +export IMAGE_POSTGIS=${IMAGE_POSTGIS:-"${IMAGE_BASE}:main-ppg$PG_VER-postgres-gis"} +export POSTGIS_VER=${POSTGIS_VER:-"3.3"} export PGOV1_TAG=${PGOV1_TAG:-"1.4.0"} export PGOV1_VER=${PGOV1_VER:-"14"} export CPGO_VERSION=${CPGO_VERSION:-"5.8.7"}