From dcebb23c3fdfae952a361e72dd89ffc736ff5d3b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 May 2025 07:10:41 +0200 Subject: [PATCH 01/10] Bump google.golang.org/protobuf from 1.31.0 to 1.33.0 (#232) Bumps google.golang.org/protobuf from 1.31.0 to 1.33.0. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-version: 1.33.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Alan Caldera <30800723+ajcaldera1@users.noreply.github.com> --- go.sum | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/go.sum b/go.sum index e3991144..4ee9a4e9 100644 --- a/go.sum +++ b/go.sum @@ -232,6 +232,11 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +<<<<<<< HEAD +======= +gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +>>>>>>> 89a2c8e (Bump google.golang.org/protobuf from 1.31.0 to 1.33.0 (#232)) gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= From 38a8227db59c4bc6ed6c75bd9b73ef98fac26a62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=2E=20Fern=C3=A1ndez?= <7312236+fernandezcuesta@users.noreply.github.com> Date: Thu, 8 May 2025 19:49:55 +0000 Subject: [PATCH 02/10] fix: enable management policies (#215) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: enable management policies Signed-off-by: Jesús Fernández <7312236+fernandezcuesta@users.noreply.github.com> * fix: linter Signed-off-by: Jesús Fernández <7312236+fernandezcuesta@users.noreply.github.com> * chore: offload lint changes to #216 Signed-off-by: Jesús Fernández <7312236+fernandezcuesta@users.noreply.github.com> * chore: revert changes as per peer review Signed-off-by: Jesús Fernández <7312236+fernandezcuesta@users.noreply.github.com> --------- Signed-off-by: Jesús Fernández <7312236+fernandezcuesta@users.noreply.github.com> Signed-off-by: Alan Caldera <30800723+ajcaldera1@users.noreply.github.com> --- go.sum | 3 +++ 1 file changed, 3 insertions(+) diff --git a/go.sum b/go.sum index 4ee9a4e9..d2e756ec 100644 --- a/go.sum +++ b/go.sum @@ -233,10 +233,13 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= <<<<<<< HEAD +<<<<<<< HEAD ======= gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= >>>>>>> 89a2c8e (Bump google.golang.org/protobuf from 1.31.0 to 1.33.0 (#232)) +======= +>>>>>>> 78b4165 (fix: enable management policies (#215)) gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= From ca497d4243cb04b75b50d4fddc20a16357c1879b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=2E=20Fern=C3=A1ndez?= <7312236+fernandezcuesta@users.noreply.github.com> Date: Thu, 22 May 2025 12:59:59 +0200 Subject: [PATCH 03/10] chore: remove duplicate entry of golangci version (#236) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: remove duplicate entry of golangci version Signed-off-by: Jesús Fernández <7312236+fernandezcuesta@users.noreply.github.com> * chore: bump up versions for crossplane 1.20 Signed-off-by: Jesús Fernández <7312236+fernandezcuesta@users.noreply.github.com> * chore: restore changes Signed-off-by: Jesús Fernández <7312236+fernandezcuesta@users.noreply.github.com> --------- Signed-off-by: Jesús Fernández <7312236+fernandezcuesta@users.noreply.github.com> Signed-off-by: Alan Caldera <30800723+ajcaldera1@users.noreply.github.com> --- Makefile | 9 +++++---- cluster/local/integration_tests.sh | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 95926214..715600c7 100644 --- a/Makefile +++ b/Makefile @@ -23,18 +23,19 @@ NPROCS ?= 1 # to half the number of CPU cores. GO_TEST_PARALLEL := $(shell echo $$(( $(NPROCS) / 2 ))) -GOLANGCILINT_VERSION ?= 1.63.4 +GOLANGCILINT_VERSION ?= 2.1.2 GO_STATIC_PACKAGES = $(GO_PROJECT)/cmd/provider GO_LDFLAGS += -X $(GO_PROJECT)/pkg/version.Version=$(VERSION) GO_SUBDIRS += cmd pkg apis GO111MODULE = on -GOLANGCILINT_VERSION = 2.1.2 -include build/makelib/golang.mk # ==================================================================================== # Setup Kubernetes tools -KIND_NODE_IMAGE_TAG ?= v1.23.4 -DOCKER_REGISTRY ?= "xpkg.upbound.io" +KIND_NODE_IMAGE_TAG ?= v1.30.13 +KIND_VERSION ?= v0.29.0 +KUBECTL_VERSION ?= v1.30.13 +CROSSPLANE_CLI_VERSION ?= v1.20.0 -include build/makelib/k8s_tools.mk # ==================================================================================== diff --git a/cluster/local/integration_tests.sh b/cluster/local/integration_tests.sh index 4b0585e7..e8669b78 100755 --- a/cluster/local/integration_tests.sh +++ b/cluster/local/integration_tests.sh @@ -102,8 +102,8 @@ EOF echo_step "tag controller image and load it into kind cluster" - docker tag "${CONTROLLER_IMAGE}" "xpkg.upbound.io/${PACKAGE_NAME}" - "${KIND}" load docker-image "xpkg.upbound.io/${PACKAGE_NAME}" --name="${K8S_CLUSTER}" + docker tag "${CONTROLLER_IMAGE}" "xpkg.crossplane.io/${PACKAGE_NAME}" + "${KIND}" load docker-image "xpkg.crossplane.io/${PACKAGE_NAME}" --name="${K8S_CLUSTER}" echo_step "create crossplane-system namespace" From e60b95eb2636e83599079b1f0ea3edccfd9cdc6d Mon Sep 17 00:00:00 2001 From: Alan Caldera <30800723+ajcaldera1@users.noreply.github.com> Date: Wed, 21 May 2025 14:56:00 -0400 Subject: [PATCH 04/10] Added new code to check the existing state of rolconnlimit in database before mutating it. This will help cut down the number of ALTER ROLE statements that would otherwise needlessly fire for each role. Signed-off-by: Alan Caldera <30800723+ajcaldera1@users.noreply.github.com> --- apis/postgresql/v1alpha1/role_types.go | 2 + .../v1alpha1/zz_generated.deepcopy.go | 5 +++ cluster/local/postgresdb_functions.sh | 43 ++++++++++++++++++- examples/postgresql/role.yaml | 32 +++++++++++++- .../postgresql.sql.crossplane.io_roles.yaml | 4 ++ pkg/controller/postgresql/role/reconciler.go | 10 +++-- 6 files changed, 91 insertions(+), 5 deletions(-) diff --git a/apis/postgresql/v1alpha1/role_types.go b/apis/postgresql/v1alpha1/role_types.go index 749ec159..f73ec84f 100644 --- a/apis/postgresql/v1alpha1/role_types.go +++ b/apis/postgresql/v1alpha1/role_types.go @@ -100,6 +100,8 @@ type RoleConfigurationParameter struct { // A RoleObservation represents the observed state of a PostgreSQL role. type RoleObservation struct { + // ConnectionLimit represents the applied connectionlimit + ConnectionLimit *int32 `json:"connectionLimit,omitempty"` // PrivilegesAsClauses represents the applied privileges state, taking into account // any defaults applied by Postgres, and expressed as a list of ROLE PRIVILEGE clauses. PrivilegesAsClauses []string `json:"privilegesAsClauses,omitempty"` diff --git a/apis/postgresql/v1alpha1/zz_generated.deepcopy.go b/apis/postgresql/v1alpha1/zz_generated.deepcopy.go index 70d15187..ebe8708a 100644 --- a/apis/postgresql/v1alpha1/zz_generated.deepcopy.go +++ b/apis/postgresql/v1alpha1/zz_generated.deepcopy.go @@ -746,6 +746,11 @@ func (in *RoleList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RoleObservation) DeepCopyInto(out *RoleObservation) { *out = *in + if in.ConnectionLimit != nil { + in, out := &in.ConnectionLimit, &out.ConnectionLimit + *out = new(int32) + **out = **in + } if in.PrivilegesAsClauses != nil { in, out := &in.PrivilegesAsClauses, &out.PrivilegesAsClauses *out = make([]string, len(*in)) diff --git a/cluster/local/postgresdb_functions.sh b/cluster/local/postgresdb_functions.sh index 4a64c7e2..815905dc 100644 --- a/cluster/local/postgresdb_functions.sh +++ b/cluster/local/postgresdb_functions.sh @@ -116,6 +116,46 @@ check_role_privileges() { fi } +check_all_conn_limits() { + # check if the role connection limit is working properly + echo_step "check if role connection update is working" + + TARGET_DB='db1' + PARENT_ROLE='parent-role' + USER_ROLE='example-role' + + roles="$PARENT_ROLE $USER_ROLE" + conn_limits="12 -1" + + # Iterate over roles and expected connection limits + role_index=1 + for role in $roles; do + expected_limits=$(echo "$conn_limits" | cut -d ' ' -f $role_index) + check_role_limits "$role" "$expected_limits" "${postgres_root_pw}" "$TARGET_DB" + role_index=$((role_index + 1)) + done + + echo_step_completed +} + +check_role_limits() { + local role=$1 + local expected_limits=$2 + local target_db=$4 + + echo_info "Checking connection limits for role: $role (expected: $expected_limits)" + echo "" + result=$(PGPASSWORD="$3" psql -h localhost -p 5432 -U postgres -d postgres -wtAc" SELECT rolconnlimit FROM pg_roles WHERE rolname = '$role' " | tr '\n' ',' | sed 's/,$//') + + if [ "$result" = "$expected_limits" ]; then + echo_info "Connection limits for $role are as expected: $result" + echo "" + else + echo_error "ERROR: Connection limits for $role do not match expected. Found: $result, Expected: $expected_limits" + echo "" + fi +} + check_schema_privileges(){ # check if schema privileges are set properly echo_step "check if schema privileges are set properly" @@ -196,6 +236,7 @@ integration_tests_postgres() { setup_postgresdb_tests check_observe_only_database check_all_roles_privileges + check_all_conn_limits check_schema_privileges delete_postgresdb_resources -} \ No newline at end of file +} diff --git a/examples/postgresql/role.yaml b/examples/postgresql/role.yaml index 5f07914c..038b054c 100644 --- a/examples/postgresql/role.yaml +++ b/examples/postgresql/role.yaml @@ -42,4 +42,34 @@ spec: createDb: true login: true createRole: true - inherit: true \ No newline at end of file + inherit: true +--- +apiVersion: postgresql.sql.crossplane.io/v1alpha1 +kind: Role +metadata: + name: example-role +spec: + forProvider: + connectionLimit: -1 + privileges: + createDb: true + writeConnectionSecretToRef: + name: example-role-secret + namespace: default +--- +apiVersion: postgresql.sql.crossplane.io/v1alpha1 +kind: Role +metadata: + name: parent-role +spec: + forProvider: + connectionLimit: 12 + privileges: + login: true + configurationParameters: + - name: 'statement_timeout' + value: '123' + - name: 'search_path' + value: '"$user",public' + writeConnectionSecretToRef: + name: example-parent-role-secret diff --git a/package/crds/postgresql.sql.crossplane.io_roles.yaml b/package/crds/postgresql.sql.crossplane.io_roles.yaml index d06b8ce4..fcb55881 100644 --- a/package/crds/postgresql.sql.crossplane.io_roles.yaml +++ b/package/crds/postgresql.sql.crossplane.io_roles.yaml @@ -334,6 +334,10 @@ spec: type: string type: object type: array + connectionLimit: + description: ConnectionLimit represents the applied connectionlimit + format: int32 + type: integer privilegesAsClauses: description: |- PrivilegesAsClauses represents the applied privileges state, taking into account diff --git a/pkg/controller/postgresql/role/reconciler.go b/pkg/controller/postgresql/role/reconciler.go index 055e4b77..48a4a712 100644 --- a/pkg/controller/postgresql/role/reconciler.go +++ b/pkg/controller/postgresql/role/reconciler.go @@ -207,6 +207,7 @@ func (c *external) Observe(ctx context.Context, mg resource.Managed) (managed.Ex Replication: new(bool), BypassRls: new(bool), }, + ConnectionLimit: new(int32), } query := "SELECT " + @@ -259,6 +260,8 @@ func (c *external) Observe(ctx context.Context, mg resource.Managed) (managed.Ex } cr.Status.AtProvider.ConfigurationParameters = observed.ConfigurationParameters + cr.Status.AtProvider.ConnectionLimit = observed.ConnectionLimit + _, pwdChanged, err := c.getPassword(ctx, cr) if err != nil { return managed.ExternalObservation{}, err @@ -405,10 +408,11 @@ func (c *external) Update(ctx context.Context, mg resource.Managed) (managed.Ext // Update state to reflect the current configuration parameters cr.Status.AtProvider.ConfigurationParameters = cr.Spec.ForProvider.ConfigurationParameters } - cl := cr.Spec.ForProvider.ConnectionLimit - if cl != nil { + newCl := cr.Spec.ForProvider.ConnectionLimit + currCl := cr.Status.AtProvider.ConnectionLimit + if (newCl != nil && currCl != nil) && (int64(*currCl) != int64(*newCl)) { if err := c.db.Exec(ctx, xsql.Query{ - String: fmt.Sprintf("ALTER ROLE %s CONNECTION LIMIT %d", crn, int64(*cl)), + String: fmt.Sprintf("ALTER ROLE %s CONNECTION LIMIT %d", crn, int64(*newCl)), }); err != nil { return managed.ExternalUpdate{}, errors.Wrap(err, errUpdateRole) } From 30f0927b69d1cd34f4758ae28065b0ce5a2d7240 Mon Sep 17 00:00:00 2001 From: Alan Caldera <30800723+ajcaldera1@users.noreply.github.com> Date: Fri, 23 May 2025 11:10:59 -0400 Subject: [PATCH 05/10] Fixed problem with e2e tests that was not referencing the right version of kubectl. Signed-off-by: Alan Caldera <30800723+ajcaldera1@users.noreply.github.com> --- cluster/local/postgresdb_functions.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cluster/local/postgresdb_functions.sh b/cluster/local/postgresdb_functions.sh index 815905dc..800cc770 100644 --- a/cluster/local/postgresdb_functions.sh +++ b/cluster/local/postgresdb_functions.sh @@ -189,7 +189,7 @@ check_observe_only_database(){ echo_step "check if observe only database is preserved after deletion" # Delete the database kubernetes object, it should not delete the database - kubectl delete database.postgresql.sql.crossplane.io db-observe + "${KUBECTL}" delete database.postgresql.sql.crossplane.io db-observe local datname datname="$(PGPASSWORD="${postgres_root_pw}" psql -h localhost -p 5432 -U postgres -wtAc "SELECT datname FROM pg_database WHERE datname = 'db-observe';")" From ec89b16424dbb12073de31012f8cbb316adc235b Mon Sep 17 00:00:00 2001 From: Alan Caldera <30800723+ajcaldera1@users.noreply.github.com> Date: Fri, 23 May 2025 11:34:35 -0400 Subject: [PATCH 06/10] Fixed error in example Signed-off-by: Alan Caldera <30800723+ajcaldera1@users.noreply.github.com> --- examples/postgresql/role.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/postgresql/role.yaml b/examples/postgresql/role.yaml index 038b054c..37cfc069 100644 --- a/examples/postgresql/role.yaml +++ b/examples/postgresql/role.yaml @@ -73,3 +73,4 @@ spec: value: '"$user",public' writeConnectionSecretToRef: name: example-parent-role-secret + namespace: default From 558d0f1bf6f0e33b27506bbb4f255abfd1e5d469 Mon Sep 17 00:00:00 2001 From: Alan Caldera <30800723+ajcaldera1@users.noreply.github.com> Date: Fri, 23 May 2025 11:45:24 -0400 Subject: [PATCH 07/10] Corrected integration test to call "${KUBECTL}" instead of kubectl. Signed-off-by: Alan Caldera <30800723+ajcaldera1@users.noreply.github.com> --- cluster/local/integration_tests.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cluster/local/integration_tests.sh b/cluster/local/integration_tests.sh index e8669b78..c4dbfd86 100755 --- a/cluster/local/integration_tests.sh +++ b/cluster/local/integration_tests.sh @@ -220,7 +220,7 @@ cleanup_provider() { timeout=60 current=0 step=3 - while [[ $(kubectl get providerrevision.pkg.crossplane.io -o name | wc -l | tr -d '[:space:]') != "0" ]]; do + while [[ $("${KUBECTL}" get providerrevision.pkg.crossplane.io -o name | wc -l | tr -d '[:space:]') != "0" ]]; do echo "waiting another $step seconds" current=$((current + step)) if [[ $current -ge $timeout ]]; then @@ -491,4 +491,4 @@ echo_step "--- TESTING POSTGRESDB ---" integration_tests_postgres echo_step "--- INTEGRATION TESTS FOR POSTGRESDB ACCOMPLISHED SUCCESSFULLY ---" -integration_tests_end \ No newline at end of file +integration_tests_end From 13973cda3ba297ead2e2287a56549a06abc70f6c Mon Sep 17 00:00:00 2001 From: Alan Caldera <30800723+ajcaldera1@users.noreply.github.com> Date: Wed, 28 May 2025 15:50:12 -0400 Subject: [PATCH 08/10] Fixed error in merge with go.sum Signed-off-by: Alan Caldera <30800723+ajcaldera1@users.noreply.github.com> --- go.sum | 6 ------ 1 file changed, 6 deletions(-) diff --git a/go.sum b/go.sum index d2e756ec..b3b1802a 100644 --- a/go.sum +++ b/go.sum @@ -232,14 +232,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= -<<<<<<< HEAD -<<<<<<< HEAD -======= gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= ->>>>>>> 89a2c8e (Bump google.golang.org/protobuf from 1.31.0 to 1.33.0 (#232)) -======= ->>>>>>> 78b4165 (fix: enable management policies (#215)) gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= From 7ea767063f9ab4b19868a3142f9ec9ebc721deff Mon Sep 17 00:00:00 2001 From: Alan Caldera <30800723+ajcaldera1@users.noreply.github.com> Date: Wed, 28 May 2025 15:53:50 -0400 Subject: [PATCH 09/10] Updated go.sum Signed-off-by: Alan Caldera <30800723+ajcaldera1@users.noreply.github.com> --- go.sum | 2 -- 1 file changed, 2 deletions(-) diff --git a/go.sum b/go.sum index b3b1802a..e3991144 100644 --- a/go.sum +++ b/go.sum @@ -232,8 +232,6 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= -gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= From 24a83a01cfcf758c580bf7930301d256d4d32781 Mon Sep 17 00:00:00 2001 From: Alan Caldera <30800723+ajcaldera1@users.noreply.github.com> Date: Thu, 29 May 2025 16:03:10 -0400 Subject: [PATCH 10/10] Updated to use native PG Golang connection pooling Signed-off-by: Alan Caldera <30800723+ajcaldera1@users.noreply.github.com> --- pkg/clients/postgresql/postgresql.go | 71 +++++++++++++++++++++++----- 1 file changed, 59 insertions(+), 12 deletions(-) diff --git a/pkg/clients/postgresql/postgresql.go b/pkg/clients/postgresql/postgresql.go index 270bb92c..00c16b32 100644 --- a/pkg/clients/postgresql/postgresql.go +++ b/pkg/clients/postgresql/postgresql.go @@ -5,6 +5,7 @@ import ( "database/sql" "errors" "net/url" + "time" "github.com/crossplane-contrib/provider-sql/pkg/clients/xsql" "github.com/lib/pq" @@ -20,6 +21,8 @@ const ( ) type postgresDB struct { + db *sql.DB + err error dsn string endpoint string port string @@ -38,7 +41,11 @@ func New(creds map[string][]byte, database, sslmode string) xsql.DB { password := string(creds[xpv1.ResourceCredentialsSecretPasswordKey]) dsn := DSN(username, password, endpoint, port, database, sslmode) + db, err := openDB(dsn, true) + return postgresDB{ + db: db, + err: err, dsn: dsn, endpoint: endpoint, port: port, @@ -46,6 +53,34 @@ func New(creds map[string][]byte, database, sslmode string) xsql.DB { } } +// openDB returns a new database connection +func openDB(dsn string, setLimits bool) (*sql.DB, error) { + db, err := sql.Open("postgres", dsn) + if err != nil { + return nil, err + } + + // Since we are now using connection pooling, establish some sensible defaults for connections + // Ideally these parameters would be set in the config section for the provider, but that + // can be deferred to a later time. + if setLimits { + db.SetMaxOpenConns(5) + db.SetMaxIdleConns(2) + db.SetConnMaxIdleTime(2 * time.Minute) + db.SetConnMaxLifetime(10 * time.Minute) + } + + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + err = db.PingContext(ctx) + if err != nil { + return nil, err + } + + return db, nil +} + // DSN returns the DSN URL func DSN(username, password, endpoint, port, database, sslmode string) string { // Use net/url UserPassword to encode the username and password @@ -63,12 +98,16 @@ func DSN(username, password, endpoint, port, database, sslmode string) string { // ExecTx executes an array of queries, committing if all are successful and // rolling back immediately on failure. func (c postgresDB) ExecTx(ctx context.Context, ql []xsql.Query) error { - d, err := sql.Open("postgres", c.dsn) + if c.db == nil || c.err != nil { + return c.err + } + + err := c.db.PingContext(ctx) if err != nil { return err } - tx, err := d.BeginTx(ctx, nil) + tx, err := c.db.BeginTx(ctx, nil) if err != nil { return err } @@ -76,7 +115,6 @@ func (c postgresDB) ExecTx(ctx context.Context, ql []xsql.Query) error { // Rollback or Commit based on error state. Defer close in defer to make // sure the connection is always closed. defer func() { - defer d.Close() //nolint:errcheck if err != nil { tx.Rollback() //nolint:errcheck return @@ -94,37 +132,46 @@ func (c postgresDB) ExecTx(ctx context.Context, ql []xsql.Query) error { // Exec the supplied query. func (c postgresDB) Exec(ctx context.Context, q xsql.Query) error { - d, err := sql.Open("postgres", c.dsn) + if c.db == nil || c.err != nil { + return c.err + } + + err := c.db.PingContext(ctx) if err != nil { return err } - defer d.Close() //nolint:errcheck - _, err = d.ExecContext(ctx, q.String, q.Parameters...) + _, err = c.db.ExecContext(ctx, q.String, q.Parameters...) return err } // Query the supplied query. func (c postgresDB) Query(ctx context.Context, q xsql.Query) (*sql.Rows, error) { - d, err := sql.Open("postgres", c.dsn) + if c.err != nil || c.db == nil { + return nil, c.err + } + + err := c.db.PingContext(ctx) if err != nil { return nil, err } - defer d.Close() //nolint:errcheck - rows, err := d.QueryContext(ctx, q.String, q.Parameters...) + rows, err := c.db.QueryContext(ctx, q.String, q.Parameters...) return rows, err } // Scan the results of the supplied query into the supplied destination. func (c postgresDB) Scan(ctx context.Context, q xsql.Query, dest ...interface{}) error { - db, err := sql.Open("postgres", c.dsn) + if c.db == nil || c.err != nil { + return c.err + } + + err := c.db.PingContext(ctx) if err != nil { return err } - defer db.Close() //nolint:errcheck - return db.QueryRowContext(ctx, q.String, q.Parameters...).Scan(dest...) + return c.db.QueryRowContext(ctx, q.String, q.Parameters...).Scan(dest...) } // GetConnectionDetails returns the connection details for a user of this DB