Skip to content

Commit

Permalink
feat: wip
Browse files Browse the repository at this point in the history
  • Loading branch information
oxyno-zeta committed Feb 27, 2024
1 parent 8567c44 commit 7e06d6a
Show file tree
Hide file tree
Showing 10 changed files with 567 additions and 36 deletions.
26 changes: 26 additions & 0 deletions api/postgresql/v1alpha1/postgresqlengineconfiguration_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,32 @@ type PostgresqlEngineConfigurationSpec struct {
// +kubebuilder:validation:Required
// +kubebuilder:validation:MinLength=1
SecretName string `json:"secretName"`
// User connections used for secret generation
// That will be used to generate secret with primary server as url or
// to use the pg bouncer one.
// Note: Operator won't check those values.
// +optional
UserConnections *UserConnections `json:"userConnections"`
}

type UserConnections struct {
// Primary connection is referring to the primary node connection.
// +optional
PrimaryConnection *GenericUserConnection `json:"primaryConnection,omitempty"`
// Bouncer connection is referring to a pg bouncer node.
// +optional
BouncerConnection *GenericUserConnection `json:"bouncerConnection,omitempty"`
}

type GenericUserConnection struct {
// Hostname
// +required
// +kubebuilder:validation:Required
Host string `json:"host"`
// URI args like sslmode, ...
URIArgs string `json:"uriArgs"`
// Port
Port int `json:"port,omitempty"`
}

type EngineStatusPhase string
Expand Down
11 changes: 11 additions & 0 deletions api/postgresql/v1alpha1/postgresqluserrole_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,18 @@ import (
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.

type ConnectionTypesSpecEnum string

const PrimaryConnectionType ConnectionTypesSpecEnum = "PRIMARY"
const BouncerConnectionType ConnectionTypesSpecEnum = "BOUNCER"

type PostgresqlUserRolePrivilege struct {
// User Connection type.
// This is referring to the user connection type needed for this user.
// +optional
// +kubebuilder:default=PRIMARY
// +kubebuilder:validation:Enum=PRIMARY;BOUNCER
ConnectionType ConnectionTypesSpecEnum `json:"connectionType,omitempty"`
// User privileges
// +required
// +kubebuilder:validation:Required
Expand Down
47 changes: 46 additions & 1 deletion api/postgresql/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,47 @@ spec:
uriArgs:
description: URI args like sslmode, ...
type: string
userConnections:
description: |-
User connections used for secret generation
That will be used to generate secret with primary server as url or
to use the pg bouncer one.
Note: Operator won't check those values.
properties:
bouncerConnection:
description: Bouncer connection is referring to a pg bouncer node.
properties:
host:
description: Hostname
type: string
port:
description: Port
type: integer
uriArgs:
description: URI args like sslmode, ...
type: string
required:
- host
- uriArgs
type: object
primaryConnection:
description: Primary connection is referring to the primary node
connection.
properties:
host:
description: Hostname
type: string
port:
description: Port
type: integer
uriArgs:
description: URI args like sslmode, ...
type: string
required:
- host
- uriArgs
type: object
type: object
waitLinkedResourcesDeletion:
description: Wait for linked resource to be deleted
type: boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,15 @@ spec:
spec:
description: PostgresqlUserRoleSpec defines the desired state of PostgresqlUserRole.
properties:
connectionType:
default: PRIMARY
description: |-
User Connection type.
This is referring to the user connection type needed for this user.
enum:
- PRIMARY
- BOUNCER
type: string
importSecretName:
description: Import secret name
type: string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import (

const (
PGECRequeueDelayErrorNumberSeconds = 5
DefaultPGPort = 5432
)

// PostgresqlEngineConfigurationReconciler reconciles a PostgresqlEngineConfiguration object.
Expand Down Expand Up @@ -275,7 +276,7 @@ func (r *PostgresqlEngineConfigurationReconciler) updateInstance(
func (*PostgresqlEngineConfigurationReconciler) addDefaultValues(instance *postgresqlv1alpha1.PostgresqlEngineConfiguration) {
// Check port
if instance.Spec.Port == 0 {
instance.Spec.Port = 5432
instance.Spec.Port = DefaultPGPort
}
// Check default database
if instance.Spec.DefaultDatabase == "" {
Expand All @@ -286,6 +287,36 @@ func (*PostgresqlEngineConfigurationReconciler) addDefaultValues(instance *postg
if instance.Spec.CheckInterval == "" {
instance.Spec.CheckInterval = "30s"
}

// Check if user connections aren't set to init it
if instance.Spec.UserConnections == nil {
instance.Spec.UserConnections = &postgresqlv1alpha1.UserConnections{}
}

// Check if primary user connections aren't set to init it
if instance.Spec.UserConnections.PrimaryConnection == nil {
instance.Spec.UserConnections.PrimaryConnection = &postgresqlv1alpha1.GenericUserConnection{
Host: instance.Spec.Host,
URIArgs: instance.Spec.URIArgs,
Port: instance.Spec.Port,
}
}

// Check if primary user connections are set and fully valued
if instance.Spec.UserConnections.PrimaryConnection != nil {
// Check port
if instance.Spec.UserConnections.PrimaryConnection.Port == 0 {
instance.Spec.UserConnections.PrimaryConnection.Port = DefaultPGPort
}
}

// Check if bouncer user connections are set and fully valued
if instance.Spec.UserConnections.BouncerConnection != nil {
// Check port
if instance.Spec.UserConnections.BouncerConnection.Port == 0 {
instance.Spec.UserConnections.BouncerConnection.Port = DefaultPGPort
}
}
}

func (r *PostgresqlEngineConfigurationReconciler) manageError(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ var _ = Describe("PostgresqlEngineConfiguration tests", func() {
Expect(updatedPgec.Status.Message).To(BeEquivalentTo(`secret ` + pgecSecretName + ` must contain "user" and "password" values`))
})

It("should be ok to set default values", func() {
It("should be ok to set default values (minimal pgec)", func() {
// Create secret
sec := setupPGECSecret()

Expand Down Expand Up @@ -337,6 +337,95 @@ var _ = Describe("PostgresqlEngineConfiguration tests", func() {
Expect(updatedPgec.Spec.CheckInterval).To(BeEquivalentTo("30s"))
Expect(updatedPgec.Spec.Port).To(BeEquivalentTo(5432))
Expect(updatedPgec.Spec.DefaultDatabase).To(BeEquivalentTo("postgres"))
Expect(updatedPgec.Spec.UserConnections.PrimaryConnection.Host).To(BeEquivalentTo("localhost"))
Expect(updatedPgec.Spec.UserConnections.PrimaryConnection.Port).To(BeEquivalentTo(5432))
Expect(updatedPgec.Spec.UserConnections.PrimaryConnection.URIArgs).To(BeEquivalentTo("sslmode=disable"))
Expect(updatedPgec.Spec.UserConnections.BouncerConnection).To(BeNil())
})

It("should be ok to create it with only bouncer user connections", func() {
// Create secret
sec := setupPGECSecret()

// Get secret to be sure
Eventually(
func() error {
return k8sClient.Get(ctx, types.NamespacedName{
Name: sec.Name,
Namespace: sec.Namespace,
}, sec)
},
generalEventuallyTimeout,
generalEventuallyInterval,
).
Should(Succeed())

// Create pgec
prov := &postgresqlv1alpha1.PostgresqlEngineConfiguration{
ObjectMeta: v1.ObjectMeta{
Name: pgecName,
Namespace: pgecNamespace,
},
Spec: postgresqlv1alpha1.PostgresqlEngineConfigurationSpec{
Provider: "",
Host: "localhost",
Port: 5432,
URIArgs: "sslmode=disable",
DefaultDatabase: "postgres",
CheckInterval: "30s",
SecretName: pgecSecretName,
UserConnections: &postgresqlv1alpha1.UserConnections{
BouncerConnection: &postgresqlv1alpha1.GenericUserConnection{
Host: "localhost",
Port: 5432,
URIArgs: "sslmode=disable",
},
},
},
}

// Create pgec
Expect(k8sClient.Create(ctx, prov)).Should(Succeed())

updatedPgec := &postgresqlv1alpha1.PostgresqlEngineConfiguration{}
// Get updated pgec
Eventually(
func() error {
err := k8sClient.Get(ctx, types.NamespacedName{
Name: pgecName,
Namespace: pgecNamespace,
}, updatedPgec)
// Check error
if err != nil {
return err
}

// Check if status hasn't been updated
if updatedPgec.Status.Phase == postgresqlv1alpha1.EngineNoPhase {
return errors.New("pgec hasn't been updated by operator")
}

return nil
},
generalEventuallyTimeout,
generalEventuallyInterval,
).
Should(Succeed())

// Checks
Expect(updatedPgec.Status.Ready).To(BeTrue())
Expect(updatedPgec.Status.Phase).To(BeEquivalentTo(postgresqlv1alpha1.EngineValidatedPhase))
Expect(updatedPgec.Status.LastValidatedTime).NotTo(BeEquivalentTo(""))
Expect(updatedPgec.Status.Message).To(BeEquivalentTo(""))
Expect(updatedPgec.Spec.CheckInterval).To(BeEquivalentTo("30s"))
Expect(updatedPgec.Spec.Port).To(BeEquivalentTo(5432))
Expect(updatedPgec.Spec.DefaultDatabase).To(BeEquivalentTo("postgres"))
Expect(updatedPgec.Spec.UserConnections.PrimaryConnection.Host).To(BeEquivalentTo("localhost"))
Expect(updatedPgec.Spec.UserConnections.PrimaryConnection.Port).To(BeEquivalentTo(5432))
Expect(updatedPgec.Spec.UserConnections.PrimaryConnection.URIArgs).To(BeEquivalentTo("sslmode=disable"))
Expect(updatedPgec.Spec.UserConnections.BouncerConnection.Host).To(BeEquivalentTo("localhost"))
Expect(updatedPgec.Spec.UserConnections.BouncerConnection.Port).To(BeEquivalentTo(5432))
Expect(updatedPgec.Spec.UserConnections.BouncerConnection.URIArgs).To(BeEquivalentTo("sslmode=disable"))
})

It("should be ok to set everything", func() {
Expand Down
Loading

0 comments on commit 7e06d6a

Please sign in to comment.