diff --git a/Dockerfile b/Dockerfile index e564b0639..6bc5b3eba 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,6 +14,7 @@ COPY main.go main.go COPY apis/ apis/ COPY pkg/ pkg/ COPY controllers/ controllers/ +COPY webhooks/ webhooks/ # Build RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -o manager main.go diff --git a/Makefile b/Makefile index eb6c9c33e..6fe78bd6a 100644 --- a/Makefile +++ b/Makefile @@ -125,9 +125,9 @@ ENVTEST_ASSETS_DIR=$(shell pwd)/testbin test: manifests generate fmt vet envtest ## Run tests. ifdef TEST @echo Running test $(TEST) - KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path)" go test $(GO_FLAGS) ./apis/... ./pkg/... ./test/yq/... ./controllers/... -run="$(TEST)" -coverprofile cover.out + KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path)" go test $(GO_FLAGS) ./webhooks/... ./apis/... ./pkg/... ./test/yq/... ./controllers/... -run="$(TEST)" -coverprofile cover.out else - KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path)" go test $(GO_FLAGS) ./apis/... ./pkg/... ./test/yq/... ./controllers/... -coverprofile cover.out + KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path)" go test $(GO_FLAGS) ./webhooks/... ./apis/... ./pkg/... ./test/yq/... ./controllers/... -coverprofile cover.out endif PHONY: e2e-test diff --git a/main.go b/main.go index 8f8534201..d4f75c7bf 100644 --- a/main.go +++ b/main.go @@ -20,6 +20,7 @@ import ( "context" "flag" "fmt" + "github.com/k8ssandra/k8ssandra-operator/webhooks" "os" "strings" @@ -172,7 +173,7 @@ func main() { setupLog.Error(err, "unable to create controller", "controller", "K8ssandraCluster") os.Exit(1) } - if err = (&k8ssandraiov1alpha1.K8ssandraCluster{}).SetupWebhookWithManager(mgr, clientCache); err != nil { + if err = (&webhooks.ValidatedK8ssandraCluster{}).SetupWebhookWithManager(mgr, clientCache); err != nil { setupLog.Error(err, "unable to create webhook", "webhook", "K8ssandraCluster") os.Exit(1) } diff --git a/pkg/test/testenv.go b/pkg/test/testenv.go index d853ef9fb..33cb5dc75 100644 --- a/pkg/test/testenv.go +++ b/pkg/test/testenv.go @@ -14,6 +14,7 @@ import ( "go.uber.org/zap" reaperapi "github.com/k8ssandra/k8ssandra-operator/apis/reaper/v1alpha1" + "github.com/k8ssandra/k8ssandra-operator/webhooks" promapi "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" "github.com/k8ssandra/k8ssandra-operator/pkg/clientcache" @@ -99,7 +100,7 @@ func (e *TestEnv) Start(ctx context.Context, t *testing.T, initReconcilers func( e.TestClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) clientCache := clientcache.New(e.TestClient, e.TestClient, scheme.Scheme) - err = (&api.K8ssandraCluster{}).SetupWebhookWithManager(k8sManager, clientCache) + err = (&webhooks.ValidatedK8ssandraCluster{}).SetupWebhookWithManager(k8sManager, clientCache) if err != nil { return err } @@ -250,7 +251,7 @@ func (e *MultiClusterTestEnv) Start(ctx context.Context, t *testing.T, initRecon } } - err = (&api.K8ssandraCluster{}).SetupWebhookWithManager(k8sManager, clientCache) + err = (&webhooks.ValidatedK8ssandraCluster{}).SetupWebhookWithManager(k8sManager, clientCache) if err != nil { return err } diff --git a/apis/k8ssandra/v1alpha1/k8ssandracluster_webhook.go b/webhooks/k8ssandracluster_webhook.go similarity index 86% rename from apis/k8ssandra/v1alpha1/k8ssandracluster_webhook.go rename to webhooks/k8ssandracluster_webhook.go index d6a69e7f6..059b650d1 100644 --- a/apis/k8ssandra/v1alpha1/k8ssandracluster_webhook.go +++ b/webhooks/k8ssandracluster_webhook.go @@ -14,10 +14,11 @@ See the License for the specific language governing permissions and limitations under the License. */ -package v1alpha1 +package webhooks import ( "fmt" + "github.com/k8ssandra/k8ssandra-operator/apis/k8ssandra/v1alpha1" "github.com/k8ssandra/k8ssandra-operator/pkg/clientcache" "github.com/pkg/errors" @@ -35,36 +36,38 @@ var ( ErrNoResourcesSet = fmt.Errorf("softPodAntiAffinity requires Resources to be set") ) +type ValidatedK8ssandraCluster struct{ v1alpha1.K8ssandraCluster } + // log is for logging in this package. var webhookLog = logf.Log.WithName("k8ssandracluster-webhook") -func (r *K8ssandraCluster) SetupWebhookWithManager(mgr ctrl.Manager, cCache *clientcache.ClientCache) error { +func (r *ValidatedK8ssandraCluster) SetupWebhookWithManager(mgr ctrl.Manager, cCache *clientcache.ClientCache) error { clientCache = cCache return ctrl.NewWebhookManagedBy(mgr). For(r). Complete() } -var _ webhook.Defaulter = &K8ssandraCluster{} +var _ webhook.Defaulter = &ValidatedK8ssandraCluster{} // Default implements webhook.Defaulter so a webhook will be registered for the type -func (r *K8ssandraCluster) Default() { +func (r *ValidatedK8ssandraCluster) Default() { webhookLog.Info("K8ssandraCluster default values", "K8ssandraCluster", r.Name) } //+kubebuilder:webhook:path=/validate-k8ssandra-io-v1alpha1-k8ssandracluster,mutating=false,failurePolicy=fail,sideEffects=None,groups=k8ssandra.io,resources=k8ssandraclusters,verbs=create;update,versions=v1alpha1,name=vk8ssandracluster.kb.io,admissionReviewVersions=v1 -var _ webhook.Validator = &K8ssandraCluster{} +var _ webhook.Validator = &ValidatedK8ssandraCluster{} // ValidateCreate implements webhook.Validator so a webhook will be registered for the type -func (r *K8ssandraCluster) ValidateCreate() error { +func (r *ValidatedK8ssandraCluster) ValidateCreate() error { webhookLog.Info("validate K8ssandraCluster create", "K8ssandraCluster", r.Name) return r.validateK8ssandraCluster() } -func (r *K8ssandraCluster) validateK8ssandraCluster() error { +func (r *ValidatedK8ssandraCluster) validateK8ssandraCluster() error { hasClusterStorageConfig := r.Spec.Cassandra.StorageConfig != nil // Verify given k8s-contexts are correct for _, dc := range r.Spec.Cassandra.Datacenters { @@ -90,14 +93,14 @@ func (r *K8ssandraCluster) validateK8ssandraCluster() error { } // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type -func (r *K8ssandraCluster) ValidateUpdate(old runtime.Object) error { +func (r *ValidatedK8ssandraCluster) ValidateUpdate(old runtime.Object) error { webhookLog.Info("validate K8ssandraCluster update", "K8ssandraCluster", r.Name) if err := r.validateK8ssandraCluster(); err != nil { return err } - oldCluster, ok := old.(*K8ssandraCluster) + oldCluster, ok := old.(*v1alpha1.K8ssandraCluster) if !ok { return fmt.Errorf("previous object could not be casted to K8ssandraCluster") } @@ -147,7 +150,7 @@ func (r *K8ssandraCluster) ValidateUpdate(old runtime.Object) error { } // ValidateDelete implements webhook.Validator so a webhook will be registered for the type -func (r *K8ssandraCluster) ValidateDelete() error { +func (r *ValidatedK8ssandraCluster) ValidateDelete() error { webhookLog.Info("validate K8ssandraCluster delete", "name", r.Name) return nil } diff --git a/apis/k8ssandra/v1alpha1/k8ssandracluster_webhook_test.go b/webhooks/k8ssandracluster_webhook_test.go similarity index 91% rename from apis/k8ssandra/v1alpha1/k8ssandracluster_webhook_test.go rename to webhooks/k8ssandracluster_webhook_test.go index 1051fcf42..cbdbba512 100644 --- a/apis/k8ssandra/v1alpha1/k8ssandracluster_webhook_test.go +++ b/webhooks/k8ssandracluster_webhook_test.go @@ -14,12 +14,13 @@ See the License for the specific language governing permissions and limitations under the License. */ -package v1alpha1 +package webhooks import ( "context" "crypto/tls" "fmt" + "github.com/k8ssandra/k8ssandra-operator/apis/k8ssandra/v1alpha1" "net" "path/filepath" "testing" @@ -75,7 +76,7 @@ func TestWebhook(t *testing.T) { defer testEnv.Stop() scheme := runtime.NewScheme() - err = AddToScheme(scheme) + err = v1alpha1.AddToScheme(scheme) require.NoError(err) err = corev1.AddToScheme(scheme) @@ -84,7 +85,7 @@ func TestWebhook(t *testing.T) { err = admissionv1.AddToScheme(scheme) require.NoError(err) - err = AddToScheme(scheme) + err = v1alpha1.AddToScheme(scheme) require.NoError(err) err = reaperapi.AddToScheme(scheme) @@ -110,7 +111,7 @@ func TestWebhook(t *testing.T) { clientCache := clientcache.New(k8sClient, k8sClient, scheme) clientCache.AddClient("envtest", k8sClient) - err = (&K8ssandraCluster{}).SetupWebhookWithManager(mgr, clientCache) + err = (&ValidatedK8ssandraCluster{}).SetupWebhookWithManager(mgr, clientCache) require.NoError(err) //+kubebuilder:scaffold:webhook @@ -189,7 +190,7 @@ func testStorageConfigValidation(t *testing.T) { err = k8sClient.Update(ctx, cluster) require.NoError(err) - cluster.Spec.Cassandra.Datacenters = append(cluster.Spec.Cassandra.Datacenters, CassandraDatacenterTemplate{ + cluster.Spec.Cassandra.Datacenters = append(cluster.Spec.Cassandra.Datacenters, v1alpha1.CassandraDatacenterTemplate{ K8sContext: "envtest", Size: 1, }) @@ -208,7 +209,7 @@ func testNumTokens(t *testing.T) { cluster := createMinimalClusterObj("numtokens-test", "numtokens-namespace") // Create without token definition - cluster.Spec.Cassandra.CassandraConfig = &CassandraConfig{} + cluster.Spec.Cassandra.CassandraConfig = &v1alpha1.CassandraConfig{} err := k8sClient.Create(ctx, cluster) require.NoError(err) @@ -245,16 +246,16 @@ func createNamespace(require *require.Assertions, namespace string) { require.NoError(err) } -func createMinimalClusterObj(name, namespace string) *K8ssandraCluster { - return &K8ssandraCluster{ +func createMinimalClusterObj(name, namespace string) *v1alpha1.K8ssandraCluster { + return &v1alpha1.K8ssandraCluster{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: namespace, }, - Spec: K8ssandraClusterSpec{ - Cassandra: &CassandraClusterTemplate{ + Spec: v1alpha1.K8ssandraClusterSpec{ + Cassandra: &v1alpha1.CassandraClusterTemplate{ StorageConfig: &v1beta1.StorageConfig{}, - Datacenters: []CassandraDatacenterTemplate{ + Datacenters: []v1alpha1.CassandraDatacenterTemplate{ { K8sContext: "envtest", Size: 1,