Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
d9fc2bb
feat: Helm-Chart Support External Secret Operator / feat: support for…
tkcontiant Aug 29, 2025
1fa5e13
Update charts/ext-postgres-operator/values.yaml
tkcontiant Sep 10, 2025
263b869
fix: values.yaml after code-review
tkcontiant Sep 10, 2025
2c67d42
fix: values.yaml after code-review :02
tkcontiant Sep 10, 2025
f281eb2
fix: values.yaml after code-review :03
tkcontiant Sep 10, 2025
2b0edd4
fix: .Values.externalSecret
tkcontiant Sep 16, 2025
95915f2
Merge branch 'movetokube:master' into master
tkcontiant Sep 17, 2025
a2f2035
Merge branch 'movetokube:master' into master
tkcontiant Sep 25, 2025
09d4aa2
feat: Gratn Additional Access for Sequences and Functions
tkcontiant Sep 17, 2025
892c3b5
fix: increase helm install timeout
tkcontiant Sep 17, 2025
a329ee7
feat: Support for Leader election
tkcontiant Sep 18, 2025
249b9ee
feat: Support for oeprator metrics port
tkcontiant Sep 18, 2025
acafa01
feat: ServiceMonitor Support for Promtheus-Operator
tkcontiant Sep 18, 2025
90787b3
feat: ServiceMonitor Support for Promtheus-Operator :02
tkcontiant Sep 18, 2025
2b1b6f4
feat: ServiceMonitor Support for Promtheus-Operator :03
tkcontiant Sep 18, 2025
ad0b82d
chore: revert test timout value
tkcontiant Sep 18, 2025
fae7f4a
feat: ingore test helm template output files
tkcontiant Sep 18, 2025
67fd3fa
feat: bump helm-chart application version to 2.2.0
tkcontiant Sep 18, 2025
9cdc19a
feat: External-Postgres-Operator 2.3.3 build
tkcontiant Sep 18, 2025
92de57c
reoslve conflicts after rebase
tkcontiant Sep 25, 2025
cd7f2cd
feat: Update operator k8s role
tkcontiant Sep 18, 2025
7ec4bde
feat: Update operator k8s role
tkcontiant Sep 18, 2025
42ff375
feat: stage podMonitor Changes
tkcontiant Sep 19, 2025
8547b5c
feat: stage podMonitor Changes
tkcontiant Sep 19, 2025
d7ac297
feat: add podMonitor since no service to be discvered
tkcontiant Sep 19, 2025
bdcb5ed
feat: add podMonitor since no service to be discvered
tkcontiant Sep 19, 2025
5ad8713
fix: tests
tkcontiant Sep 19, 2025
1333a0e
fix: tests
tkcontiant Sep 19, 2025
f89bc32
fix: tests
tkcontiant Sep 19, 2025
f633c5e
fix: tests
tkcontiant Sep 19, 2025
8795e09
fix: missing value sin the podmonitor
tkcontiant Sep 19, 2025
d4c6e2b
fix: tests
tkcontiant Sep 19, 2025
1a878d8
Apply suggestion from @pcallewaert
tkcontiant Sep 25, 2025
35f852c
reoslve conflicts after rebase
tkcontiant Sep 25, 2025
2de42f2
reoslve conflicts after rebase
tkcontiant Sep 25, 2025
c00cf35
reoslve conflicts after rebase
tkcontiant Sep 25, 2025
f55d5e2
fix: not needed cluster wide permission
tkcontiant Sep 25, 2025
627f711
feat: provide podMonitor enable/disable bool
tkcontiant Sep 25, 2025
d590544
fix: tests after review
tkcontiant Sep 25, 2025
55d41f2
Merge branch 'master' into feat/support-sequences-and-functions
tkcontiant Sep 26, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,7 @@ kubeconfig

.gomodcache
.gocache

# helm template output temporary files
/**/out
out
4 changes: 2 additions & 2 deletions charts/ext-postgres-operator/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ description: |

type: application

version: 2.2.0
appVersion: "2.0.0"
version: 2.3.0
appVersion: "2.4.0"
4 changes: 4 additions & 0 deletions charts/ext-postgres-operator/templates/operator.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ spec:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: metrics
containerPort: 8080
protocol: "TCP"
envFrom:
- secretRef:
{{- if .Values.existingSecret }}
Expand Down
32 changes: 32 additions & 0 deletions charts/ext-postgres-operator/templates/pod-monitor.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{{- if and (.Capabilities.APIVersions.Has "monitoring.coreos.com/v1") ( .Values.podMonitor.enabled ) }}
apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
annotations:
{{- with .Values.podMonitor.additionalAnnotations }}
{{- toYaml . | nindent 4 }}
{{- end }}
labels:
{{- include "chart.labels" . | nindent 4 }}
{{- with .Values.podMonitor.additonalLabels }}
{{- toYaml . | nindent 4 }}
{{- end }}
name: {{ include "chart.fullname" . }}
namespace: {{ .Release.Namespace }}
spec:
namespaceSelector:
matchNames:
- {{ .Release.Namespace }}
podMetricsEndpoints:
- interval: {{ .Values.podMonitor.interval | default "30s" }}
scrapeTimeout: {{ .Values.podMonitor.scrapeTimeout | default "10s" }}
path: /metrics
port: metrics
{{- if .Values.podMonitor.relabelings }}
relabelings:
{{- tpl (toYaml .Values.podMonitor.relabelings) . | nindent 6 }}
{{- end }}
selector:
matchLabels:
{{- include "chart.selectorLabels" . | nindent 6 }}
{{- end -}}
26 changes: 23 additions & 3 deletions charts/ext-postgres-operator/templates/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,31 @@ rules:
resources:
- pods
verbs:
- "get"
- get
- apiGroups:
- "apps"
- ""
resources:
- events
verbs:
- create
- patch
- update
- apiGroups:
- coordination.k8s.io
resources:
- leases
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
- apiGroups:
- apps
resources:
- replicasets
- deployments
verbs:
- "get"
- get
16 changes: 15 additions & 1 deletion charts/ext-postgres-operator/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ watchNamespace: ""
# Define connection to postgres database server
postgres:
# postgres hostname
host: "localhost"
host: "localhost:5432"
# postgres admin user and password ( ignored if existingSecret or ExternalSecret is set )
user: "admin"
password: "password"
Expand Down Expand Up @@ -114,6 +114,20 @@ env: {}
# POSTGRES_INSTANCE: "XXXXXXXXXX"
# POSTGRES_CLOUD_PROVIDER: "AWS"

# podMonitor is a custom resource used by the Prometheus-Operator and others
podMonitor:
enabled: false
interval: 30s
scrapeTimeout: 10s
relabeling: []
# - targetLabel: app
# replacement: '{{ include "chart.name" . }}'
additonalLabels: {}
# e.g. release label of the prometheus operator
# release: prometheus-operator
additionalAnnotations: {}
# e.g. {}

nodeSelector: {}

tolerations: []
8 changes: 4 additions & 4 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,15 @@ func main() {
var secureMetrics bool
var enableHTTP2 bool
var tlsOpts []func(*tls.Config)
flag.StringVar(&metricsAddr, "metrics-bind-address", "0", "The address the metrics endpoint binds to. "+
flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metrics endpoint binds to. "+
"Use :8443 for HTTPS or :8080 for HTTP, or leave as 0 to disable the metrics service.")
flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
flag.BoolVar(&enableLeaderElection, "leader-elect", false,
flag.BoolVar(&enableLeaderElection, "leader-elect", true,
"Enable leader election for controller manager. "+
"Enabling this will ensure there is only one active controller manager.")
flag.BoolVar(&secureMetrics, "metrics-secure", true,
flag.BoolVar(&secureMetrics, "metrics-secure", false,
"If set, the metrics endpoint is served securely via HTTPS. Use --metrics-secure=false to use HTTP instead.")
flag.BoolVar(&enableHTTP2, "enable-http2", false,
flag.BoolVar(&enableHTTP2, "enable-http2", true,
"If set, HTTP/2 will be enabled for the metrics and webhook servers")
opts := zap.Options{
Development: true,
Expand Down
4 changes: 4 additions & 0 deletions config/manager/operator.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ spec:
- name: ext-postgres-operator
image: movetokube/postgres-operator:2.0.0
imagePullPolicy: Always
ports:
- name: metrics
containerPort: 8080
protocol: "TCP"
envFrom:
- secretRef:
name: ext-postgres-operator
Expand Down
13 changes: 13 additions & 0 deletions config/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ rules:
- configmaps
- secrets
- services
- events
verbs:
- "*"
- apiGroups:
Expand All @@ -17,6 +18,18 @@ rules:
- pods
verbs:
- "get"
- apiGroups:
- coordination.k8s.io
resources:
- leases
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
- apiGroups:
- "apps"
resources:
Expand Down
74 changes: 54 additions & 20 deletions internal/controller/postgres_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,27 @@ func (r *PostgresReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
instance.Status.Roles.Writer = writer
instance.Status.Succeeded = true
}

desiredOwner := instance.Spec.MasterRole
// If no owner was specified, use default owner name
if desiredOwner == "" {
desiredOwner = fmt.Sprintf("%s-group", instance.Spec.Database)
}
// rename owner role if instance.Spec.MasterRole was changed
ownerChanged := instance.Status.Roles.Owner != "" && instance.Status.Roles.Owner != desiredOwner
if ownerChanged {
err = r.pg.RenameGroupRole(instance.Status.Roles.Owner, desiredOwner)
if err != nil {
return requeue(errors.NewInternalError(err))
}
// Alter database owner if the owner role was changed
err = r.pg.AlterDatabaseOwner(instance.Spec.Database, instance.Status.Roles.Owner)
if err != nil {
return requeue(errors.NewInternalError(err))
}
instance.Status.Roles.Owner = desiredOwner
}

// create extensions
for _, extension := range instance.Spec.Extensions {
// Check if extension is already added. Skip if already is added.
Expand All @@ -184,12 +205,17 @@ func (r *PostgresReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
}
// create schemas
var (
database = instance.Spec.Database
owner = instance.Status.Roles.Owner
reader = instance.Status.Roles.Reader
writer = instance.Status.Roles.Writer
readerPrivs = "SELECT"
writerPrivs = "SELECT,INSERT,DELETE,UPDATE"
database = instance.Spec.Database
owner = instance.Status.Roles.Owner
reader = instance.Status.Roles.Reader
writer = instance.Status.Roles.Writer
readerPrivs = "SELECT"
writerPrivs = "SELECT,INSERT,DELETE,UPDATE"
writerSequencePrivs = "USAGE,SELECT"
writerFunctionPrivs = "EXECUTE"
ownerPrivs = "ALL"
ownerFunctionPrivs = "ALL"
ownerSequencePrivs = "ALL"
)
for _, schema := range instance.Spec.Schemas {
// Schema was previously created
Expand All @@ -203,6 +229,11 @@ func (r *PostgresReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
reqLogger.Error(err, fmt.Sprintf("Could not create schema %s", schema))
continue
}
instance.Status.Schemas = append(instance.Status.Schemas, schema)
}

// Set privileges on schemas during every reconcile to ensure privileges are correct
for _, schema := range instance.Spec.Schemas {

// Set privileges on schema
schemaPrivilegesReader := postgres.PostgresSchemaPrivileges{
Expand All @@ -218,32 +249,35 @@ func (r *PostgresReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
continue
}
schemaPrivilegesWriter := postgres.PostgresSchemaPrivileges{
DB: database,
Role: writer,
Schema: schema,
Privs: writerPrivs,
CreateSchema: true,
DB: database,
Role: writer,
Schema: schema,
Privs: writerPrivs,
SequencePrivs: writerSequencePrivs,
FunctionPrivs: writerFunctionPrivs,
CreateSchema: true,
}
err = r.pg.SetSchemaPrivileges(schemaPrivilegesWriter, reqLogger)
if err != nil {
reqLogger.Error(err, fmt.Sprintf("Could not give %s permissions \"%s\"", writer, writerPrivs))
reqLogger.Error(err, fmt.Sprintf("Could not give %s permissions \"%s\", sequence privileges \"%s\", and function privileges \"%s\"", writer, writerPrivs, writerSequencePrivs, writerFunctionPrivs))
continue
}
schemaPrivilegesOwner := postgres.PostgresSchemaPrivileges{
DB: database,
Role: owner,
Schema: schema,
Privs: writerPrivs,
CreateSchema: true,
DB: database,
Role: owner,
Schema: schema,
Privs: ownerPrivs,
SequencePrivs: ownerSequencePrivs,
FunctionPrivs: ownerFunctionPrivs,
CreateSchema: true,
}
err = r.pg.SetSchemaPrivileges(schemaPrivilegesOwner, reqLogger)
if err != nil {
reqLogger.Error(err, fmt.Sprintf("Could not give %s permissions \"%s\"", writer, writerPrivs))
reqLogger.Error(err, fmt.Sprintf("Could not give %s permissions \"%s\", sequence privileges \"%s\", and function privileges \"%s\"", owner, ownerPrivs, ownerSequencePrivs, ownerFunctionPrivs))
continue
}

instance.Status.Schemas = append(instance.Status.Schemas, schema)
}

err = r.Status().Patch(ctx, instance, client.MergeFrom(before))
if err != nil {
return requeue(err)
Expand Down
13 changes: 7 additions & 6 deletions internal/controller/postgres_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ var _ = Describe("PostgresReconciler", func() {
// Gomock
mockCtrl = gomock.NewController(GinkgoT())
pg = mockpg.NewMockPG(mockCtrl)
pg.EXPECT().AlterDatabaseOwner(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
pg.EXPECT().ReassignDatabaseOwner(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
cl = k8sClient
// Create runtime scheme
sc = scheme.Scheme
Expand Down Expand Up @@ -684,10 +686,10 @@ var _ = Describe("PostgresReconciler", func() {
// Expected method calls
// customers schema
pg.EXPECT().CreateSchema(name, name+"-group", "customers", gomock.Any()).Return(nil).Times(1)
pg.EXPECT().SetSchemaPrivileges(gomock.Any(), gomock.Any()).Return(nil).Times(3)
pg.EXPECT().SetSchemaPrivileges(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
// stores schema
pg.EXPECT().CreateSchema(name, name+"-group", "stores", gomock.Any()).Return(nil).Times(1)
pg.EXPECT().SetSchemaPrivileges(gomock.Any(), gomock.Any()).Return(nil).Times(3)
pg.EXPECT().SetSchemaPrivileges(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
})

It("should update status", func() {
Expand All @@ -708,10 +710,10 @@ var _ = Describe("PostgresReconciler", func() {
// Expected method calls
// customers schema errors
pg.EXPECT().CreateSchema(name, name+"-group", "customers", gomock.Any()).Return(fmt.Errorf("Could not create schema")).Times(1)
pg.EXPECT().SetSchemaPrivileges(gomock.Any(), gomock.Any()).Return(nil).Times(0)
pg.EXPECT().SetSchemaPrivileges(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
// stores schema
pg.EXPECT().CreateSchema(name, name+"-group", "stores", gomock.Any()).Return(nil).Times(1)
pg.EXPECT().SetSchemaPrivileges(gomock.Any(), gomock.Any()).Return(nil).Times(3)
pg.EXPECT().SetSchemaPrivileges(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
})

It("should update status", func() {
Expand Down Expand Up @@ -743,10 +745,9 @@ var _ = Describe("PostgresReconciler", func() {
It("should not recreate existing schema", func() {
// customers schema
pg.EXPECT().CreateSchema(name, name+"-group", "customers", gomock.Any()).Return(nil).Times(1)
pg.EXPECT().SetSchemaPrivileges(gomock.Any(), gomock.Any()).Return(nil).Times(3)
pg.EXPECT().SetSchemaPrivileges(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
// stores schema already exists
pg.EXPECT().CreateSchema(name, name+"-group", "stores", gomock.Any()).Times(0)
pg.EXPECT().SetSchemaPrivileges(gomock.Any(), gomock.Any()).Return(nil).Times(0)
// Call reconcile
err := runReconcile(rp, ctx, req)
Expect(err).NotTo(HaveOccurred())
Expand Down
Loading