Skip to content

Commit

Permalink
[KOGITO-7840] - Add validation on Workflow Metadata with admission we…
Browse files Browse the repository at this point in the history
…bhooks

Signed-off-by: Spolti <[email protected]>
  • Loading branch information
spolti committed Aug 22, 2023
1 parent cf61e86 commit d1379d0
Show file tree
Hide file tree
Showing 31 changed files with 904 additions and 127 deletions.
33 changes: 21 additions & 12 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,10 @@ build: generate ## Build manager binary.
build-4-debug: generate ## Build manager binary with debug options.
go build -gcflags="all=-N -l" -o bin/manager main.go

ENABLE_WEBHOOKS ?= false
.PHONY: run
run: manifests generate ## Run a controller from your host.
go run ./main.go
ENABLE_WEBHOOKS=${ENABLE_WEBHOOKS} go run ./main.go

.PHONY: debug
debug: build-4-debug ## Run a controller from your host from binary
Expand All @@ -159,6 +160,10 @@ podman-build: test ## Build container image with the manager.
docker-push: ## Push docker image with the manager.
docker push ${IMG}

.PHONY: podman-push
podman-push: ## Push container image with the manager.
podman push ${PODMAN_PUSH_PARAMS} ${IMG}

# This is currently done directly into the CI
# PLATFORMS defines the target platforms for the manager image be build to provide support to multiple
# architectures. (i.e. make docker-buildx IMG=myregistry/mypoperator:0.0.1). To use this option you need to:
Expand All @@ -177,10 +182,6 @@ docker-buildx: test ## Build and push docker image for the manager for cross-pla
- docker buildx rm project-v3-builder
rm Dockerfile.cross

.PHONY: podman-push
podman-push: ## Push container image with the manager.
podman push ${PODMAN_PUSH_PARAMS} ${IMG}

.PHONY: container-build
container-build: test ## Build the container image
cekit -v --descriptor image.yaml build ${build_options} $(BUILDER)
Expand All @@ -207,19 +208,19 @@ uninstall: manifests kustomize ## Uninstall CRDs from the K8s cluster specified
$(KUSTOMIZE) build config/crd | kubectl delete --ignore-not-found=$(ignore-not-found) -f -

.PHONY: deploy
deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config.
deploy: manifests kustomize install-cert-manager ## Deploy controller to the K8s cluster specified in ~/.kube/config.
cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
$(KUSTOMIZE) build config/default | kubectl apply -f -

.PHONY: undeploy
undeploy: uninstall-cert-manager ## Undeploy controller from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
$(KUSTOMIZE) build config/default | kubectl delete --ignore-not-found=$(ignore-not-found) -f -

.PHONY: generate-deploy
generate-deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config.
cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
$(KUSTOMIZE) build config/default > operator.yaml

.PHONY: undeploy
undeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
$(KUSTOMIZE) build config/default | kubectl delete --ignore-not-found=$(ignore-not-found) -f -

##@ Build Dependencies

## Location to install dependencies to
Expand Down Expand Up @@ -265,7 +266,7 @@ bundle-build: ## Build the bundle image.

.PHONY: bundle-push
bundle-push: ## Push the bundle image.
$(MAKE) contianer-push IMG=$(BUNDLE_IMG)
$(MAKE) container-push IMG=$(BUNDLE_IMG)

.PHONY: opm
OPM = ./bin/opm
Expand Down Expand Up @@ -333,4 +334,12 @@ test-e2e: install-operator-sdk
go test ./test/e2e/* -v -ginkgo.v

.PHONY: before-pr
before-pr: test generate-all
before-pr: test generate-all

.PHONY: install-cert-manager
install-cert-manager:
./hack/local/cert-manager.sh install

.PHONY: uninstall-cert-manager
uninstall-cert-manager:
./hack/local/cert-manager.sh uninstall
4 changes: 4 additions & 0 deletions PROJECT
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ resources:
kind: SonataFlow
path: github.com/kiegroup/kogito-serverless-operator/api/v1alpha08
version: v1alpha08
webhooks:
defaulting: true
validation: true
webhookVersion: v1
- api:
crdVersion: v1
namespaced: true
Expand Down
13 changes: 9 additions & 4 deletions api/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@ module github.com/kiegroup/kogito-serverless-operator/api
go 1.19

require (
github.com/onsi/ginkgo/v2 v2.9.5
github.com/onsi/gomega v1.27.7
github.com/serverlessworkflow/sdk-go/v2 v2.2.3
k8s.io/api v0.27.2
k8s.io/apimachinery v0.27.2
k8s.io/client-go v0.27.2
k8s.io/klog/v2 v2.100.1
knative.dev/pkg v0.0.0-20230525143525-9bda38b21643
sigs.k8s.io/controller-runtime v0.15.0
sigs.k8s.io/yaml v1.3.0
Expand All @@ -20,18 +24,21 @@ require (
github.com/evanphx/json-patch/v5 v5.6.0 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/go-logr/zapr v1.2.4 // indirect
github.com/go-openapi/jsonpointer v0.19.6 // indirect
github.com/go-openapi/jsonreference v0.20.1 // indirect
github.com/go-openapi/swag v0.22.3 // indirect
github.com/go-playground/locales v0.14.0 // indirect
github.com/go-playground/universal-translator v0.18.0 // indirect
github.com/go-playground/validator/v10 v10.11.1 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/gnostic v0.6.9 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/imdario/mergo v0.3.13 // indirect
github.com/josharian/intern v1.0.0 // indirect
Expand All @@ -52,25 +59,23 @@ require (
github.com/stretchr/testify v1.8.2 // indirect
go.uber.org/atomic v1.10.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
go.uber.org/zap v1.24.0 // indirect
golang.org/x/crypto v0.8.0 // indirect
golang.org/x/mod v0.10.0 // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/oauth2 v0.7.0 // indirect
golang.org/x/sync v0.2.0 // indirect
golang.org/x/sys v0.8.0 // indirect
golang.org/x/term v0.8.0 // indirect
golang.org/x/text v0.9.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.9.1 // indirect
gomodules.xyz/jsonpatch/v2 v2.3.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.30.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/apiextensions-apiserver v0.27.2 // indirect
k8s.io/client-go v0.27.2 // indirect
k8s.io/component-base v0.27.2 // indirect
k8s.io/klog/v2 v2.100.1 // indirect
k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f // indirect
k8s.io/utils v0.0.0-20230313181309-38a27ef9d749 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
Expand Down
2 changes: 1 addition & 1 deletion api/go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
Expand Down Expand Up @@ -160,7 +161,6 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
Expand Down
101 changes: 101 additions & 0 deletions api/v1alpha08/sonataflow_webhook.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// Copyright 2023 Red Hat, Inc. and/or its affiliates
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License

package v1alpha08

import (
"fmt"

cncfvalidator "github.com/serverlessworkflow/sdk-go/v2/validator"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/klog/v2"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/webhook"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"

"github.com/kiegroup/kogito-serverless-operator/api/metadata"
"github.com/kiegroup/kogito-serverless-operator/log"
)

func (r *SonataFlow) SetupWebhookWithManager(mgr ctrl.Manager) error {
return ctrl.NewWebhookManagedBy(mgr).
For(r).
Complete()
}

// Uncomment to enable the mutating webhook.
// Uncomment also the mutating webhook in the config/default/webhookcainjection_patch.yaml file.
// //+kubebuilder:webhook:path=/mutate-sonataflow-org-v1alpha08-sonataflow,mutating=true,failurePolicy=fail,sideEffects=None,groups=sonataflow.org,resources=sonataflows,verbs=create;update,versions=v1alpha08,name=msonataflow.kb.io,admissionReviewVersions=v1

var _ webhook.Defaulter = &SonataFlow{}

// Default implements webhook.Defaulter so a webhook will be registered for the type
func (s *SonataFlow) Default() {
klog.V(log.I).InfoS("Applying default values for ", "name", s.Name)
// Add defaults
if len(s.ObjectMeta.Annotations[metadata.Version]) == 0 {
s.ObjectMeta.Annotations[metadata.Key] = metadata.SpecVersion
}
klog.V(log.I).InfoS("BBBBBBB Applying default values for ", "specVersion", s.ObjectMeta.Annotations[metadata.Key])
}

// change verbs to "verbs=create;update;delete" if you want to enable deletion validation.
//+kubebuilder:webhook:path=/validate-sonataflow-org-v1alpha08-sonataflow,mutating=false,failurePolicy=fail,sideEffects=None,groups=sonataflow.org,resources=sonataflows,verbs=create;update,versions=v1alpha08,name=vsonataflow.kb.io,admissionReviewVersions=v1

var _ webhook.Validator = &SonataFlow{}

var requiredMetadataFields = [2]string{metadata.Description, metadata.Version}

// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
func (r *SonataFlow) ValidateCreate() (admission.Warnings, error) {
klog.V(log.I).InfoS("validate create", "name", r.Name)
return nil, validate(r)
}

// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
func (r *SonataFlow) ValidateUpdate(old runtime.Object) (admission.Warnings, error) {
klog.V(log.I).InfoS("validate update", "name", r.Name)
return nil, validate(r)
}

// ValidateDelete implements webhook.Validator so a webhook will be registered for the type
func (r *SonataFlow) ValidateDelete() (admission.Warnings, error) {
klog.V(log.I).InfoS("validate delete", "name", r.Name)
// TODO
return nil, nil
}

func validate(r *SonataFlow) error {
// validate the required metadata
response := "Field metadata.annotation.%s.%s not set."
var missingAnnotations []string
for _, field := range requiredMetadataFields {
if len(r.Annotations[field]) == 0 {
missingAnnotations = append(missingAnnotations, fmt.Sprintf(response, metadata.Domain, field))
}
}
if len(missingAnnotations) > 0 {
return fmt.Errorf("%+v", missingAnnotations)
}

klog.V(log.I).InfoS("Validating workflow", "flow", r.Spec.Flow)

validator := cncfvalidator.GetValidator()
fmt.Printf("validator: %+v", r.Spec.Flow)
if err := validator.Struct(r.Spec.Flow); err != nil {
return err
}

return nil
}
Loading

0 comments on commit d1379d0

Please sign in to comment.