Skip to content

Commit

Permalink
Add validation of metadata in cell0 to webhook
Browse files Browse the repository at this point in the history
  • Loading branch information
mrkisaolamb committed May 30, 2023
1 parent 1fd76bf commit 926bde0
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 3 deletions.
37 changes: 35 additions & 2 deletions api/v1beta1/novacell_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,12 @@ package v1beta1

import (
"k8s.io/apimachinery/pkg/runtime"
apierrors "k8s.io/apimachinery/pkg/api/errors"
ctrl "sigs.k8s.io/controller-runtime"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/webhook"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apimachinery/pkg/runtime/schema"
)

// NovaCellDefaults -
Expand Down Expand Up @@ -80,6 +83,15 @@ func (spec *NovaCellSpec) Default() {
}
}


// ValidateMetadata validate metadata template
func (r *NovaCell) ValidateMetadata() *field.Error{
if r.Spec.CellName == "cell0" && *r.Spec.MetadataServiceTemplate.Replicas != 0{
return field.Forbidden(field.NewPath("spec").Child("MetadataServiceTemplate").Child("Replicas"), "should be 0 for cell0")
}
return nil
}

// NOTE: change verbs to "verbs=create;update;delete" if you want to enable deletion validation.
//+kubebuilder:webhook:path=/validate-nova-openstack-org-v1beta1-novacell,mutating=false,failurePolicy=fail,sideEffects=None,groups=nova.openstack.org,resources=novacells,verbs=create;update,versions=v1beta1,name=vnovacell.kb.io,admissionReviewVersions=v1

Expand All @@ -88,16 +100,37 @@ var _ webhook.Validator = &NovaCell{}
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
func (r *NovaCell) ValidateCreate() error {
novacelllog.Info("validate create", "name", r.Name)
var allErrs field.ErrorList

if err := r.ValidateMetadata(); err != nil {
allErrs = append(allErrs, err)
}

// TODO(user): fill in your validation logic upon object creation.
if len(allErrs) != 0 {
novacelllog.Info("validation failed", "name", r.Name)
return apierrors.NewInvalid(
schema.GroupKind{Group: "nova.openstack.org", Kind: "Nova"},
r.Name, allErrs)
}
return nil
}

// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
func (r *NovaCell) ValidateUpdate(old runtime.Object) error {
novacelllog.Info("validate update", "name", r.Name)

// TODO(user): fill in your validation logic upon object update.
var allErrs field.ErrorList

if err := r.ValidateMetadata(); err != nil {
allErrs = append(allErrs, err)
}

if len(allErrs) != 0 {
novacelllog.Info("validation failed", "name", r.Name)
return apierrors.NewInvalid(
schema.GroupKind{Group: "nova.openstack.org", Kind: "Nova"},
r.Name, allErrs)
}
return nil
}

Expand Down
47 changes: 46 additions & 1 deletion test/functional/nova_multicell_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -720,7 +720,7 @@ var _ = Describe("Nova multicell", func() {
cell0Template["cellDatabaseUser"] = "nova_cell0"

cell0Template["metadataServiceTemplate"] = map[string]interface{}{
"replicas": 1,
"replicas": 0,
}

cell1Template := GetDefaultNovaCellTemplate()
Expand Down Expand Up @@ -778,4 +778,49 @@ var _ = Describe("Nova multicell", func() {
)
})
})
When("Nova CR instance is created with metadata in cell0", func() {
BeforeEach(func() {
DeferCleanup(k8sClient.Delete, ctx, CreateNovaSecret(novaNames.NovaName.Namespace, SecretName))
DeferCleanup(
k8sClient.Delete,
ctx,
CreateNovaMessageBusSecret(cell0.CellName.Namespace, fmt.Sprintf("%s-secret", cell0.TransportURLName.Name)),
)

serviceSpec := corev1.ServiceSpec{Ports: []corev1.ServicePort{{Port: 3306}}}
DeferCleanup(th.DeleteDBService, th.CreateDBService(novaNames.APIMariaDBDatabaseName.Namespace, novaNames.APIMariaDBDatabaseName.Name, serviceSpec))
DeferCleanup(th.DeleteDBService, th.CreateDBService(cell0.MariaDBDatabaseName.Namespace, cell0.MariaDBDatabaseName.Name, serviceSpec))

spec := GetDefaultNovaSpec()
cell0Template := GetDefaultNovaCellTemplate()
cell0Template["cellDatabaseInstance"] = cell0.MariaDBDatabaseName.Name
cell0Template["cellDatabaseUser"] = "nova_cell0"

cell0Template["metadataServiceTemplate"] = map[string]interface{}{
"replicas": 1,
}

spec["cellTemplates"] = map[string]interface{}{
"cell0": cell0Template,
}
spec["metadataServiceTemplate"] = map[string]interface{}{
"replicas": 0,
}
spec["apiDatabaseInstance"] = novaNames.APIMariaDBDatabaseName.Name
spec["apiMessageBusInstance"] = cell0.TransportURLName.Name

DeferCleanup(th.DeleteInstance, CreateNova(novaNames.NovaName, spec))
keystoneAPIName := th.CreateKeystoneAPI(novaNames.NovaName.Namespace)
DeferCleanup(th.DeleteKeystoneAPI, keystoneAPIName)
keystoneAPI := th.GetKeystoneAPI(keystoneAPIName)
keystoneAPI.Status.APIEndpoints["internal"] = "http://keystone-internal-openstack.testing"
Eventually(func(g Gomega) {
g.Expect(k8sClient.Status().Update(ctx, keystoneAPI.DeepCopy())).Should(Succeed())
}, timeout, interval).Should(Succeed())
th.SimulateKeystoneServiceReady(novaNames.KeystoneServiceName)
})
It("cell0 never created", func() {
NovaCellNotExists(cell0.CellName)
})
})
})

0 comments on commit 926bde0

Please sign in to comment.