diff --git a/apis/clusters/v1beta1/postgresql_webhook.go b/apis/clusters/v1beta1/postgresql_webhook.go index 903062490..51f567063 100644 --- a/apis/clusters/v1beta1/postgresql_webhook.go +++ b/apis/clusters/v1beta1/postgresql_webhook.go @@ -20,8 +20,10 @@ import ( "context" "fmt" + k8sCore "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/webhook" @@ -32,13 +34,15 @@ import ( var postgresqllog = logf.Log.WithName("postgresql-resource") type pgValidator struct { - API validation.Validation + API validation.Validation + K8sClient client.Client } func (r *PostgreSQL) SetupWebhookWithManager(mgr ctrl.Manager, api validation.Validation) error { return ctrl.NewWebhookManagedBy(mgr). For(r).WithValidator(webhook.CustomValidator(&pgValidator{ - API: api, + API: api, + K8sClient: mgr.GetClient(), })). Complete() } @@ -87,6 +91,13 @@ func (pgv *pgValidator) ValidateCreate(ctx context.Context, obj runtime.Object) return err } + if pg.Spec.UserRefs != nil { + err = pgv.validatePostgreSQLUsers(ctx, pg) + if err != nil { + return err + } + } + appVersions, err := pgv.API.ListAppVersions(models.PgAppKind) if err != nil { return fmt.Errorf("cannot list versions for kind: %v, err: %w", @@ -165,6 +176,13 @@ func (pgv *pgValidator) ValidateUpdate(ctx context.Context, old runtime.Object, return pgv.ValidateCreate(ctx, pg) } + if pg.Spec.UserRefs != nil { + err := pgv.validatePostgreSQLUsers(ctx, pg) + if err != nil { + return err + } + } + err := pg.Spec.ValidateImmutableFieldsUpdate(oldCluster.Spec) if err != nil { return fmt.Errorf("immutable fields validation error: %v", err) @@ -180,6 +198,32 @@ func (pgv *pgValidator) ValidateUpdate(ctx context.Context, old runtime.Object, return nil } +func (pgv *pgValidator) validatePostgreSQLUsers(ctx context.Context, pg *PostgreSQL) error { + nodeList := &k8sCore.NodeList{} + + err := pgv.K8sClient.List(ctx, nodeList, &client.ListOptions{}) + if err != nil { + return fmt.Errorf("cannot list node list, error: %v", err) + } + + var externalIPExists bool + for _, node := range nodeList.Items { + for _, nodeAddress := range node.Status.Addresses { + if nodeAddress.Type == k8sCore.NodeExternalIP { + externalIPExists = true + break + } + } + } + + if !externalIPExists || pg.Spec.PrivateNetworkCluster { + return fmt.Errorf("cannot create PostgreSQL user, if your cluster is private or has no external ips " + + "you need to configure peering and remove user references from cluster specification") + } + + return nil +} + // ValidateDelete implements webhook.Validator so a webhook will be registered for the type func (pgv *pgValidator) ValidateDelete(ctx context.Context, obj runtime.Object) error { pg, ok := obj.(*PostgreSQL)