Skip to content

Commit

Permalink
issue-588, check for no external IPs or private cluster in PostgreSQL…
Browse files Browse the repository at this point in the history
… webhook is implemented
  • Loading branch information
DoodgeMatvey committed Oct 9, 2023
1 parent e2401e3 commit 5ed2ebd
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 58 deletions.
48 changes: 46 additions & 2 deletions apis/clusters/v1beta1/postgresql_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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()
}
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand Down
56 changes: 0 additions & 56 deletions controllers/clusters/postgresql_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -296,62 +296,6 @@ func (r *PostgreSQLReconciler) handleCreateCluster(
return models.ReconcileRequeue
}

if pg.Spec.UserRefs != nil {
nodeList := &k8sCore.NodeList{}

err = r.List(ctx, nodeList, &client.ListOptions{})
if err != nil {
logger.Error(err, "Cannot list all nodes",
"cluster name", pg.Spec.Name,
"clusterID", pg.Status.ID,
)

r.EventRecorder.Eventf(
pg, models.Warning, models.CreationFailed,
"Fetching all nodes is failed. Reason: %v",
err,
)

return models.ReconcileRequeue
}

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 {
logger.Error(err, "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",
"cluster name", pg.Spec.Name,
"clusterID", pg.Status.ID,
)

r.EventRecorder.Eventf(
pg, models.Warning, models.CreationFailed,
"Creating PostgreSQL user has been failed. Reason: %v", err,
)

return models.ReconcileRequeue
}

err = r.startUsersCreationJob(pg)
if err != nil {
logger.Error(err, "Failed to start user PostreSQL creation job")
r.EventRecorder.Eventf(pg, models.Warning, models.CreationFailed,
"User creation job is failed. Reason: %v", err)
return models.ReconcileRequeue
}

r.EventRecorder.Event(pg, models.Normal, models.Created,
"Cluster user creation job is started")
}

return models.ExitReconcile
}

Expand Down

0 comments on commit 5ed2ebd

Please sign in to comment.