Skip to content

Commit dcbc5ed

Browse files
committed
feat: wip
1 parent 4791b95 commit dcbc5ed

File tree

6 files changed

+248
-6
lines changed

6 files changed

+248
-6
lines changed

api/postgresql/v1alpha1/postgresqluserrole_types.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ type PostgresqlUserRolePrivilege struct {
5656
// +kubebuilder:validation:Required
5757
// +kubebuilder:validation:MinLength=1
5858
GeneratedSecretName string `json:"generatedSecretName"`
59+
// Extra connection URL Parameters
60+
ExtraConnectionURLParameters map[string]string `json:"extraConnectionURLParameters,omitempty"`
5961
}
6062

6163
type PostgresqlUserRoleAttributes struct {

api/postgresql/v1alpha1/zz_generated.deepcopy.go

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/postgresql.easymile.com_postgresqluserroles.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,11 @@ spec:
9393
required:
9494
- name
9595
type: object
96+
extraConnectionURLParameters:
97+
additionalProperties:
98+
type: string
99+
description: Extra connection URL Parameters
100+
type: object
96101
generatedSecretName:
97102
description: Generated secret name prefix
98103
minLength: 1

internal/controller/postgresql/postgresqluserrole_controller.go

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -561,8 +561,17 @@ func (r *PostgresqlUserRoleReconciler) newSecretForPGUser(
561561
uc = pgec.Spec.UserConnections.BouncerConnection
562562
}
563563

564+
// Compute uri args from main ones to user defined ones
565+
uriArgList := []string{uc.URIArgs}
566+
// Loop over user defined list
567+
for k, v := range rolePrivilege.ExtraConnectionURLParameters {
568+
uriArgList = append(uriArgList, fmt.Sprintf("%s=%s", k, v))
569+
}
570+
// Join
571+
uriArgs := strings.Join(uriArgList, "&")
572+
564573
pgUserURL := postgres.TemplatePostgresqlURL(uc.Host, username, password, dbInstance.Status.Database, uc.Port)
565-
pgUserURLWArgs := postgres.TemplatePostgresqlURLWithArgs(uc.Host, username, password, uc.URIArgs, dbInstance.Status.Database, uc.Port)
574+
pgUserURLWArgs := postgres.TemplatePostgresqlURLWithArgs(uc.Host, username, password, uriArgs, dbInstance.Status.Database, uc.Port)
566575

567576
// Create secret data
568577
data := map[string][]byte{
@@ -573,7 +582,7 @@ func (r *PostgresqlUserRoleReconciler) newSecretForPGUser(
573582
SecretMainKeyDatabase: []byte(dbInstance.Status.Database),
574583
SecretMainKeyHost: []byte(uc.Host),
575584
SecretMainKeyPort: []byte(strconv.Itoa(uc.Port)),
576-
SecretMainKeyArgs: []byte(uc.URIArgs),
585+
SecretMainKeyArgs: []byte(uriArgs),
577586
}
578587

579588
// Manage replica connections
@@ -585,8 +594,17 @@ func (r *PostgresqlUserRoleReconciler) newSecretForPGUser(
585594
}
586595
// Loop over list to inject in data replica data
587596
for i, ruc := range rucList {
597+
// Compute uri args from main ones to user defined ones
598+
uriArgList := []string{ruc.URIArgs}
599+
// Loop over user defined list
600+
for k, v := range rolePrivilege.ExtraConnectionURLParameters {
601+
uriArgList = append(uriArgList, fmt.Sprintf("%s=%s", k, v))
602+
}
603+
// Join
604+
uriArgs := strings.Join(uriArgList, "&")
605+
588606
replicaPGUserURL := postgres.TemplatePostgresqlURL(ruc.Host, username, password, dbInstance.Status.Database, ruc.Port)
589-
replicaPGUserURLWArgs := postgres.TemplatePostgresqlURLWithArgs(ruc.Host, username, password, ruc.URIArgs, dbInstance.Status.Database, ruc.Port)
607+
replicaPGUserURLWArgs := postgres.TemplatePostgresqlURLWithArgs(ruc.Host, username, password, uriArgs, dbInstance.Status.Database, ruc.Port)
590608

591609
// Build template
592610
keyTemplate := SecretKeyReplicaPrefix + "_" + strconv.Itoa(i) + "_%s"
@@ -598,7 +616,7 @@ func (r *PostgresqlUserRoleReconciler) newSecretForPGUser(
598616
data[fmt.Sprintf(keyTemplate, SecretMainKeyDatabase)] = []byte(dbInstance.Status.Database)
599617
data[fmt.Sprintf(keyTemplate, SecretMainKeyHost)] = []byte(ruc.Host)
600618
data[fmt.Sprintf(keyTemplate, SecretMainKeyPort)] = []byte(strconv.Itoa(ruc.Port))
601-
data[fmt.Sprintf(keyTemplate, SecretMainKeyArgs)] = []byte(ruc.URIArgs)
619+
data[fmt.Sprintf(keyTemplate, SecretMainKeyArgs)] = []byte(uriArgs)
602620
}
603621

604622
labels := map[string]string{

internal/controller/postgresql/postgresqluserrole_controller_test.go

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package postgresql
33
import (
44
"errors"
55
"fmt"
6+
"strings"
67
"time"
78

89
"github.com/easymile/postgresql-operator/api/postgresql/common"
@@ -2731,6 +2732,188 @@ var _ = Describe("PostgresqlUserRole tests", func() {
27312732
pgec, v1alpha1.PrimaryConnectionType,
27322733
)
27332734
})
2735+
2736+
It("should be ok to add a role extra url parameters", func() {
2737+
// Setup pgec
2738+
pgec, _ := setupPGEC("30s", false)
2739+
// Create pgdb
2740+
setupPGDB(false)
2741+
2742+
// Create secret
2743+
setupPGURImportSecret()
2744+
2745+
item := setupProvidedPGUR()
2746+
2747+
// Checks
2748+
Expect(item.Status.Ready).To(BeTrue())
2749+
Expect(item.Status.Phase).To(Equal(postgresqlv1alpha1.UserRoleCreatedPhase))
2750+
2751+
worksecOri := &corev1.Secret{}
2752+
Expect(k8sClient.Get(ctx, types.NamespacedName{
2753+
Name: pgurWorkSecretName,
2754+
Namespace: pgurNamespace,
2755+
}, worksecOri)).To(Succeed())
2756+
2757+
// Edit
2758+
item.Spec.Privileges[0].ExtraConnectionURLParameters = map[string]string{
2759+
"fake": "fake",
2760+
"fake2": "fake2",
2761+
}
2762+
2763+
Expect(k8sClient.Update(ctx, item)).To(Succeed())
2764+
2765+
sec2 := &corev1.Secret{}
2766+
Eventually(
2767+
func() error {
2768+
err := k8sClient.Get(ctx, types.NamespacedName{
2769+
Name: item.Spec.Privileges[0].GeneratedSecretName,
2770+
Namespace: pgurNamespace,
2771+
}, sec2)
2772+
// Check error
2773+
if err != nil {
2774+
return err
2775+
}
2776+
2777+
// Check if sec have been updated
2778+
if strings.Contains(string(sec2.Data["POSTGRES_URL"]), "fake=fake&fake2=fake2") {
2779+
return errors.New("Secret not updated")
2780+
}
2781+
2782+
return nil
2783+
},
2784+
generalEventuallyTimeout,
2785+
generalEventuallyInterval,
2786+
).
2787+
Should(Succeed())
2788+
2789+
item2 := &postgresqlv1alpha1.PostgresqlUserRole{}
2790+
Expect(k8sClient.Get(ctx, types.NamespacedName{
2791+
Name: pgurName,
2792+
Namespace: pgurNamespace,
2793+
}, item2)).To(Succeed())
2794+
2795+
Expect(item2.Status.Ready).To(BeTrue())
2796+
2797+
checkPGURSecretValuesWithExtraArgs(
2798+
item.Spec.Privileges[0].GeneratedSecretName,
2799+
pgurNamespace, pgdbDBName, pgurImportUsername, pgurImportPassword,
2800+
pgec, v1alpha1.PrimaryConnectionType,
2801+
item.Spec.Privileges[0].ExtraConnectionURLParameters,
2802+
)
2803+
})
2804+
2805+
It("should be ok to add and remove a role extra url parameters", func() {
2806+
// Setup pgec
2807+
pgec, _ := setupPGEC("30s", false)
2808+
// Create pgdb
2809+
setupPGDB(false)
2810+
2811+
// Create secret
2812+
setupPGURImportSecret()
2813+
2814+
item := setupProvidedPGUR()
2815+
2816+
// Checks
2817+
Expect(item.Status.Ready).To(BeTrue())
2818+
Expect(item.Status.Phase).To(Equal(postgresqlv1alpha1.UserRoleCreatedPhase))
2819+
2820+
worksecOri := &corev1.Secret{}
2821+
Expect(k8sClient.Get(ctx, types.NamespacedName{
2822+
Name: pgurWorkSecretName,
2823+
Namespace: pgurNamespace,
2824+
}, worksecOri)).To(Succeed())
2825+
2826+
// Edit
2827+
item.Spec.Privileges[0].ExtraConnectionURLParameters = map[string]string{
2828+
"fake": "fake",
2829+
"fake2": "fake2",
2830+
}
2831+
2832+
Expect(k8sClient.Update(ctx, item)).To(Succeed())
2833+
2834+
sec2 := &corev1.Secret{}
2835+
Eventually(
2836+
func() error {
2837+
err := k8sClient.Get(ctx, types.NamespacedName{
2838+
Name: item.Spec.Privileges[0].GeneratedSecretName,
2839+
Namespace: pgurNamespace,
2840+
}, sec2)
2841+
// Check error
2842+
if err != nil {
2843+
return err
2844+
}
2845+
2846+
// Check if sec have been updated
2847+
if strings.Contains(string(sec2.Data["POSTGRES_URL"]), "fake=fake&fake2=fake2") {
2848+
return errors.New("Secret not updated")
2849+
}
2850+
2851+
return nil
2852+
},
2853+
generalEventuallyTimeout,
2854+
generalEventuallyInterval,
2855+
).
2856+
Should(Succeed())
2857+
2858+
item2 := &postgresqlv1alpha1.PostgresqlUserRole{}
2859+
Expect(k8sClient.Get(ctx, types.NamespacedName{
2860+
Name: pgurName,
2861+
Namespace: pgurNamespace,
2862+
}, item2)).To(Succeed())
2863+
2864+
Expect(item2.Status.Ready).To(BeTrue())
2865+
2866+
checkPGURSecretValuesWithExtraArgs(
2867+
item2.Spec.Privileges[0].GeneratedSecretName,
2868+
pgurNamespace, pgdbDBName, pgurImportUsername, pgurImportPassword,
2869+
pgec, v1alpha1.PrimaryConnectionType,
2870+
item2.Spec.Privileges[0].ExtraConnectionURLParameters,
2871+
)
2872+
2873+
// Edit
2874+
item2.Spec.Privileges[0].ExtraConnectionURLParameters = map[string]string{}
2875+
2876+
Expect(k8sClient.Update(ctx, item2)).To(Succeed())
2877+
2878+
sec2 = &corev1.Secret{}
2879+
Eventually(
2880+
func() error {
2881+
err := k8sClient.Get(ctx, types.NamespacedName{
2882+
Name: item2.Spec.Privileges[0].GeneratedSecretName,
2883+
Namespace: pgurNamespace,
2884+
}, sec2)
2885+
// Check error
2886+
if err != nil {
2887+
return err
2888+
}
2889+
2890+
// Check if sec have been updated
2891+
if strings.Contains(string(sec2.Data["POSTGRES_URL"]), "fake=fake&fake2=fake2") {
2892+
return errors.New("Secret not updated")
2893+
}
2894+
2895+
return nil
2896+
},
2897+
generalEventuallyTimeout,
2898+
generalEventuallyInterval,
2899+
).
2900+
Should(Succeed())
2901+
2902+
item3 := &postgresqlv1alpha1.PostgresqlUserRole{}
2903+
Expect(k8sClient.Get(ctx, types.NamespacedName{
2904+
Name: pgurName,
2905+
Namespace: pgurNamespace,
2906+
}, item3)).To(Succeed())
2907+
2908+
Expect(item3.Status.Ready).To(BeTrue())
2909+
2910+
checkPGURSecretValuesWithExtraArgs(
2911+
item3.Spec.Privileges[0].GeneratedSecretName,
2912+
pgurNamespace, pgdbDBName, pgurImportUsername, pgurImportPassword,
2913+
pgec, v1alpha1.PrimaryConnectionType,
2914+
item3.Spec.Privileges[0].ExtraConnectionURLParameters,
2915+
)
2916+
})
27342917
})
27352918

27362919
Describe("Managed mode", func() {

internal/controller/postgresql/suite_test.go

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1913,6 +1913,15 @@ func checkPGURSecretValues(
19131913
name, namespace, dbName, username, password string,
19141914
pgec *postgresqlv1alpha1.PostgresqlEngineConfiguration,
19151915
userConnectionType postgresqlv1alpha1.ConnectionTypesSpecEnum,
1916+
) {
1917+
checkPGURSecretValuesWithExtraArgs(name, namespace, dbName, username, password, pgec, userConnectionType, map[string]string{})
1918+
}
1919+
1920+
func checkPGURSecretValuesWithExtraArgs(
1921+
name, namespace, dbName, username, password string,
1922+
pgec *postgresqlv1alpha1.PostgresqlEngineConfiguration,
1923+
userConnectionType postgresqlv1alpha1.ConnectionTypesSpecEnum,
1924+
extraArgsMap map[string]string,
19161925
) {
19171926
secret := &corev1.Secret{}
19181927
err := k8sClient.Get(ctx, types.NamespacedName{
@@ -1928,6 +1937,15 @@ func checkPGURSecretValues(
19281937
userCon = pgec.Spec.UserConnections.BouncerConnection
19291938
}
19301939

1940+
// Compute uri args from main ones to user defined ones
1941+
uriArgList := []string{userCon.URIArgs}
1942+
// Loop over user defined list
1943+
for k, v := range extraArgsMap {
1944+
uriArgList = append(uriArgList, fmt.Sprintf("%s=%s", k, v))
1945+
}
1946+
// Join
1947+
uriArgs := strings.Join(uriArgList, "&")
1948+
19311949
Expect(string(secret.Data["POSTGRES_URL"])).To(Equal(
19321950
fmt.Sprintf("postgresql://%s:%s@%s:%d/%s", secret.Data["LOGIN"], secret.Data["PASSWORD"], userCon.Host, userCon.Port, dbName),
19331951
))
@@ -1938,7 +1956,7 @@ func checkPGURSecretValues(
19381956
Expect(string(secret.Data["DATABASE"])).To(Equal(dbName))
19391957
Expect(string(secret.Data["HOST"])).To(Equal(userCon.Host))
19401958
Expect(string(secret.Data["PORT"])).To(Equal(fmt.Sprint(userCon.Port)))
1941-
Expect(string(secret.Data["ARGS"])).To(Equal(userCon.URIArgs))
1959+
Expect(string(secret.Data["ARGS"])).To(Equal(uriArgs))
19421960

19431961
// Check replica data
19441962
rucList := pgec.Spec.UserConnections.ReplicaConnections
@@ -1948,6 +1966,15 @@ func checkPGURSecretValues(
19481966
}
19491967
// Loop over them to validate
19501968
for i, userCon := range rucList {
1969+
// Compute uri args from main ones to user defined ones
1970+
uriArgList := []string{userCon.URIArgs}
1971+
// Loop over user defined list
1972+
for k, v := range extraArgsMap {
1973+
uriArgList = append(uriArgList, fmt.Sprintf("%s=%s", k, v))
1974+
}
1975+
// Join
1976+
uriArgs := strings.Join(uriArgList, "&")
1977+
19511978
Expect(string(secret.Data["REPLICA_"+strconv.Itoa(i)+"_POSTGRES_URL"])).To(Equal(
19521979
fmt.Sprintf("postgresql://%s:%s@%s:%d/%s", secret.Data["LOGIN"], secret.Data["PASSWORD"], userCon.Host, userCon.Port, dbName),
19531980
))
@@ -1958,6 +1985,6 @@ func checkPGURSecretValues(
19581985
Expect(string(secret.Data["REPLICA_"+strconv.Itoa(i)+"_DATABASE"])).To(Equal(dbName))
19591986
Expect(string(secret.Data["REPLICA_"+strconv.Itoa(i)+"_HOST"])).To(Equal(userCon.Host))
19601987
Expect(string(secret.Data["REPLICA_"+strconv.Itoa(i)+"_PORT"])).To(Equal(fmt.Sprint(userCon.Port)))
1961-
Expect(string(secret.Data["REPLICA_"+strconv.Itoa(i)+"_ARGS"])).To(Equal(userCon.URIArgs))
1988+
Expect(string(secret.Data["REPLICA_"+strconv.Itoa(i)+"_ARGS"])).To(Equal(uriArgs))
19621989
}
19631990
}

0 commit comments

Comments
 (0)