diff --git a/cluster/local/integration_tests.sh b/cluster/local/integration_tests.sh index f7a197cf..99131406 100755 --- a/cluster/local/integration_tests.sh +++ b/cluster/local/integration_tests.sh @@ -40,6 +40,10 @@ eval $(make --no-print-directory -C ${projectdir} build.vars) # ------------------------------ +# Provide safe defaults for variables that may not be set by build.vars +: "${KIND_VERSION:=unknown}" +: "${KIND_NODE_IMAGE_TAG:=v1.23.4}" + SAFEHOSTARCH="${SAFEHOSTARCH:-amd64}" CONTROLLER_IMAGE="${BUILD_REGISTRY}/${PROJECT_NAME}-${SAFEHOSTARCH}" @@ -47,6 +51,13 @@ version_tag="$(cat ${projectdir}/_output/version)" # tag as latest version to load into kind cluster K8S_CLUSTER="${K8S_CLUSTER:-${BUILD_REGISTRY}-inttests}" +# Optional: set USE_OCI=true to use an in-cluster OCI registry for provider package delivery +# Modes: +# - USE_OCI=true => Push .xpkg into an in-cluster registry and install Provider from OCI (no host cache, no PVC) +# - USE_OCI=false => Extract .xpkg to .gz on host and mount as cache for Crossplane (offline local cache) +USE_OCI=${USE_OCI:-true} + + PACKAGE_NAME="provider-sql" MARIADB_ROOT_PW=$(openssl rand -base64 32) MARIADB_TEST_PW=$(openssl rand -base64 32) @@ -56,6 +67,12 @@ if [ "$skipcleanup" != true ]; then function cleanup { echo_step "Cleaning up..." export KUBECONFIG= + # stop port-forward if running + if [ -f "${projectdir}/.work/registry-pf.pid" ]; then + pfpid=$(cat "${projectdir}/.work/registry-pf.pid" || true) + if [ -n "$pfpid" ]; then kill "$pfpid" 2>/dev/null || true; fi + rm -f "${projectdir}/.work/registry-pf.pid" + fi cleanup_cluster } @@ -77,18 +94,33 @@ integration_tests_end() { } setup_cluster() { - echo_step "setting up local package cache" - + if [ "${USE_OCI}" = true ]; then + echo_sub_step "Mode: OCI (no host cache, no PVC)" + else + echo_sub_step "Mode: Local cache (.gz mounted via PV/PVC)" + fi local cache_path="${projectdir}/.work/inttest-package-cache" - mkdir -p "${cache_path}" - echo "created cache dir at ${cache_path}" - "${UP}" alpha xpkg xp-extract --from-xpkg "${OUTPUT_DIR}"/xpkg/linux_"${SAFEHOSTARCH}"/"${PACKAGE_NAME}"-"${VERSION}".xpkg -o "${cache_path}/${PACKAGE_NAME}.gz" - chmod 644 "${cache_path}/${PACKAGE_NAME}.gz" - local node_image="kindest/node:${KIND_NODE_IMAGE_TAG}" - echo_step "creating k8s cluster using kind ${KIND_VERSION} and node image ${node_image}" - local config="$( cat < .gz)" + mkdir -p "${cache_path}" + echo "created cache dir at ${cache_path}" + "${UP}" alpha xpkg xp-extract --from-xpkg "${OUTPUT_DIR}"/xpkg/linux_"${SAFEHOSTARCH}"/"${PACKAGE_NAME}"-"${VERSION}".xpkg -o "${cache_path}/${PACKAGE_NAME}-${VERSION}.gz" + chmod 644 "${cache_path}/${PACKAGE_NAME}-${VERSION}.gz" + + echo_step "creating k8s cluster (with cache mount) using kind ${KIND_VERSION} and ${node_image}" + local config="$( cat </dev/null 2>&1 & echo $! >"${projectdir}/.work/registry-pf.pid" ) + for i in {1..20}; do nc -z localhost 5000 && break || sleep 0.5; done +} + +push_xpkg_to_registry() { + [ "${USE_OCI}" = true ] || return 0 + echo_step "push xpkg to in-cluster registry" + local xpkg_path="${OUTPUT_DIR}/xpkg/linux_${SAFEHOSTARCH}/${PACKAGE_NAME}-${VERSION}.xpkg" + local ref_ver="localhost:5000/${PACKAGE_NAME}:${version_tag}" + local ref_latest="localhost:5000/${PACKAGE_NAME}:latest" + "${UP}" xpkg push ${ref_ver} -f "${xpkg_path}" + "${UP}" xpkg push ${ref_latest} -f "${xpkg_path}" + echo_info "pushed tags: ${ref_ver}, ${ref_latest}" } setup_provider() { echo_step "installing provider" - local yaml="$( cat </dev/null "${HELM}" repo update "${HELM}" install mariadb bitnami/mariadb \ - --version 11.3.0 \ + --version 24.0.2 \ --set auth.rootPassword="${MARIADB_ROOT_PW}" \ --wait } @@ -347,13 +497,13 @@ setup_mariadb_no_tls() { setup_mariadb_tls() { echo_step "installing MariaDB with TLS" "${KUBECTL}" create secret generic mariadb-creds \ - --from-literal username="test" \ - --from-literal password="${MARIADB_TEST_PW}" \ - --from-literal endpoint="mariadb.default.svc.cluster.local" \ - --from-literal port="3306" \ - --from-file=ca-cert.pem \ - --from-file=client-cert.pem \ - --from-file=client-key.pem + --from-literal=username="test" \ + --from-literal=password="${MARIADB_TEST_PW}" \ + --from-literal=endpoint="mariadb.default.svc.cluster.local" \ + --from-literal=port="3306" \ + --from-file=ca-cert.pem \ + --from-file=client-cert.pem \ + --from-file=client-key.pem local values=$(cat </dev/null "${HELM}" repo update "${HELM}" install mariadb bitnami/mariadb \ - --version 11.3.0 \ + --version 24.0.2 \ --values <(echo "$values") \ --wait } @@ -459,6 +609,8 @@ cleanup_test_resources() { setup_cluster setup_crossplane +setup_local_registry +push_xpkg_to_registry setup_provider echo_step "--- INTEGRATION TESTS - NO TLS ---" diff --git a/cluster/local/postgresdb_functions.sh b/cluster/local/postgresdb_functions.sh index b909f8b4..5d02bd85 100644 --- a/cluster/local/postgresdb_functions.sh +++ b/cluster/local/postgresdb_functions.sh @@ -3,22 +3,62 @@ 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/null 2>&1 || true "${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 | grep -v "Handling connection for" & + echo_sub_step "Helm repo add/update done" + echo_step_completed + # Install or upgrade to tolerate re-runs; increase verbosity and timeout + echo_sub_step "Helm upgrade --install bitnami/postgresql (no persistence)" + set +e + "${HELM}" upgrade --install postgresdb bitnami/postgresql \ + --version 18.2.0 \ + --set auth.postgresPassword="${postgres_root_pw}" \ + --set primary.persistence.enabled=false \ + --wait \ + --timeout 10m \ + --debug + rc=$? + set -e + if [ $rc -ne 0 ]; then + echo_info "Helm install failed. Dumping diagnostics..." + "${KUBECTL}" get all -A || true + "${KUBECTL}" get events --sort-by=.lastTimestamp | tail -n 200 || true + "${HELM}" status postgresdb || true + echo_error "Helm install/upgrade of PostgresDB failed" + fi + echo_step_completed + + echo_sub_step "Create connection secret postgresdb-creds" + "${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" + echo_step_completed + + # Start port-forward; ignore output filtering failures under pipefail + echo_sub_step "Start port-forward to svc/postgresdb-postgresql:5432" + ( "${KUBECTL}" port-forward --namespace default svc/postgresdb-postgresql 5432:5432 | grep -v "Handling connection for" || true ) & PORT_FORWARD_PID=$! + # Wait for local port to be ready + for i in {1..20}; do + if nc -z 127.0.0.1 5432 >/dev/null 2>&1; then + echo_sub_step "Port-forward ready (PID: ${PORT_FORWARD_PID})" + echo_step_completed + break + fi + sleep 0.5 + if [ $i -eq 20 ]; then + echo_error "Port-forward to PostgreSQL did not become ready" + fi + done } setup_provider_config_postgres_no_tls() { @@ -38,6 +78,7 @@ spec: EOF )" echo "${yaml}" | "${KUBECTL}" apply -f - + echo_step_completed } create_grantable_objects() { @@ -341,7 +382,9 @@ delete_postgresdb_resources(){ "${KUBECTL}" delete --ignore-not-found=true -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 - + if [ -n "${PROVIDER_CONFIG_POSTGRES_YAML:-}" ]; then + echo "${PROVIDER_CONFIG_POSTGRES_YAML}" | "${KUBECTL}" delete -f - + fi # ----------- cleaning postgres related resources diff --git a/cmd/provider/main.go b/cmd/provider/main.go index 300a4eb6..7694e4ea 100644 --- a/cmd/provider/main.go +++ b/cmd/provider/main.go @@ -27,6 +27,7 @@ import ( "github.com/alecthomas/kingpin/v2" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/cache" + "sigs.k8s.io/controller-runtime/pkg/config" "sigs.k8s.io/controller-runtime/pkg/log/zap" xpcontroller "github.com/crossplane/crossplane-runtime/pkg/controller" @@ -47,6 +48,7 @@ func main() { leaderElection = app.Flag("leader-election", "Use leader election for the controller manager.").Short('l').Default("false").Envar("LEADER_ELECTION").Bool() maxReconcileRate = app.Flag("max-reconcile-rate", "The global maximum rate per second at which resources may checked for drift from the desired state.").Default("10").Int() enableManagementPolicies = app.Flag("enable-management-policies", "Enable/disable support for Management Policies.").Default("true").Envar("ENABLE_MANAGEMENT_POLICIES").Bool() + cacheSyncTimeout = app.Flag("cache-sync-timeout", "Timeout for controller caches to sync with the Kubernetes API server on startup.").Default("2m").Envar("CACHE_SYNC_TIMEOUT").Duration() ) kingpin.MustParse(app.Parse(os.Args[1:])) @@ -70,6 +72,9 @@ func main() { Cache: cache.Options{ SyncPeriod: syncPeriod, }, + Controller: config.Controller{ + CacheSyncTimeout: *cacheSyncTimeout, + }, }) kingpin.FatalIfError(err, "Cannot create controller manager") kingpin.FatalIfError(apis.AddToScheme(mgr.GetScheme()), "Cannot add SQL APIs to scheme")