From e217e9e0df5dd1ec7e40f45fcfc2e235fed4a700 Mon Sep 17 00:00:00 2001 From: yangsoon Date: Fri, 18 Jun 2021 23:40:12 +0800 Subject: [PATCH] add autoGenWorkloadDefinition option (#1804) add autoGenWorkloadDefinition option to choose whether to create workloaddef via webhook --- .../templates/kubevela-controller.yaml | 1 + charts/vela-core/values.yaml | 2 + cmd/core/main.go | 1 + .../api/vela-controller-params-reference.md | 27 ++++++++++++++ .../core.oam.dev/oamruntime_controller.go | 3 ++ .../componentdefinition/mutating_handler.go | 37 ++++++++++++++----- 6 files changed, 61 insertions(+), 10 deletions(-) create mode 100644 design/api/vela-controller-params-reference.md diff --git a/charts/vela-core/templates/kubevela-controller.yaml b/charts/vela-core/templates/kubevela-controller.yaml index f82f925f1..bb256beaf 100644 --- a/charts/vela-core/templates/kubevela-controller.yaml +++ b/charts/vela-core/templates/kubevela-controller.yaml @@ -118,6 +118,7 @@ spec: - "--use-webhook=true" - "--webhook-port={{ .Values.webhookService.port }}" - "--webhook-cert-dir={{ .Values.admissionWebhooks.certificate.mountPath }}" + - "--autogen-workload-definition={{ .Values.admissionWebhooks.autoGenWorkloadDefinition }}" {{ end }} {{ if not .Values.useAppConfig }} - "--app-config-installed=false" diff --git a/charts/vela-core/values.yaml b/charts/vela-core/values.yaml index 6244e0a16..642019a78 100644 --- a/charts/vela-core/values.yaml +++ b/charts/vela-core/values.yaml @@ -77,6 +77,8 @@ admissionWebhooks: tolerations: [] certManager: enabled: false + # If autoGenWorkloadDefinition is true, webhook will auto generated workloadDefinition which componentDefinition refers to + autoGenWorkloadDefinition: true #Enable debug logs for development purpose logDebug: false diff --git a/cmd/core/main.go b/cmd/core/main.go index 23843e0e7..72d5ca1a0 100644 --- a/cmd/core/main.go +++ b/cmd/core/main.go @@ -91,6 +91,7 @@ func main() { "custom-revision-hook-url is a webhook url which will let KubeVela core to call with applicationConfiguration and component info and return a customized component revision") flag.BoolVar(&controllerArgs.ApplicationConfigurationInstalled, "app-config-installed", true, "app-config-installed indicates if applicationConfiguration CRD is installed") + flag.BoolVar(&controllerArgs.AutoGenWorkloadDefinition, "autogen-workload-definition", true, "Automatic generated workloadDefinition which componentDefinition refers to.") flag.StringVar(&healthAddr, "health-addr", ":9440", "The address the health endpoint binds to.") flag.StringVar(&applyOnceOnly, "apply-once-only", "false", "For the purpose of some production environment that workload or trait should not be affected if no spec change, available options: on, off, force.") diff --git a/design/api/vela-controller-params-reference.md b/design/api/vela-controller-params-reference.md new file mode 100644 index 000000000..03d10932e --- /dev/null +++ b/design/api/vela-controller-params-reference.md @@ -0,0 +1,27 @@ +# KubeVela Controller Parameters Reference + +| parameter | type | default | describe | +| :-------------------------: | :----: | :-------------------------------: | :----------------------------------------------------------: | +| use-webhook | bool | false | Enable Admission Webhook | +| webhook-cert-dir | string | /k8s-webhook-server/serving-certs | Admission webhook cert/key dir. | +| webhook-port | int | 9443 | Admission webhook listen address | +| metrics-addr | string | :8080 | The address the metric endpoint binds to. | +| enable-leader-election | bool | false | Enable leader election for controller manager. Enabling this will ensure there is only one active controller manager. | +| leader-election-namespace | string | "" | Determines the namespace in which the leader election configmap will be created. | +| log-file-path | string | "" | The file to write logs to. | +| log-file-max-size | int | 1024 | Defines the maximum size a log file can grow to, Unit is megabytes. | +| log-debug | bool | false | Enable debug logs for development purpose | +| revision-limit | int | 50 | revision-limit is the maximum number of revisions that will be maintained. The default value is 50. | +| application-revision-limit | int | 10 | application-revision-limit is the maximum number of application useless revisions that will be maintained, if the useless revisions exceed this number, older ones will be GCed first.The default value is 10. | +| definition-revision-limit | int | 20 | definition-revision-limit is the maximum number of component/trait definition useless revisions that will be maintained, if the useless revisions exceed this number, older ones will be GCed first.The default value is 20. | +| custom-revision-hook-url | string | "" | custom-revision-hook-url is a webhook url which will let KubeVela core to call with applicationConfiguration and component info and return a customized component revision | +| app-config-installed | bool | true | app-config-installed indicates if applicationConfiguration CRD is installed | +| autogen-workload-definition | bool | true | Automatic generated workloadDefinition which componentDefinition refers to | +| health-addr | string | :9440 | The address the health endpoint binds to. | +| apply-once-only | string | false | For the purpose of some production environment that workload or trait should not be affected if no spec change, available options: on, off, force. | +| disable-caps | string | "" | To be disabled builtin capability list. | +| storage-driver | string | Local | Application file save to the storage driver | +| informer-re-sync-interval | time | 2h | controller shared informer lister full re-sync period | +| system-definition-namespace | string | vela-system | define the namespace of the system-level definition | +| concurrent-reconciles | int | 4 | concurrent-reconciles is the concurrent reconcile number of the controller. | +| depend-check-wait | time | 30s | depend-check-wait is the time to wait for ApplicationConfiguration's dependent-resource ready. | \ No newline at end of file diff --git a/pkg/controller/core.oam.dev/oamruntime_controller.go b/pkg/controller/core.oam.dev/oamruntime_controller.go index 5d2a126dc..0b5d5ad3a 100644 --- a/pkg/controller/core.oam.dev/oamruntime_controller.go +++ b/pkg/controller/core.oam.dev/oamruntime_controller.go @@ -76,4 +76,7 @@ type Args struct { // DependCheckWait is the time to wait for ApplicationConfiguration's dependent-resource ready DependCheckWait time.Duration + + // AutoGenWorkloadDefinition indicates whether automatic generated workloadDefinition which componentDefinition refers to + AutoGenWorkloadDefinition bool } diff --git a/pkg/webhook/core.oam.dev/v1alpha2/componentdefinition/mutating_handler.go b/pkg/webhook/core.oam.dev/v1alpha2/componentdefinition/mutating_handler.go index ee6c39eb9..4b68939b5 100644 --- a/pkg/webhook/core.oam.dev/v1alpha2/componentdefinition/mutating_handler.go +++ b/pkg/webhook/core.oam.dev/v1alpha2/componentdefinition/mutating_handler.go @@ -19,6 +19,7 @@ package componentdefinition import ( "context" "encoding/json" + "fmt" "net/http" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -43,6 +44,8 @@ type MutatingHandler struct { Client client.Client // Decoder decodes objects Decoder *admission.Decoder + // AutoGenWorkloadDef indicates whether create workloadDef which componentDef refers to + AutoGenWorkloadDef bool } var _ admission.Handler = &MutatingHandler{} @@ -79,32 +82,44 @@ func (h *MutatingHandler) Mutate(obj *v1beta1.ComponentDefinition) error { klog.InfoS("mutate", "name", obj.Name) // If the Type field is not empty, it means that ComponentDefinition refers to an existing WorkloadDefinition - if obj.Spec.Workload.Type != "" { - return nil + if obj.Spec.Workload.Type != "" && obj.Spec.Workload.Definition == (common.WorkloadGVK{}) { + workloadDef := new(v1beta1.WorkloadDefinition) + return h.Client.Get(context.TODO(), client.ObjectKey{Name: obj.Spec.Workload.Type, Namespace: obj.Namespace}, workloadDef) } + if obj.Spec.Workload.Definition != (common.WorkloadGVK{}) { // If only Definition field exists, fill Type field according to Definition. defRef, err := util.ConvertWorkloadGVK2Definition(h.Mapper, obj.Spec.Workload.Definition) if err != nil { return err } - obj.Spec.Workload.Type = defRef.Name - // Create workloadDefinition which componentDefinition refers to + if obj.Spec.Workload.Type == "" { + obj.Spec.Workload.Type = defRef.Name + } + workloadDef := new(v1beta1.WorkloadDefinition) err = h.Client.Get(context.TODO(), client.ObjectKey{Name: defRef.Name, Namespace: obj.Namespace}, workloadDef) if err != nil { if apierrors.IsNotFound(err) { - workloadDef.SetName(defRef.Name) - workloadDef.SetNamespace(obj.Namespace) - workloadDef.Spec.Reference = defRef - return h.Client.Create(context.TODO(), workloadDef) + // Create workloadDefinition which componentDefinition refers to + if h.AutoGenWorkloadDef { + workloadDef.SetName(defRef.Name) + workloadDef.SetNamespace(obj.Namespace) + workloadDef.Spec.Reference = defRef + return h.Client.Create(context.TODO(), workloadDef) + } + + return fmt.Errorf("workloadDefinition %s referenced by componentDefinition is not found, please create the workloadDefinition first", defRef.Name) } return err } return nil } - obj.Spec.Workload.Type = types.AutoDetectWorkloadDefinition + + if obj.Spec.Workload.Type == "" { + obj.Spec.Workload.Type = types.AutoDetectWorkloadDefinition + } return nil } @@ -130,5 +145,7 @@ func (h *MutatingHandler) InjectClient(c client.Client) error { // RegisterMutatingHandler will register component mutation handler to the webhook func RegisterMutatingHandler(mgr manager.Manager, args controller.Args) { server := mgr.GetWebhookServer() - server.Register("/mutating-core-oam-dev-v1beta1-componentdefinitions", &webhook.Admission{Handler: &MutatingHandler{Mapper: args.DiscoveryMapper}}) + server.Register("/mutating-core-oam-dev-v1beta1-componentdefinitions", &webhook.Admission{ + Handler: &MutatingHandler{Mapper: args.DiscoveryMapper, AutoGenWorkloadDef: args.AutoGenWorkloadDefinition}, + }) }