Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions charts/postgres-operator/crds/operatorconfigurations.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ spec:
nullable: true
items:
type: string
database_name_regexp:
type: string
default: "^[a-zA-Z_][a-zA-Z0-9_]*$"
docker_image:
type: string
default: "ghcr.io/zalando/spilo-15:2.1-p9"
Expand Down
6 changes: 6 additions & 0 deletions docs/reference/operator_parameters.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,12 @@ Those are top-level keys, containing both leaf keys and groups.
operator's own container, change the [operator deployment manually](https://github.com/zalando/postgres-operator/blob/master/manifests/postgres-operator.yaml#L20).
The default is `false`.


* **database_name_regexp**
By default the operator will follow the naming conventions for PostgreSQL. However,
the regexp can be modified to customize the validation.
The default is `^[a-zA-Z_][a-zA-Z0-9_]*$`.

## Postgres users

Parameters describing Postgres users. In a CRD-configuration, they are grouped
Expand Down
1 change: 1 addition & 0 deletions manifests/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ data:
crd_categories: "all"
# custom_service_annotations: "keyx:valuez,keya:valuea"
# custom_pod_annotations: "keya:valuea,keyb:valueb"
# database_name_regexp: "^[a-zA-Z_][a-zA-Z0-9_]*$"
db_hosted_zone: db.example.com
debug_logging: "true"
# default_cpu_limit: "1"
Expand Down
3 changes: 3 additions & 0 deletions manifests/operatorconfiguration.crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ spec:
nullable: true
items:
type: string
database_name_regexp:
type: string
default: "^[a-zA-Z_][a-zA-Z0-9_]*$"
docker_image:
type: string
default: "ghcr.io/zalando/spilo-15:2.1-p9"
Expand Down
5 changes: 3 additions & 2 deletions pkg/apis/acid.zalan.do/v1/operator_configuration_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ package v1
// Operator configuration CRD definition, please use snake_case for field names.

import (
"github.com/zalando/postgres-operator/pkg/util/config"

"time"

"github.com/zalando/postgres-operator/pkg/util/config"

"github.com/zalando/postgres-operator/pkg/spec"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -102,6 +102,7 @@ type KubernetesMetaConfiguration struct {
PodManagementPolicy string `json:"pod_management_policy,omitempty"`
EnableReadinessProbe bool `json:"enable_readiness_probe,omitempty"`
EnableCrossNamespaceSecret bool `json:"enable_cross_namespace_secret,omitempty"`
DatabaseNameRegexp string `json:"database_name_regexp" default:"^[a-zA-Z_][a-zA-Z0-9_]*$"`
}

// PostgresPodResourcesDefaults defines the spec of default resources
Expand Down
7 changes: 7 additions & 0 deletions pkg/cluster/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,10 @@ func (c *Cluster) Create() error {
c.eventRecorder.Eventf(c.GetReference(), v1.EventTypeNormal, "Services", "The service %q for role %s has been successfully created", util.NameFromMeta(service.ObjectMeta), role)
}

if err = c.readValidateDatabaseNameRegexp(c.OpConfig.DatabaseNameRegexp); err != nil {
return err
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should rather place the existing validation.

if err = c.initUsers(); err != nil {
return err
}
Expand Down Expand Up @@ -337,6 +341,7 @@ func (c *Cluster) Create() error {
// that feature explicitly
if !(c.databaseAccessDisabled() || c.getNumberOfInstances(&c.Spec) <= 0 || c.Spec.StandbyCluster != nil) {
c.logger.Infof("Create roles")

Copy link
Member

@FxKu FxKu Apr 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please do not introduce unrelated changes - even these are just blank lines

if err = c.createRoles(); err != nil {
return fmt.Errorf("could not create users: %v", err)
}
Expand All @@ -345,9 +350,11 @@ func (c *Cluster) Create() error {
if err = c.syncDatabases(); err != nil {
return fmt.Errorf("could not sync databases: %v", err)
}

if err = c.syncPreparedDatabases(); err != nil {
return fmt.Errorf("could not sync prepared databases: %v", err)
}

c.logger.Infof("databases have been successfully created")
}

Expand Down
1 change: 1 addition & 0 deletions pkg/cluster/cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ var cl = New(
Resources: config.Resources{
DownscalerAnnotations: []string{"downscaler/*"},
},
DatabaseNameRegexp: "^[a-zA-Z_][a-zA-Z0-9_]*$",
},
},
k8sutil.NewMockKubernetesClient(),
Expand Down
19 changes: 19 additions & 0 deletions pkg/cluster/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"database/sql"
"fmt"
"net"
"regexp"
"strings"
"text/template"
"time"
Expand Down Expand Up @@ -415,6 +416,24 @@ func (c *Cluster) executeCreateDatabaseSchema(databaseName, schemaName, dbOwner
"creating database schema", "create database schema")
}

// readValidateDatabaseNameRegexp validates the regex expression. If the validation was
// successful, it sets the global regex object variable for validation.
func (c *Cluster) readValidateDatabaseNameRegexp(expr string) error {
if !(len(expr) > 0) {
return fmt.Errorf("The regex expression for the database name validation is not set")
}

regex, err := regexp.Compile(expr)
if err != nil {
return fmt.Errorf("The regex expression %q for the database name validation is not correct", expr)
}

databaseNameRegexp = regex
c.logger.Infof("regexp for database name/schema validation has been initialized")

return nil
}

func (c *Cluster) execCreateDatabaseSchema(databaseName, schemaName, dbOwner, schemaOwner, statement, doing, operation string) error {
if !c.databaseSchemaNameValid(schemaName) {
return nil
Expand Down
31 changes: 31 additions & 0 deletions pkg/cluster/database_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package cluster

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestReadValidateDatabaseNameRegexp(t *testing.T) {
tests := []struct {
name string
expression string
wantErrMsg string
}{
{"default value", databaseNameRegexp.String(), ""},
{"null value", "", "validation is not set"},
{"wrong expression", "12(@3202@@!)#)$$%#$_!@@!_*%_@", "validation is not correct"},
{"correct expression", "^[a-z0-9]([-_a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-_a-z0-9]*[a-z0-9])?)*$", ""},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := cl.readValidateDatabaseNameRegexp(tt.expression)
if len(tt.wantErrMsg) > 0 {
assert.Containsf(t, err.Error(), tt.wantErrMsg, "expected error containing %q, got %s", tt.wantErrMsg, err)
} else {
assert.Nil(t, err)
}
})
}
}
4 changes: 2 additions & 2 deletions pkg/util/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@ package config

import (
"encoding/json"
"fmt"
"strings"
"time"

"fmt"

"github.com/zalando/postgres-operator/pkg/spec"
"github.com/zalando/postgres-operator/pkg/util/constants"
v1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -246,6 +245,7 @@ type Config struct {
PatroniAPICheckInterval time.Duration `name:"patroni_api_check_interval" default:"1s"`
PatroniAPICheckTimeout time.Duration `name:"patroni_api_check_timeout" default:"5s"`
EnablePatroniFailsafeMode *bool `name:"enable_patroni_failsafe_mode" default:"false"`
DatabaseNameRegexp string `name:"database_name_regexp" default:"^[a-zA-Z_][a-zA-Z0-9_]*$"`
}

// MustMarshal marshals the config or panics
Expand Down