Skip to content

Commit 463bf42

Browse files
egeguneshors
andauthoredJan 2, 2025
K8SPG-699: Add pgvector support (#991)
* K8SPG-699: Add pgvector support * update extension * fix golangci-lint --------- Co-authored-by: Viacheslav Sarzhan <slava.sarzhan@percona.com>
1 parent 78c3d22 commit 463bf42

14 files changed

+156
-1
lines changed
 

‎build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -8352,6 +8352,8 @@ spec:
83528352
type: boolean
83538353
pgStatStatements:
83548354
type: boolean
8355+
pgvector:
8356+
type: boolean
83558357
type: object
83568358
image:
83578359
description: |-

‎build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -8064,6 +8064,8 @@ spec:
80648064
type: boolean
80658065
pg_stat_monitor:
80668066
type: boolean
8067+
pgvector:
8068+
type: boolean
80678069
type: object
80688070
custom:
80698071
items:

‎config/crd/bases/pgv2.percona.com_perconapgclusters.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -8470,6 +8470,8 @@ spec:
84708470
type: boolean
84718471
pg_stat_monitor:
84728472
type: boolean
8473+
pgvector:
8474+
type: boolean
84738475
type: object
84748476
custom:
84758477
items:

‎config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -8312,6 +8312,8 @@ spec:
83128312
type: boolean
83138313
pgStatStatements:
83148314
type: boolean
8315+
pgvector:
8316+
type: boolean
83158317
type: object
83168318
image:
83178319
description: |-

‎deploy/bundle.yaml

+4
Original file line numberDiff line numberDiff line change
@@ -8763,6 +8763,8 @@ spec:
87638763
type: boolean
87648764
pg_stat_monitor:
87658765
type: boolean
8766+
pgvector:
8767+
type: boolean
87668768
type: object
87678769
custom:
87688770
items:
@@ -33985,6 +33987,8 @@ spec:
3398533987
type: boolean
3398633988
pgStatStatements:
3398733989
type: boolean
33990+
pgvector:
33991+
type: boolean
3398833992
type: object
3398933993
image:
3399033994
description: |-

‎deploy/cr.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,7 @@ spec:
495495
# builtin:
496496
# pg_stat_monitor: true
497497
# pg_audit: true
498+
# pgvector: false
498499
# custom:
499500
# - name: pg_cron
500501
# version: 1.6.1

‎deploy/crd.yaml

+4
Original file line numberDiff line numberDiff line change
@@ -8763,6 +8763,8 @@ spec:
87638763
type: boolean
87648764
pg_stat_monitor:
87658765
type: boolean
8766+
pgvector:
8767+
type: boolean
87668768
type: object
87678769
custom:
87688770
items:
@@ -33985,6 +33987,8 @@ spec:
3398533987
type: boolean
3398633988
pgStatStatements:
3398733989
type: boolean
33990+
pgvector:
33991+
type: boolean
3398833992
type: object
3398933993
image:
3399033994
description: |-

‎deploy/cw-bundle.yaml

+4
Original file line numberDiff line numberDiff line change
@@ -8763,6 +8763,8 @@ spec:
87638763
type: boolean
87648764
pg_stat_monitor:
87658765
type: boolean
8766+
pgvector:
8767+
type: boolean
87668768
type: object
87678769
custom:
87688770
items:
@@ -33985,6 +33987,8 @@ spec:
3398533987
type: boolean
3398633988
pgStatStatements:
3398733989
type: boolean
33990+
pgvector:
33991+
type: boolean
3398833992
type: object
3398933993
image:
3399033994
description: |-

‎internal/controller/postgrescluster/postgres.go

+14-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131
"github.com/percona/percona-postgresql-operator/internal/pgaudit"
3232
"github.com/percona/percona-postgresql-operator/internal/pgstatmonitor"
3333
"github.com/percona/percona-postgresql-operator/internal/pgstatstatements"
34+
"github.com/percona/percona-postgresql-operator/internal/pgvector"
3435
"github.com/percona/percona-postgresql-operator/internal/postgis"
3536
"github.com/percona/percona-postgresql-operator/internal/postgres"
3637
pgpassword "github.com/percona/percona-postgresql-operator/internal/postgres/password"
@@ -234,7 +235,7 @@ func (r *Reconciler) reconcilePostgresDatabases(
234235
// Calculate a hash of the SQL that should be executed in PostgreSQL.
235236

236237
// K8SPG-375, K8SPG-577
237-
var pgAuditOK, pgStatMonitorOK, pgStatStatementsOK, postgisInstallOK bool
238+
var pgAuditOK, pgStatMonitorOK, pgStatStatementsOK, pgvectorOK, postgisInstallOK bool
238239
create := func(ctx context.Context, exec postgres.Executor) error {
239240
if cluster.Spec.Extensions.PGStatMonitor {
240241
if pgStatMonitorOK = pgstatmonitor.EnableInPostgreSQL(ctx, exec) == nil; !pgStatMonitorOK {
@@ -280,6 +281,18 @@ func (r *Reconciler) reconcilePostgresDatabases(
280281
}
281282
}
282283

284+
if cluster.Spec.Extensions.PGVector {
285+
if pgvectorOK = pgvector.EnableInPostgreSQL(ctx, exec) == nil; !pgvectorOK {
286+
r.Recorder.Event(cluster, corev1.EventTypeWarning, "pgvectorDisabled",
287+
"Unable to install pgvector")
288+
}
289+
} else {
290+
if pgvectorOK = pgvector.DisableInPostgreSQL(ctx, exec) == nil; !pgvectorOK {
291+
r.Recorder.Event(cluster, corev1.EventTypeWarning, "pgvectorEnabled",
292+
"Unable to disable pgvector")
293+
}
294+
}
295+
283296
// Enabling PostGIS extensions is a one-way operation
284297
// e.g., you can take a PostgresCluster and turn it into a PostGISCluster,
285298
// but you cannot reverse the process, as that would potentially remove an extension

‎internal/pgvector/postgres.go

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package pgvector
2+
3+
import (
4+
"context"
5+
6+
"github.com/percona/percona-postgresql-operator/internal/logging"
7+
"github.com/percona/percona-postgresql-operator/internal/postgres"
8+
)
9+
10+
// EnableInPostgreSQL installs pgvector triggers into every database.
11+
func EnableInPostgreSQL(ctx context.Context, exec postgres.Executor) error {
12+
log := logging.FromContext(ctx)
13+
14+
stdout, stderr, err := exec.ExecInAllDatabases(ctx,
15+
// Quiet the NOTICE from IF EXISTS, and install the pgAudit event triggers.
16+
// - https://www.postgresql.org/docs/current/runtime-config-client.html
17+
// - https://github.com/pgaudit/pgaudit#settings
18+
`SET client_min_messages = WARNING; CREATE EXTENSION IF NOT EXISTS vector; ALTER EXTENSION vector UPDATE;`,
19+
map[string]string{
20+
"ON_ERROR_STOP": "on", // Abort when any one command fails.
21+
"QUIET": "on", // Do not print successful commands to stdout.
22+
})
23+
24+
log.V(1).Info("enabled pgvector", "stdout", stdout, "stderr", stderr)
25+
26+
return err
27+
}
28+
29+
func DisableInPostgreSQL(ctx context.Context, exec postgres.Executor) error {
30+
log := logging.FromContext(ctx)
31+
32+
stdout, stderr, err := exec.ExecInAllDatabases(ctx,
33+
// Quiet the NOTICE from IF EXISTS, and install the pgAudit event triggers.
34+
// - https://www.postgresql.org/docs/current/runtime-config-client.html
35+
// - https://github.com/pgaudit/pgaudit#settings
36+
`SET client_min_messages = WARNING; DROP EXTENSION IF EXISTS vector;`,
37+
map[string]string{
38+
"ON_ERROR_STOP": "on", // Abort when any one command fails.
39+
"QUIET": "on", // Do not print successful commands to stdout.
40+
})
41+
42+
log.V(1).Info("disabled pgvector", "stdout", stdout, "stderr", stderr)
43+
44+
return err
45+
}
46+
47+
// PostgreSQLParameters sets the parameters required by pgAudit.
48+
func PostgreSQLParameters(outParameters *postgres.Parameters) {}

‎internal/pgvector/postgres_test.go

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package pgvector
2+
3+
import (
4+
"context"
5+
"errors"
6+
"io"
7+
"strings"
8+
"testing"
9+
10+
"gotest.tools/v3/assert"
11+
)
12+
13+
func TestEnableInPostgreSQL(t *testing.T) {
14+
expected := errors.New("whoops")
15+
exec := func(
16+
_ context.Context, stdin io.Reader, stdout, stderr io.Writer, command ...string,
17+
) error {
18+
assert.Assert(t, stdout != nil, "should capture stdout")
19+
assert.Assert(t, stderr != nil, "should capture stderr")
20+
21+
assert.Assert(t, strings.Contains(strings.Join(command, "\n"),
22+
`SELECT datname FROM pg_catalog.pg_database`,
23+
), "expected all databases and templates")
24+
25+
b, err := io.ReadAll(stdin)
26+
assert.NilError(t, err)
27+
assert.Equal(t, string(b), strings.Trim(`
28+
SET client_min_messages = WARNING; CREATE EXTENSION IF NOT EXISTS vector; ALTER EXTENSION vector UPDATE;
29+
`, "\t\n"))
30+
31+
return expected
32+
}
33+
34+
ctx := context.Background()
35+
assert.Equal(t, expected, EnableInPostgreSQL(ctx, exec))
36+
}
37+
38+
func TestDisableInPostgreSQL(t *testing.T) {
39+
expected := errors.New("whoops")
40+
exec := func(
41+
_ context.Context, stdin io.Reader, stdout, stderr io.Writer, command ...string,
42+
) error {
43+
assert.Assert(t, stdout != nil, "should capture stdout")
44+
assert.Assert(t, stderr != nil, "should capture stderr")
45+
46+
assert.Assert(t, strings.Contains(strings.Join(command, "\n"),
47+
`SELECT datname FROM pg_catalog.pg_database`,
48+
), "expected all databases and templates")
49+
50+
b, err := io.ReadAll(stdin)
51+
assert.NilError(t, err)
52+
assert.Equal(t, string(b), strings.Trim(`
53+
SET client_min_messages = WARNING; DROP EXTENSION IF EXISTS vector;
54+
`, "\t\n"))
55+
56+
return expected
57+
}
58+
59+
ctx := context.Background()
60+
assert.Equal(t, expected, DisableInPostgreSQL(ctx, exec))
61+
}

‎pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go

+6
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ func (cr *PerconaPGCluster) Default() {
206206
cr.Spec.Proxy.PGBouncer.Metadata.Labels[LabelOperatorVersion] = cr.Spec.CRVersion
207207

208208
t := true
209+
f := false
209210

210211
if cr.Spec.Backups.TrackLatestRestorableTime == nil {
211212
cr.Spec.Backups.TrackLatestRestorableTime = &t
@@ -224,6 +225,9 @@ func (cr *PerconaPGCluster) Default() {
224225
if cr.Spec.Extensions.BuiltIn.PGAudit == nil {
225226
cr.Spec.Extensions.BuiltIn.PGAudit = &t
226227
}
228+
if cr.Spec.Extensions.BuiltIn.PGVector == nil {
229+
cr.Spec.Extensions.BuiltIn.PGVector = &f
230+
}
227231

228232
if cr.CompareVersion("2.6.0") >= 0 && cr.Spec.AutoCreateUserSchema == nil {
229233
cr.Spec.AutoCreateUserSchema = &t
@@ -344,6 +348,7 @@ func (cr *PerconaPGCluster) ToCrunchy(ctx context.Context, postgresCluster *crun
344348

345349
postgresCluster.Spec.Extensions.PGStatMonitor = *cr.Spec.Extensions.BuiltIn.PGStatMonitor
346350
postgresCluster.Spec.Extensions.PGAudit = *cr.Spec.Extensions.BuiltIn.PGAudit
351+
postgresCluster.Spec.Extensions.PGVector = *cr.Spec.Extensions.BuiltIn.PGVector
347352

348353
return postgresCluster, nil
349354
}
@@ -567,6 +572,7 @@ type CustomExtensionsStorageSpec struct {
567572
type BuiltInExtensionsSpec struct {
568573
PGStatMonitor *bool `json:"pg_stat_monitor,omitempty"`
569574
PGAudit *bool `json:"pg_audit,omitempty"`
575+
PGVector *bool `json:"pgvector,omitempty"`
570576
}
571577

572578
type ExtensionsSpec struct {

‎pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go

+5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go

+1
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ type ExtensionsSpec struct {
186186
PGStatMonitor bool `json:"pgStatMonitor,omitempty"`
187187
PGAudit bool `json:"pgAudit,omitempty"`
188188
PGStatStatements bool `json:"pgStatStatements,omitempty"`
189+
PGVector bool `json:"pgvector,omitempty"`
189190
}
190191

191192
// DataSource defines data sources for a new PostgresCluster.

0 commit comments

Comments
 (0)
Please sign in to comment.