diff --git a/CHANGELOG.md b/CHANGELOG.md index 44511a7b9..876533c0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,11 @@ ## [MAJOR.MINOR.PATCH] - YYYY-MM-DD +## v0.16.1 - YYYY-MM-DD + - Check VPC for running services before deletion +- Expose `CONNECTIONPOOL_NAME` in `ConnectionPool` secret +- Fix `CONNECTIONPOOL_PORT` exposes service port instead of pool port ## v0.16.0 - 2023-12-07 diff --git a/api/v1alpha1/connectionpool_types.go b/api/v1alpha1/connectionpool_types.go index fcd83ab21..237d32e1c 100644 --- a/api/v1alpha1/connectionpool_types.go +++ b/api/v1alpha1/connectionpool_types.go @@ -35,7 +35,7 @@ type ConnectionPoolSpec struct { PoolMode string `json:"poolMode,omitempty"` // Information regarding secret creation. - // Exposed keys: `CONNECTIONPOOL_HOST`, `CONNECTIONPOOL_PORT`, `CONNECTIONPOOL_DATABASE`, `CONNECTIONPOOL_USER`, `CONNECTIONPOOL_PASSWORD`, `CONNECTIONPOOL_SSLMODE`, `CONNECTIONPOOL_DATABASE_URI` + // Exposed keys: `CONNECTIONPOOL_NAME`, `CONNECTIONPOOL_HOST`, `CONNECTIONPOOL_PORT`, `CONNECTIONPOOL_DATABASE`, `CONNECTIONPOOL_USER`, `CONNECTIONPOOL_PASSWORD`, `CONNECTIONPOOL_SSLMODE`, `CONNECTIONPOOL_DATABASE_URI` ConnInfoSecretTarget ConnInfoSecretTarget `json:"connInfoSecretTarget,omitempty"` // Authentication reference to Aiven token in a secret diff --git a/charts/aiven-operator-crds/templates/aiven.io_connectionpools.yaml b/charts/aiven-operator-crds/templates/aiven.io_connectionpools.yaml index 7b303bd10..f8b3d4399 100644 --- a/charts/aiven-operator-crds/templates/aiven.io_connectionpools.yaml +++ b/charts/aiven-operator-crds/templates/aiven.io_connectionpools.yaml @@ -69,9 +69,9 @@ spec: type: object connInfoSecretTarget: description: 'Information regarding secret creation. Exposed keys: - `CONNECTIONPOOL_HOST`, `CONNECTIONPOOL_PORT`, `CONNECTIONPOOL_DATABASE`, - `CONNECTIONPOOL_USER`, `CONNECTIONPOOL_PASSWORD`, `CONNECTIONPOOL_SSLMODE`, - `CONNECTIONPOOL_DATABASE_URI`' + `CONNECTIONPOOL_NAME`, `CONNECTIONPOOL_HOST`, `CONNECTIONPOOL_PORT`, + `CONNECTIONPOOL_DATABASE`, `CONNECTIONPOOL_USER`, `CONNECTIONPOOL_PASSWORD`, + `CONNECTIONPOOL_SSLMODE`, `CONNECTIONPOOL_DATABASE_URI`' properties: annotations: additionalProperties: diff --git a/config/crd/bases/aiven.io_connectionpools.yaml b/config/crd/bases/aiven.io_connectionpools.yaml index 7b303bd10..f8b3d4399 100644 --- a/config/crd/bases/aiven.io_connectionpools.yaml +++ b/config/crd/bases/aiven.io_connectionpools.yaml @@ -69,9 +69,9 @@ spec: type: object connInfoSecretTarget: description: 'Information regarding secret creation. Exposed keys: - `CONNECTIONPOOL_HOST`, `CONNECTIONPOOL_PORT`, `CONNECTIONPOOL_DATABASE`, - `CONNECTIONPOOL_USER`, `CONNECTIONPOOL_PASSWORD`, `CONNECTIONPOOL_SSLMODE`, - `CONNECTIONPOOL_DATABASE_URI`' + `CONNECTIONPOOL_NAME`, `CONNECTIONPOOL_HOST`, `CONNECTIONPOOL_PORT`, + `CONNECTIONPOOL_DATABASE`, `CONNECTIONPOOL_USER`, `CONNECTIONPOOL_PASSWORD`, + `CONNECTIONPOOL_SSLMODE`, `CONNECTIONPOOL_DATABASE_URI`' properties: annotations: additionalProperties: diff --git a/controllers/connectionpool_controller.go b/controllers/connectionpool_controller.go index d3843a8a6..5d24b4e7b 100644 --- a/controllers/connectionpool_controller.go +++ b/controllers/connectionpool_controller.go @@ -5,6 +5,7 @@ package controllers import ( "context" "fmt" + "net/url" "strconv" "github.com/aiven/aiven-go-client/v2" @@ -129,6 +130,11 @@ func (h ConnectionPoolHandler) get(ctx context.Context, avn *aiven.Client, obj c return nil, fmt.Errorf("cannot get ConnectionPool: %w", err) } + poolURI, err := url.Parse(cp.ConnectionURI) + if err != nil { + return nil, fmt.Errorf("can't parse ConnectionPool URI: %w", err) + } + s, err := avn.Services.Get(ctx, connPool.Spec.Project, connPool.Spec.ServiceName) if err != nil { return nil, fmt.Errorf("cannot get service: %w", err) @@ -143,8 +149,9 @@ func (h ConnectionPoolHandler) get(ctx context.Context, avn *aiven.Client, obj c if len(connPool.Spec.Username) == 0 { prefix := getSecretPrefix(connPool) stringData := map[string]string{ + prefix + "NAME": connPool.Name, prefix + "HOST": s.URIParams["host"], - prefix + "PORT": s.URIParams["port"], + prefix + "PORT": poolURI.Port(), prefix + "DATABASE": cp.Database, prefix + "USER": s.URIParams["user"], prefix + "PASSWORD": s.URIParams["password"], @@ -152,7 +159,7 @@ func (h ConnectionPoolHandler) get(ctx context.Context, avn *aiven.Client, obj c prefix + "DATABASE_URI": cp.ConnectionURI, // todo: remove in future releases "PGHOST": s.URIParams["host"], - "PGPORT": s.URIParams["port"], + "PGPORT": poolURI.Port(), "PGDATABASE": cp.Database, "PGUSER": s.URIParams["user"], "PGPASSWORD": s.URIParams["password"], @@ -170,8 +177,9 @@ func (h ConnectionPoolHandler) get(ctx context.Context, avn *aiven.Client, obj c prefix := getSecretPrefix(connPool) stringData := map[string]string{ + prefix + "NAME": connPool.Name, prefix + "HOST": s.URIParams["host"], - prefix + "PORT": s.URIParams["port"], + prefix + "PORT": poolURI.Port(), prefix + "DATABASE": cp.Database, prefix + "USER": cp.Username, prefix + "PASSWORD": u.Password, @@ -179,7 +187,7 @@ func (h ConnectionPoolHandler) get(ctx context.Context, avn *aiven.Client, obj c prefix + "DATABASE_URI": cp.ConnectionURI, // todo: remove in future releases "PGHOST": s.URIParams["host"], - "PGPORT": s.URIParams["port"], + "PGPORT": poolURI.Port(), "PGDATABASE": cp.Database, "PGUSER": cp.Username, "PGPASSWORD": u.Password, diff --git a/docs/docs/api-reference/connectionpool.md b/docs/docs/api-reference/connectionpool.md index 277574049..53e500e1d 100644 --- a/docs/docs/api-reference/connectionpool.md +++ b/docs/docs/api-reference/connectionpool.md @@ -57,7 +57,7 @@ ConnectionPoolSpec defines the desired state of ConnectionPool. **Optional** - [`authSecretRef`](#spec.authSecretRef-property){: name='spec.authSecretRef-property'} (object). Authentication reference to Aiven token in a secret. See below for [nested schema](#spec.authSecretRef). -- [`connInfoSecretTarget`](#spec.connInfoSecretTarget-property){: name='spec.connInfoSecretTarget-property'} (object). Information regarding secret creation. Exposed keys: `CONNECTIONPOOL_HOST`, `CONNECTIONPOOL_PORT`, `CONNECTIONPOOL_DATABASE`, `CONNECTIONPOOL_USER`, `CONNECTIONPOOL_PASSWORD`, `CONNECTIONPOOL_SSLMODE`, `CONNECTIONPOOL_DATABASE_URI`. See below for [nested schema](#spec.connInfoSecretTarget). +- [`connInfoSecretTarget`](#spec.connInfoSecretTarget-property){: name='spec.connInfoSecretTarget-property'} (object). Information regarding secret creation. Exposed keys: `CONNECTIONPOOL_NAME`, `CONNECTIONPOOL_HOST`, `CONNECTIONPOOL_PORT`, `CONNECTIONPOOL_DATABASE`, `CONNECTIONPOOL_USER`, `CONNECTIONPOOL_PASSWORD`, `CONNECTIONPOOL_SSLMODE`, `CONNECTIONPOOL_DATABASE_URI`. See below for [nested schema](#spec.connInfoSecretTarget). - [`poolMode`](#spec.poolMode-property){: name='spec.poolMode-property'} (string, Enum: `session`, `transaction`, `statement`). Mode the pool operates in (session, transaction, statement). - [`poolSize`](#spec.poolSize-property){: name='spec.poolSize-property'} (integer). Number of connections the pool may create towards the backend server. @@ -76,7 +76,7 @@ Authentication reference to Aiven token in a secret. _Appears on [`spec`](#spec)._ -Information regarding secret creation. Exposed keys: `CONNECTIONPOOL_HOST`, `CONNECTIONPOOL_PORT`, `CONNECTIONPOOL_DATABASE`, `CONNECTIONPOOL_USER`, `CONNECTIONPOOL_PASSWORD`, `CONNECTIONPOOL_SSLMODE`, `CONNECTIONPOOL_DATABASE_URI`. +Information regarding secret creation. Exposed keys: `CONNECTIONPOOL_NAME`, `CONNECTIONPOOL_HOST`, `CONNECTIONPOOL_PORT`, `CONNECTIONPOOL_DATABASE`, `CONNECTIONPOOL_USER`, `CONNECTIONPOOL_PASSWORD`, `CONNECTIONPOOL_SSLMODE`, `CONNECTIONPOOL_DATABASE_URI`. **Required** diff --git a/tests/connectionpool_test.go b/tests/connectionpool_test.go index 98a14e334..a35c93aca 100644 --- a/tests/connectionpool_test.go +++ b/tests/connectionpool_test.go @@ -157,6 +157,7 @@ func TestConnectionPool(t *testing.T) { assert.NotEmpty(t, secret.Data["DATABASE_URI"]) // New secrets + assert.Equal(t, poolName, string(secret.Data["CONNECTIONPOOL_NAME"])) assert.NotEmpty(t, secret.Data["CONNECTIONPOOL_HOST"]) assert.NotEmpty(t, secret.Data["CONNECTIONPOOL_PORT"]) assert.NotEmpty(t, secret.Data["CONNECTIONPOOL_DATABASE"]) @@ -165,6 +166,11 @@ func TestConnectionPool(t *testing.T) { assert.NotEmpty(t, secret.Data["CONNECTIONPOOL_SSLMODE"]) assert.NotEmpty(t, secret.Data["CONNECTIONPOOL_DATABASE_URI"]) + // URI contains valid values + uri := string(secret.Data["CONNECTIONPOOL_DATABASE_URI"]) + assert.Contains(t, uri, string(secret.Data["CONNECTIONPOOL_HOST"])) + assert.Contains(t, uri, string(secret.Data["CONNECTIONPOOL_PORT"])) + // We need to validate deletion, // because we can get false positive here: // if service is deleted, pool is destroyed in Aiven. No service — no pool. No pool — no pool.