Skip to content

Commit

Permalink
test(postgresql): implement postgresdb integration tests (#208)
Browse files Browse the repository at this point in the history
Signed-off-by: oliver.zokra <[email protected]>
  • Loading branch information
olikyr authored Jan 13, 2025
1 parent fcd50ac commit d0c080b
Show file tree
Hide file tree
Showing 6 changed files with 254 additions and 4 deletions.
23 changes: 20 additions & 3 deletions cluster/local/integration_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,20 @@ if [ "$skipcleanup" != true ]; then
trap cleanup EXIT
fi

SCRIPT_DIR="$(dirname "$(realpath "$0")")"
# shellcheck source="$SCRIPT_DIR/postgresdb_functions.sh"
source "$SCRIPT_DIR/postgresdb_functions.sh"
if [ $? -ne 0 ]; then
echo "postgresdb_functions.sh failed. Exiting."
exit 1
fi

integration_tests_end() {
echo_step "--- CLEAN-UP ---"
cleanup_provider
echo_success " All integration tests succeeded!"
}

setup_cluster() {
echo_step "setting up local package cache"

Expand Down Expand Up @@ -469,7 +483,10 @@ cleanup_provider_config
cleanup_mariadb
cleanup_tls_certs

echo_step "--- CLEAN-UP ---"
cleanup_provider
echo_step "--- INTEGRATION TESTS FOR MySQL ACCOMPLISHED SUCCESSFULLY ---"

echo_step "--- TESTING POSTGRESDB ---"
integration_tests_postgres
echo_step "--- INTEGRATION TESTS FOR POSTGRESDB ACCOMPLISHED SUCCESSFULLY ---"

echo_success "Integration tests succeeded!"
integration_tests_end
167 changes: 167 additions & 0 deletions cluster/local/postgresdb_functions.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
#!/usr/bin/env bash
set -e

setup_postgresdb_no_tls() {
echo_step "Installing PostgresDB Helm chart into default namespace"
postgres_root_pw=$(LC_ALL=C tr -cd "A-Za-z0-9" </dev/urandom | head -c 32)

"${HELM}" repo update
"${HELM}" install postgresdb bitnami/postgresql \
--version 11.9.1 \
--set global.postgresql.auth.postgresPassword="${postgres_root_pw}" \
--wait

"${KUBECTL}" create secret generic postgresdb-creds \
--from-literal username="postgres" \
--from-literal password="${postgres_root_pw}" \
--from-literal endpoint="postgresdb-postgresql.default.svc.cluster.local" \
--from-literal port="5432"

"${KUBECTL}" port-forward --namespace default svc/postgresdb-postgresql 5432:5432 &
PORT_FORWARD_PID=$!
}

setup_provider_config_postgres_no_tls() {
echo_step "creating ProviderConfig for PostgresDb with no TLS"
local yaml="$( cat <<EOF
apiVersion: postgresql.sql.crossplane.io/v1alpha1
kind: ProviderConfig
metadata:
name: default
spec:
sslMode: disable
credentials:
source: PostgreSQLConnectionSecret
connectionSecretRef:
namespace: default
name: postgresdb-creds
EOF
)"
echo "${yaml}" | "${KUBECTL}" apply -f -
}

setup_postgresdb_tests(){
# install provider resources
echo_step "creating PostgresDB Database resource"
# create DB
"${KUBECTL}" apply -f ${projectdir}/examples/postgresql/database.yaml

echo_step "creating PostgresDB Role resource"
# create grant
"${KUBECTL}" apply -f ${projectdir}/examples/postgresql/role.yaml

echo_step "creating PostgresDB Grant resource"
# create grant
"${KUBECTL}" apply -f ${projectdir}/examples/postgresql/grant.yaml

echo_step "creating PostgresDB Schema resources"
# create grant
"${KUBECTL}" apply -f ${projectdir}/examples/postgresql/schema.yaml

echo_step "check if Role is ready"
"${KUBECTL}" wait --timeout 2m --for condition=Ready -f ${projectdir}/examples/postgresql/role.yaml
echo_step_completed

echo_step "check if database is ready"
"${KUBECTL}" wait --timeout 2m --for condition=Ready -f ${projectdir}/examples/postgresql/database.yaml
echo_step_completed

echo_step "check if grant is ready"
"${KUBECTL}" wait --timeout 2m --for condition=Ready -f ${projectdir}/examples/postgresql/grant.yaml
echo_step_completed

echo_step "check if schema is ready"
"${KUBECTL}" wait --timeout 2m --for condition=Ready -f ${projectdir}/examples/postgresql/schema.yaml
echo_step_completed
}

check_all_roles_privileges() {
# check if granting mechanism is working properly
echo_step "check if grant mechanism is working"

TARGET_DB='db1'
OWNER_ROLE='ownerrole'
USER_ROLE='example-role'

# Define roles and their expected privileges
roles="$OWNER_ROLE $USER_ROLE"
privileges="CONNECT|CREATE|TEMP ||"

# Iterate over roles and expected privileges
role_index=1
for role in $roles; do
expected_privileges=$(echo "$privileges" | cut -d ' ' -f $role_index)
check_role_privileges "$role" "$expected_privileges" "${postgres_root_pw}" "$TARGET_DB"
role_index=$((role_index + 1))
done

echo_step_completed
}

check_role_privileges() {
local role=$1
local expected_privileges=$2
local target_db=$4

echo_info "Checking privileges for role: $role (expected: $expected_privileges)"
echo ""
result=$(PGPASSWORD="$3" psql -h localhost -p 5432 -U postgres -d postgres -wtAc" SELECT CASE WHEN has_database_privilege('$role', '$target_db', 'CONNECT') THEN 'CONNECT' ELSE NULL END, CASE WHEN has_database_privilege('$role', '$target_db', 'CREATE') THEN 'CREATE' ELSE NULL END, CASE WHEN has_database_privilege('$role', '$target_db', 'TEMP') THEN 'TEMP' ELSE NULL END " | tr '\n' ',' | sed 's/,$//')

if [ "$result" = "$expected_privileges" ]; then
echo_info "Privileges for $role are as expected: $result"
echo ""
else
echo_error "ERROR: Privileges for $role do not match expected. Found: $result, Expected: $expected_privileges"
echo ""
fi
}

check_schema_privileges(){
# check if schema privileges are set properly
echo_step "check if schema privileges are set properly"

TARGET_DB='db1'

nspacl=$(PGPASSWORD="${postgres_root_pw}" psql -h localhost -p 5432 -U postgres -d "$TARGET_DB" -wtAc "SELECT nspacl FROM pg_namespace WHERE nspname = 'public';")
nspacl=$(echo "$nspacl" | xargs)

if [[ "$nspacl" == "{ownerrole=UC/ownerrole}" ]]; then
echo "Privileges on schema public are as expected: $nspacl"
echo_info "OK"
else
echo "Privileges on schema public are NOT as expected: $nspacl"
echo_error "Not OK"
fi

echo_step_completed
}

delete_postgresdb_resources(){
# uninstall
echo_step "uninstalling ${PROJECT_NAME}"
"${KUBECTL}" delete -f ${projectdir}/examples/postgresql/grant.yaml
"${KUBECTL}" delete -f ${projectdir}/examples/postgresql/database.yaml
"${KUBECTL}" delete -f ${projectdir}/examples/postgresql/role.yaml
"${KUBECTL}" delete -f ${projectdir}/examples/postgresql/schema.yaml
echo "${PROVIDER_CONFIG_POSTGRES_YAML}" | "${KUBECTL}" delete -f -

# ----------- cleaning postgres related resources

echo_step "kill port-forwarding"
kill $PORT_FORWARD_PID

echo_step "uninstalling secret and provider config for postgres"
"${KUBECTL}" delete secret postgresdb-creds

echo_step "Uninstalling PostgresDB Helm chart from default namespace"
"${HELM}" uninstall postgresdb
}

integration_tests_postgres() {
setup_postgresdb_no_tls
setup_provider_config_postgres_no_tls
setup_postgresdb_tests
check_all_roles_privileges
check_schema_privileges
delete_postgresdb_resources
}
10 changes: 10 additions & 0 deletions examples/postgresql/database.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,13 @@ metadata:
name: example
spec:
forProvider: {}
---
apiVersion: postgresql.sql.crossplane.io/v1alpha1
kind: Database
metadata:
name: db1
spec:
deletionPolicy: Orphan
forProvider:
allowConnections: true
owner: "ownerrole"
27 changes: 27 additions & 0 deletions examples/postgresql/grant.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,30 @@ spec:
name: example-role
memberOfRef:
name: parent-role
---
apiVersion: postgresql.sql.crossplane.io/v1alpha1
kind: Grant
metadata:
name: grant-postgres-an-owner-role
spec:
deletionPolicy: Orphan
forProvider:
role: "postgres"
memberOfRef:
name: "ownerrole"
---
apiVersion: postgresql.sql.crossplane.io/v1alpha1
kind: Grant
metadata:
name: grant-owner-role-privilege-connect
spec:
deletionPolicy: Orphan
forProvider:
withOption: "GRANT"
privileges:
- CONNECT
roleRef:
name: "ownerrole"
databaseRef:
name: "db1"
revokePublicOnDb: true
17 changes: 16 additions & 1 deletion examples/postgresql/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ spec:
value: '123'
- name: 'search_path'
value: '"$user",public'

writeConnectionSecretToRef:
name: example-parent-role-secret
namespace: default
Expand All @@ -28,3 +27,19 @@ spec:
writeConnectionSecretToRef:
name: example-role-secret
namespace: default
---
apiVersion: postgresql.sql.crossplane.io/v1alpha1
kind: Role
metadata:
name: ownerrole
spec:
deletionPolicy: Orphan
writeConnectionSecretToRef:
name: ownerrole-secret
namespace: default
forProvider:
privileges:
createDb: true
login: true
createRole: true
inherit: true
14 changes: 14 additions & 0 deletions examples/postgresql/schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,17 @@ spec:
name: example-role
providerConfigRef:
name: default
---
apiVersion: postgresql.sql.crossplane.io/v1alpha1
kind: Schema
metadata:
name: public
spec:
forProvider:
revokePublicOnSchema: true
databaseRef:
name: db1
roleRef:
name: ownerrole
providerConfigRef:
name: default

0 comments on commit d0c080b

Please sign in to comment.