From 44bdf033ad51e282e87e83ec46035ef11e7bd115 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 18 Nov 2021 16:09:35 +0800 Subject: [PATCH] [Backport release-1.1] Fix: observability installation (#2735) * fix observability installation (cherry picked from commit 32646ea3b671c052a4174101761e4df5d08fdb67) * fix nil pointer (cherry picked from commit 29564fe264756142ca9f9120cd3871673ae18639) * fix nil pointer (cherry picked from commit 716d869dc551571e38f8bebb4213f9367356fd47) * remove asset, build in trait (cherry picked from commit acbeeb16e116e23b27ead87ae6b6deacb78a2774) Co-authored-by: qiaozp --- .../templates/addons/observability.yaml | 135 ++----------- .../import-grafana-dashboard.yaml | 39 ++++ .../defwithtemplate/pure-ingress.yaml | 56 ++++++ .../register-grafana-datasource.yaml | 48 +++++ .../import-grafana-dashboard.yaml | 39 ++++ .../defwithtemplate/pure-ingress.yaml | 56 ++++++ .../register-grafana-datasource.yaml | 48 +++++ docs/examples/obervability/README.md | 4 +- .../trait-import-grafana-dashboard.cue | 21 -- .../trait-register-grafana-datasource.cue | 31 --- references/cli/addon.go | 104 +++++----- .../addons/auto-gen/observability.yaml | 135 ++----------- .../addons/observability/template.yaml | 190 ++---------------- .../internal/import-grafana-dashboard.cue | 35 ++++ .../definitions/internal/pure-ingress.cue | 60 ++++++ .../internal/register-grafana-datasource.cue | 46 +++++ 16 files changed, 515 insertions(+), 532 deletions(-) create mode 100644 charts/vela-core/templates/defwithtemplate/import-grafana-dashboard.yaml create mode 100644 charts/vela-core/templates/defwithtemplate/pure-ingress.yaml create mode 100644 charts/vela-core/templates/defwithtemplate/register-grafana-datasource.yaml create mode 100644 charts/vela-minimal/templates/defwithtemplate/import-grafana-dashboard.yaml create mode 100644 charts/vela-minimal/templates/defwithtemplate/pure-ingress.yaml create mode 100644 charts/vela-minimal/templates/defwithtemplate/register-grafana-datasource.yaml delete mode 100644 docs/examples/obervability/trait-import-grafana-dashboard.cue delete mode 100644 docs/examples/obervability/trait-register-grafana-datasource.cue create mode 100644 vela-templates/definitions/internal/import-grafana-dashboard.cue create mode 100644 vela-templates/definitions/internal/pure-ingress.cue create mode 100644 vela-templates/definitions/internal/register-grafana-datasource.cue diff --git a/charts/vela-core/templates/addons/observability.yaml b/charts/vela-core/templates/addons/observability.yaml index 804e514b4..4b8e4d2ee 100644 --- a/charts/vela-core/templates/addons/observability.yaml +++ b/charts/vela-core/templates/addons/observability.yaml @@ -10,106 +10,13 @@ data: namespace: vela-system spec: components: - - name: ns-observability - properties: - apiVersion: v1 - kind: Namespace - metadata: - name: observability - type: raw - - name: import-grafana-dashboard-traitdef - properties: - apiVersion: core.oam.dev/v1beta1 - kind: TraitDefinition - metadata: - annotations: - definition.oam.dev/description: Import dashboards to Grafana - name: import-grafana-dashboard - namespace: vela-system - spec: - schematic: - cue: - template: "outputs: registerdatasource: {\n\tapiVersion: \"grafana.extension.oam.dev/v1alpha1\"\n\tkind: - \ \"ImportDashboard\"\n\tspec: {\n\t\tgrafana: {\n\t\t\tservice: - \ parameter.grafanaServiceName\n\t\t\tnamespace: parameter.grafanaServiceNamespace\n\t\t\tcredentialSecret: - \ parameter.credentialSecret\n\t\t\tcredentialSecretNamespace: - parameter.credentialSecretNamespace\n\t\t}\n\t\turls: parameter.urls\n\t}\n}\nparameter: - {\n\tgrafanaServiceName: string\n\tgrafanaServiceNamespace: *\"default\" - | string\n\tcredentialSecret: string\n\tcredentialSecretNamespace: - *\"default\" | string\n\turls: [...string]\n}\n" - type: raw - - name: pure-ingress-traitdef - properties: - apiVersion: core.oam.dev/v1beta1 - kind: TraitDefinition - metadata: - annotations: - definition.oam.dev/description: Enable public web traffic for the component - without creating a Service. - name: pure-ingress - namespace: vela-system - spec: - schematic: - cue: - template: "\noutputs: ingress: {\n\tapiVersion: \"networking.k8s.io/v1beta1\"\n\tkind: - \ \"Ingress\"\n\tmetadata:\n\t\tname: context.name\n\tspec: {\n\t\trules: - [{\n\t\t\thost: parameter.domain\n\t\t\thttp: {\n\t\t\t\tpaths: [\n\t\t\t\t\tfor - k, v in parameter.http {\n\t\t\t\t\t\tpath: k\n\t\t\t\t\t\tbackend: - {\n\t\t\t\t\t\t\tserviceName: context.name\n\t\t\t\t\t\t\tservicePort: - v\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t]\n\t\t\t}\n\t\t}]\n\t}\n}\n\nparameter: - {\n\t// +usage=Specify the domain you want to expose\n\tdomain: string\n\n\t// - +usage=Specify the mapping relationship between the http path and the - workload port\n\thttp: [string]: int\n}\n" - status: - customStatus: |- - let igs = context.outputs.ingress.status.loadBalancer.ingress - if igs == _|_ { - message: "No loadBalancer found, visiting by using 'vela port-forward " + context.appName + " --route'\n" - } - if len(igs) > 0 { - if igs[0].ip != _|_ { - message: "Visiting URL: " + context.outputs.ingress.spec.rules[0].host + ", IP: " + igs[0].ip - } - if igs[0].ip == _|_ { - message: "Visiting URL: " + context.outputs.ingress.spec.rules[0].host - } - } - healthPolicy: | - isHealth: len(context.outputs.ingress.status.loadBalancer.ingress) > 0 - type: raw - - name: register-grafana-datasource-traitdef - properties: - apiVersion: core.oam.dev/v1beta1 - kind: TraitDefinition - metadata: - annotations: - definition.oam.dev/description: Add a datasource to Grafana - name: register-grafana-datasource - namespace: vela-system - spec: - schematic: - cue: - template: "outputs: registerdatasource: {\n\tapiVersion: \"grafana.extension.oam.dev/v1alpha1\"\n\tkind: - \ \"DatasourceRegistration\"\n\tspec: {\n\t\tgrafana: {\n\t\t\tservice: - \ parameter.grafanaServiceName\n\t\t\tnamespace: parameter.grafanaServiceNamespace\n\t\t\tcredentialSecret: - \ parameter.credentialSecret\n\t\t\tcredentialSecretNamespace: - parameter.credentialSecretNamespace\n\t\t}\n\t\tdatasource: {\n\t\t\tname: - \ parameter.name\n\t\t\ttype: parameter.type\n\t\t\taccess: - \ parameter.access\n\t\t\tservice: parameter.service\n\t\t\tnamespace: - parameter.namespace\n\t\t}\n\t}\n}\n\nparameter: {\n\tgrafanaServiceName: - \ string\n\tgrafanaServiceNamespace: *\"default\" | string\n\tcredentialSecret: - \ string\n\tcredentialSecretNamespace: string\n\tname: string\n\ttype: - \ string\n\taccess: *\"proxy\" - | string\n\tservice: string\n\tnamespace: *\"default\" - | string\n}\n" - type: raw - name: grafana-registration properties: chart: ./chart git: branch: master repoType: git - targetNamespace: observability + targetNamespace: vela-system url: https://github.com/oam-dev/grafana-registration values: replicaCount: 1 @@ -119,7 +26,7 @@ data: chart: grafana releaseName: grafana repoType: helm - targetNamespace: observability + targetNamespace: vela-system url: https://charts.kubevela.net/addons version: 6.14.1 traits: @@ -130,9 +37,9 @@ data: type: pure-ingress - properties: credentialSecret: grafana - credentialSecretNamespace: observability + credentialSecretNamespace: vela-system grafanaServiceName: grafana - grafanaServiceNamespace: observability + grafanaServiceNamespace: vela-system urls: - https://charts.kubevela.net/addons/dashboards/kubevela_core_logging.json - https://charts.kubevela.net/addons/dashboards/kubevela_core_monitoring.json @@ -145,18 +52,18 @@ data: chart: loki-stack releaseName: loki repoType: helm - targetNamespace: observability + targetNamespace: vela-system url: https://charts.kubevela.net/addons version: 2.4.1 traits: - properties: access: proxy credentialSecret: grafana - credentialSecretNamespace: observability + credentialSecretNamespace: vela-system grafanaServiceName: grafana - grafanaServiceNamespace: observability + grafanaServiceNamespace: vela-system name: loki - namespace: observability + namespace: vela-system service: loki type: loki type: register-grafana-datasource @@ -166,7 +73,7 @@ data: chart: prometheus releaseName: prometheus repoType: helm - targetNamespace: observability + targetNamespace: vela-system url: https://charts.kubevela.net/addons values: alertmanager: @@ -184,11 +91,11 @@ data: - properties: access: proxy credentialSecret: grafana - credentialSecretNamespace: observability + credentialSecretNamespace: vela-system grafanaServiceName: grafana - grafanaServiceNamespace: observability + grafanaServiceNamespace: vela-system name: prometheus - namespace: observability + namespace: vela-system service: prometheus-server type: prometheus type: register-grafana-datasource @@ -197,7 +104,7 @@ data: properties: chart: kube-state-metrics repoType: helm - targetNamespace: observability + targetNamespace: vela-system url: https://charts.kubevela.net/addons values: image: @@ -212,22 +119,6 @@ data: name: fluxcd namespace: vela-system type: depends-on-app - - name: apply-ns - properties: - component: ns-observability - type: apply-component - - name: apply-trait-1 - properties: - component: import-grafana-dashboard-traitdef - type: apply-component - - name: apply-trait-2 - properties: - component: pure-ingress-traitdef - type: apply-component - - name: apply-trait-3 - properties: - component: register-grafana-datasource-traitdef - type: apply-component - name: apply-resources type: apply-remaining status: diff --git a/charts/vela-core/templates/defwithtemplate/import-grafana-dashboard.yaml b/charts/vela-core/templates/defwithtemplate/import-grafana-dashboard.yaml new file mode 100644 index 000000000..2f7809c84 --- /dev/null +++ b/charts/vela-core/templates/defwithtemplate/import-grafana-dashboard.yaml @@ -0,0 +1,39 @@ +# Code generated by KubeVela templates. DO NOT EDIT. Please edit the original cue file. +# Definition source cue file: vela-templates/definitions/internal/import-grafana-dashboard.cue +apiVersion: core.oam.dev/v1beta1 +kind: TraitDefinition +metadata: + annotations: + definition.oam.dev/description: Import dashboards to Grafana + name: import-grafana-dashboard + namespace: {{.Values.systemDefinitionNamespace}} +spec: + appliesToWorkloads: [] + conflictsWith: [] + podDisruptive: false + schematic: + cue: + template: | + outputs: registerdatasource: { + apiVersion: "grafana.extension.oam.dev/v1alpha1" + kind: "ImportDashboard" + spec: { + grafana: { + service: parameter.grafanaServiceName + namespace: parameter.grafanaServiceNamespace + credentialSecret: parameter.credentialSecret + credentialSecretNamespace: parameter.credentialSecretNamespace + } + urls: parameter.urls + } + } + parameter: { + grafanaServiceName: string + grafanaServiceNamespace: *"default" | string + credentialSecret: string + credentialSecretNamespace: *"default" | string + urls: [...string] + + } + workloadRefPath: "" + diff --git a/charts/vela-core/templates/defwithtemplate/pure-ingress.yaml b/charts/vela-core/templates/defwithtemplate/pure-ingress.yaml new file mode 100644 index 000000000..ca33a488f --- /dev/null +++ b/charts/vela-core/templates/defwithtemplate/pure-ingress.yaml @@ -0,0 +1,56 @@ +# Code generated by KubeVela templates. DO NOT EDIT. Please edit the original cue file. +# Definition source cue file: vela-templates/definitions/internal/pure-ingress.cue +apiVersion: core.oam.dev/v1beta1 +kind: TraitDefinition +metadata: + annotations: + definition.oam.dev/description: Enable public web traffic for the component without creating a Service. + name: pure-ingress + namespace: {{.Values.systemDefinitionNamespace}} +spec: + appliesToWorkloads: [] + conflictsWith: [] + podDisruptive: false + schematic: + cue: + template: | + outputs: ingress: { + apiVersion: "networking.k8s.io/v1beta1" + kind: "Ingress" + metadata: name: context.name + spec: rules: [{ + host: parameter.domain + http: paths: [ + for k, v in parameter.http { + path: k + backend: { + serviceName: context.name + servicePort: v + } + }, + ] + }] + } + parameter: { + // +usage=Specify the domain you want to expose + domain: string + + // +usage=Specify the mapping relationship between the http path and the workload port + http: [string]: int + } + status: + customStatus: |- + let igs = context.outputs.ingress.status.loadBalancer.ingress + if igs == _|_ { + message: "No loadBalancer found, visiting by using 'vela port-forward " + context.appName + " --route'\n" + } + if len(igs) > 0 { + if igs[0].ip != _|_ { + message: "Visiting URL: " + context.outputs.ingress.spec.rules[0].host + ", IP: " + igs[0].ip + } + if igs[0].ip == _|_ { + message: "Visiting URL: " + context.outputs.ingress.spec.rules[0].host + } + } + workloadRefPath: "" + diff --git a/charts/vela-core/templates/defwithtemplate/register-grafana-datasource.yaml b/charts/vela-core/templates/defwithtemplate/register-grafana-datasource.yaml new file mode 100644 index 000000000..25c18cfe0 --- /dev/null +++ b/charts/vela-core/templates/defwithtemplate/register-grafana-datasource.yaml @@ -0,0 +1,48 @@ +# Code generated by KubeVela templates. DO NOT EDIT. Please edit the original cue file. +# Definition source cue file: vela-templates/definitions/internal/register-grafana-datasource.cue +apiVersion: core.oam.dev/v1beta1 +kind: TraitDefinition +metadata: + annotations: + definition.oam.dev/description: Add a datasource to Grafana + name: register-grafana-datasource + namespace: {{.Values.systemDefinitionNamespace}} +spec: + appliesToWorkloads: [] + conflictsWith: [] + podDisruptive: false + schematic: + cue: + template: | + outputs: registerdatasource: { + apiVersion: "grafana.extension.oam.dev/v1alpha1" + kind: "DatasourceRegistration" + spec: { + grafana: { + service: parameter.grafanaServiceName + namespace: parameter.grafanaServiceNamespace + credentialSecret: parameter.credentialSecret + credentialSecretNamespace: parameter.credentialSecretNamespace + } + datasource: { + name: parameter.name + type: parameter.type + access: parameter.access + service: parameter.service + namespace: parameter.namespace + } + } + } + parameter: { + grafanaServiceName: string + grafanaServiceNamespace: *"default" | string + credentialSecret: string + credentialSecretNamespace: string + name: string + type: string + access: *"proxy" | string + service: string + namespace: *"default" | string + } + workloadRefPath: "" + diff --git a/charts/vela-minimal/templates/defwithtemplate/import-grafana-dashboard.yaml b/charts/vela-minimal/templates/defwithtemplate/import-grafana-dashboard.yaml new file mode 100644 index 000000000..2f7809c84 --- /dev/null +++ b/charts/vela-minimal/templates/defwithtemplate/import-grafana-dashboard.yaml @@ -0,0 +1,39 @@ +# Code generated by KubeVela templates. DO NOT EDIT. Please edit the original cue file. +# Definition source cue file: vela-templates/definitions/internal/import-grafana-dashboard.cue +apiVersion: core.oam.dev/v1beta1 +kind: TraitDefinition +metadata: + annotations: + definition.oam.dev/description: Import dashboards to Grafana + name: import-grafana-dashboard + namespace: {{.Values.systemDefinitionNamespace}} +spec: + appliesToWorkloads: [] + conflictsWith: [] + podDisruptive: false + schematic: + cue: + template: | + outputs: registerdatasource: { + apiVersion: "grafana.extension.oam.dev/v1alpha1" + kind: "ImportDashboard" + spec: { + grafana: { + service: parameter.grafanaServiceName + namespace: parameter.grafanaServiceNamespace + credentialSecret: parameter.credentialSecret + credentialSecretNamespace: parameter.credentialSecretNamespace + } + urls: parameter.urls + } + } + parameter: { + grafanaServiceName: string + grafanaServiceNamespace: *"default" | string + credentialSecret: string + credentialSecretNamespace: *"default" | string + urls: [...string] + + } + workloadRefPath: "" + diff --git a/charts/vela-minimal/templates/defwithtemplate/pure-ingress.yaml b/charts/vela-minimal/templates/defwithtemplate/pure-ingress.yaml new file mode 100644 index 000000000..ca33a488f --- /dev/null +++ b/charts/vela-minimal/templates/defwithtemplate/pure-ingress.yaml @@ -0,0 +1,56 @@ +# Code generated by KubeVela templates. DO NOT EDIT. Please edit the original cue file. +# Definition source cue file: vela-templates/definitions/internal/pure-ingress.cue +apiVersion: core.oam.dev/v1beta1 +kind: TraitDefinition +metadata: + annotations: + definition.oam.dev/description: Enable public web traffic for the component without creating a Service. + name: pure-ingress + namespace: {{.Values.systemDefinitionNamespace}} +spec: + appliesToWorkloads: [] + conflictsWith: [] + podDisruptive: false + schematic: + cue: + template: | + outputs: ingress: { + apiVersion: "networking.k8s.io/v1beta1" + kind: "Ingress" + metadata: name: context.name + spec: rules: [{ + host: parameter.domain + http: paths: [ + for k, v in parameter.http { + path: k + backend: { + serviceName: context.name + servicePort: v + } + }, + ] + }] + } + parameter: { + // +usage=Specify the domain you want to expose + domain: string + + // +usage=Specify the mapping relationship between the http path and the workload port + http: [string]: int + } + status: + customStatus: |- + let igs = context.outputs.ingress.status.loadBalancer.ingress + if igs == _|_ { + message: "No loadBalancer found, visiting by using 'vela port-forward " + context.appName + " --route'\n" + } + if len(igs) > 0 { + if igs[0].ip != _|_ { + message: "Visiting URL: " + context.outputs.ingress.spec.rules[0].host + ", IP: " + igs[0].ip + } + if igs[0].ip == _|_ { + message: "Visiting URL: " + context.outputs.ingress.spec.rules[0].host + } + } + workloadRefPath: "" + diff --git a/charts/vela-minimal/templates/defwithtemplate/register-grafana-datasource.yaml b/charts/vela-minimal/templates/defwithtemplate/register-grafana-datasource.yaml new file mode 100644 index 000000000..25c18cfe0 --- /dev/null +++ b/charts/vela-minimal/templates/defwithtemplate/register-grafana-datasource.yaml @@ -0,0 +1,48 @@ +# Code generated by KubeVela templates. DO NOT EDIT. Please edit the original cue file. +# Definition source cue file: vela-templates/definitions/internal/register-grafana-datasource.cue +apiVersion: core.oam.dev/v1beta1 +kind: TraitDefinition +metadata: + annotations: + definition.oam.dev/description: Add a datasource to Grafana + name: register-grafana-datasource + namespace: {{.Values.systemDefinitionNamespace}} +spec: + appliesToWorkloads: [] + conflictsWith: [] + podDisruptive: false + schematic: + cue: + template: | + outputs: registerdatasource: { + apiVersion: "grafana.extension.oam.dev/v1alpha1" + kind: "DatasourceRegistration" + spec: { + grafana: { + service: parameter.grafanaServiceName + namespace: parameter.grafanaServiceNamespace + credentialSecret: parameter.credentialSecret + credentialSecretNamespace: parameter.credentialSecretNamespace + } + datasource: { + name: parameter.name + type: parameter.type + access: parameter.access + service: parameter.service + namespace: parameter.namespace + } + } + } + parameter: { + grafanaServiceName: string + grafanaServiceNamespace: *"default" | string + credentialSecret: string + credentialSecretNamespace: string + name: string + type: string + access: *"proxy" | string + service: string + namespace: *"default" | string + } + workloadRefPath: "" + diff --git a/docs/examples/obervability/README.md b/docs/examples/obervability/README.md index 1c259cbab..07e7d5098 100644 --- a/docs/examples/obervability/README.md +++ b/docs/examples/obervability/README.md @@ -1,4 +1,4 @@ This repo is the source artifacts for addon `observability`. -- All .cue files are source artifacts from definition of [observability-asset](../../../vela-templates/addons/observability-asset). -- `initializer-observability.yaml` will help developer [observability](../../../vela-templates/addons/observability). +- All files in definitions are source artifacts which is now built-in in `vela-core` helm chart. +- `application-observability.yaml` will help developer [observability](../../../vela-templates/addons/observability). diff --git a/docs/examples/obervability/trait-import-grafana-dashboard.cue b/docs/examples/obervability/trait-import-grafana-dashboard.cue deleted file mode 100644 index eba46b9cc..000000000 --- a/docs/examples/obervability/trait-import-grafana-dashboard.cue +++ /dev/null @@ -1,21 +0,0 @@ -outputs: registerdatasource: { - apiVersion: "grafana.extension.oam.dev/v1alpha1" - kind: "ImportDashboard" - spec: { - grafana: { - service: parameter.grafanaServiceName - namespace: parameter.grafanaServiceNamespace - credentialSecret: parameter.credentialSecret - credentialSecretNamespace: parameter.credentialSecretNamespace - } - urls: parameter.urls - } -} - -parameter: { - grafanaServiceName: string - grafanaServiceNamespace: *"default" | string - credentialSecret: string - credentialSecretNamespace: *"default" | string - urls: [...string] -} diff --git a/docs/examples/obervability/trait-register-grafana-datasource.cue b/docs/examples/obervability/trait-register-grafana-datasource.cue deleted file mode 100644 index 1c2950c3a..000000000 --- a/docs/examples/obervability/trait-register-grafana-datasource.cue +++ /dev/null @@ -1,31 +0,0 @@ -outputs: registerdatasource: { - apiVersion: "grafana.extension.oam.dev/v1alpha1" - kind: "DatasourceRegistration" - spec: { - grafana: { - service: parameter.grafanaServiceName - namespace: parameter.grafanaServiceNamespace - credentialSecret: parameter.credentialSecret - credentialSecretNamespace: parameter.credentialSecretNamespace - } - datasource: { - name: parameter.name - type: parameter.type - access: parameter.access - service: parameter.service - namespace: parameter.namespace - } - } -} - -parameter: { - grafanaServiceName: string - grafanaServiceNamespace: *"default" | string - credentialSecret: string - credentialSecretNamespace: string - name: string - type: string - access: *"proxy" | string - service: string - namespace: *"default" | string -} diff --git a/references/cli/addon.go b/references/cli/addon.go index d5c8f1570..715b50072 100644 --- a/references/cli/addon.go +++ b/references/cli/addon.go @@ -24,6 +24,10 @@ import ( "text/template" "time" + yaml2 "k8s.io/apimachinery/pkg/util/yaml" + + "github.com/oam-dev/kubevela/pkg/oam/util" + common2 "github.com/oam-dev/kubevela/apis/core.oam.dev/common" "github.com/Masterminds/sprig" @@ -31,20 +35,15 @@ import ( "github.com/pkg/errors" "github.com/spf13/cobra" v1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/runtime/serializer/yaml" types2 "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/wait" - "k8s.io/client-go/dynamic" "sigs.k8s.io/controller-runtime/pkg/client" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" "github.com/oam-dev/kubevela/apis/types" "github.com/oam-dev/kubevela/pkg/oam" - "github.com/oam-dev/kubevela/pkg/oam/discoverymapper" "github.com/oam-dev/kubevela/pkg/utils/apply" "github.com/oam-dev/kubevela/pkg/utils/common" cmdutil "github.com/oam-dev/kubevela/pkg/utils/util" @@ -53,6 +52,9 @@ import ( const ( // DescAnnotation records the description of addon DescAnnotation = "addons.oam.dev/description" + + // DependsOnWorkFlowStepName is workflow step name which is used to check dependsOn app + DependsOnWorkFlowStepName = "depends-on-app" ) var statusUninstalled = "uninstalled" @@ -333,25 +335,10 @@ type Addon struct { data string // Args is map for renderInitializer Args map[string]string - application *unstructured.Unstructured - gvk *schema.GroupVersionKind + application *v1beta1.Application } -func (a *Addon) getGVK() (*schema.GroupVersionKind, error) { - if a.gvk == nil { - if a.application == nil { - _, err := a.renderApplication() - if err != nil { - return nil, err - } - } - gvk := schema.FromAPIVersionAndKind(a.application.GetAPIVersion(), a.application.GetKind()) - a.gvk = &gvk - } - return a.gvk, nil -} - -func (a *Addon) renderApplication() (*unstructured.Unstructured, error) { +func (a *Addon) renderApplication() (*v1beta1.Application, error) { if a.Args == nil { a.Args = map[string]string{} } @@ -364,14 +351,10 @@ func (a *Addon) renderApplication() (*unstructured.Unstructured, error) { if err != nil { return nil, errors.Wrap(err, "application template render fail") } - dec := yaml.NewDecodingSerializer(unstructured.UnstructuredJSONScheme) - obj := &unstructured.Unstructured{} - _, gvk, err := dec.Decode(buf.Bytes(), nil, obj) + err = yaml2.NewYAMLOrJSONDecoder(&buf, buf.Len()).Decode(&a.application) if err != nil { return nil, err } - a.application = obj - a.gvk = gvk return a.application, nil } @@ -382,6 +365,10 @@ func (a *Addon) enable() error { if err != nil { return err } + err = a.installDependsOn() + if err != nil { + return errors.Wrap(err, "Error occurs when install dependent addon") + } err = applicator.Apply(ctx, obj) if err != nil { return errors.Wrapf(err, "Error occurs when apply addon application: %s\n", a.name) @@ -393,7 +380,7 @@ func (a *Addon) enable() error { return nil } -func waitApplicationRunning(obj *unstructured.Unstructured) error { +func waitApplicationRunning(obj *v1beta1.Application) error { ctx := context.Background() period := 20 * time.Second timeout := 10 * time.Minute @@ -412,40 +399,12 @@ func waitApplicationRunning(obj *unstructured.Unstructured) error { }) } func (a *Addon) disable() error { - dynamicClient, err := dynamic.NewForConfig(clientArgs.Config) - if err != nil { - return err - } - mapper, err := discoverymapper.New(clientArgs.Config) - if err != nil { - return err - } obj, err := a.renderApplication() if err != nil { return err } - gvk, err := a.getGVK() - if err != nil { - return err - } - mapping, err := mapper.RESTMapping(gvk.GroupKind(), gvk.Version) - if err != nil { - return err - } - var resourceREST dynamic.ResourceInterface - if mapping.Scope.Name() == meta.RESTScopeNameNamespace { - // namespaced resources should specify the namespace - resourceREST = dynamicClient.Resource(mapping.Resource).Namespace(obj.GetNamespace()) - } else { - // for cluster-wide resources - resourceREST = dynamicClient.Resource(mapping.Resource) - } - deletePolicy := metav1.DeletePropagationForeground - deleteOptions := metav1.DeleteOptions{ - PropagationPolicy: &deletePolicy, - } fmt.Println("Deleting all resources...") - err = resourceREST.Delete(context.TODO(), obj.GetName(), deleteOptions) + err = clt.Delete(context.TODO(), obj, client.PropagationPolicy(metav1.DeletePropagationForeground)) if err != nil { return err } @@ -468,6 +427,37 @@ func (a *Addon) setArgs(args map[string]string) { a.Args = args } +func (a *Addon) installDependsOn() error { + if a.application.Spec.Workflow == nil || a.application.Spec.Workflow.Steps == nil { + return nil + } + repo, err := NewAddonRepo() + if err != nil { + return err + } + for _, step := range a.application.Spec.Workflow.Steps { + if step.Type == DependsOnWorkFlowStepName { + props, err := util.RawExtension2Map(step.Properties) + if err != nil { + return err + } + dependsOnAddonName, _ := props["name"].(string) + fmt.Printf("Installing dependent addon: %s\n", dependsOnAddonName) + addon, err := repo.getAddon(dependsOnAddonName) + if err != nil { + return err + } + if addon.getStatus() != statusInstalled { + err = addon.enable() + if err != nil { + return err + } + } + } + } + return nil +} + // TransAddonName will turn addon's name from xxx/yyy to xxx-yyy func TransAddonName(name string) string { return strings.ReplaceAll(name, "/", "-") diff --git a/vela-templates/addons/auto-gen/observability.yaml b/vela-templates/addons/auto-gen/observability.yaml index 9bde345f0..2f6d749ca 100644 --- a/vela-templates/addons/auto-gen/observability.yaml +++ b/vela-templates/addons/auto-gen/observability.yaml @@ -7,106 +7,13 @@ metadata: namespace: vela-system spec: components: - - name: ns-observability - properties: - apiVersion: v1 - kind: Namespace - metadata: - name: observability - type: raw - - name: import-grafana-dashboard-traitdef - properties: - apiVersion: core.oam.dev/v1beta1 - kind: TraitDefinition - metadata: - annotations: - definition.oam.dev/description: Import dashboards to Grafana - name: import-grafana-dashboard - namespace: vela-system - spec: - schematic: - cue: - template: "outputs: registerdatasource: {\n\tapiVersion: \"grafana.extension.oam.dev/v1alpha1\"\n\tkind: - \ \"ImportDashboard\"\n\tspec: {\n\t\tgrafana: {\n\t\t\tservice: - \ parameter.grafanaServiceName\n\t\t\tnamespace: parameter.grafanaServiceNamespace\n\t\t\tcredentialSecret: - \ parameter.credentialSecret\n\t\t\tcredentialSecretNamespace: - parameter.credentialSecretNamespace\n\t\t}\n\t\turls: parameter.urls\n\t}\n}\nparameter: - {\n\tgrafanaServiceName: string\n\tgrafanaServiceNamespace: *\"default\" - | string\n\tcredentialSecret: string\n\tcredentialSecretNamespace: - *\"default\" | string\n\turls: [...string]\n}\n" - type: raw - - name: pure-ingress-traitdef - properties: - apiVersion: core.oam.dev/v1beta1 - kind: TraitDefinition - metadata: - annotations: - definition.oam.dev/description: Enable public web traffic for the component - without creating a Service. - name: pure-ingress - namespace: vela-system - spec: - schematic: - cue: - template: "\noutputs: ingress: {\n\tapiVersion: \"networking.k8s.io/v1beta1\"\n\tkind: - \ \"Ingress\"\n\tmetadata:\n\t\tname: context.name\n\tspec: {\n\t\trules: - [{\n\t\t\thost: parameter.domain\n\t\t\thttp: {\n\t\t\t\tpaths: [\n\t\t\t\t\tfor - k, v in parameter.http {\n\t\t\t\t\t\tpath: k\n\t\t\t\t\t\tbackend: - {\n\t\t\t\t\t\t\tserviceName: context.name\n\t\t\t\t\t\t\tservicePort: - v\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t]\n\t\t\t}\n\t\t}]\n\t}\n}\n\nparameter: - {\n\t// +usage=Specify the domain you want to expose\n\tdomain: string\n\n\t// - +usage=Specify the mapping relationship between the http path and the - workload port\n\thttp: [string]: int\n}\n" - status: - customStatus: |- - let igs = context.outputs.ingress.status.loadBalancer.ingress - if igs == _|_ { - message: "No loadBalancer found, visiting by using 'vela port-forward " + context.appName + " --route'\n" - } - if len(igs) > 0 { - if igs[0].ip != _|_ { - message: "Visiting URL: " + context.outputs.ingress.spec.rules[0].host + ", IP: " + igs[0].ip - } - if igs[0].ip == _|_ { - message: "Visiting URL: " + context.outputs.ingress.spec.rules[0].host - } - } - healthPolicy: | - isHealth: len(context.outputs.ingress.status.loadBalancer.ingress) > 0 - type: raw - - name: register-grafana-datasource-traitdef - properties: - apiVersion: core.oam.dev/v1beta1 - kind: TraitDefinition - metadata: - annotations: - definition.oam.dev/description: Add a datasource to Grafana - name: register-grafana-datasource - namespace: vela-system - spec: - schematic: - cue: - template: "outputs: registerdatasource: {\n\tapiVersion: \"grafana.extension.oam.dev/v1alpha1\"\n\tkind: - \ \"DatasourceRegistration\"\n\tspec: {\n\t\tgrafana: {\n\t\t\tservice: - \ parameter.grafanaServiceName\n\t\t\tnamespace: parameter.grafanaServiceNamespace\n\t\t\tcredentialSecret: - \ parameter.credentialSecret\n\t\t\tcredentialSecretNamespace: - parameter.credentialSecretNamespace\n\t\t}\n\t\tdatasource: {\n\t\t\tname: - \ parameter.name\n\t\t\ttype: parameter.type\n\t\t\taccess: - \ parameter.access\n\t\t\tservice: parameter.service\n\t\t\tnamespace: - parameter.namespace\n\t\t}\n\t}\n}\n\nparameter: {\n\tgrafanaServiceName: - \ string\n\tgrafanaServiceNamespace: *\"default\" | string\n\tcredentialSecret: - \ string\n\tcredentialSecretNamespace: string\n\tname: string\n\ttype: - \ string\n\taccess: *\"proxy\" - | string\n\tservice: string\n\tnamespace: *\"default\" - | string\n}\n" - type: raw - name: grafana-registration properties: chart: ./chart git: branch: master repoType: git - targetNamespace: observability + targetNamespace: vela-system url: https://github.com/oam-dev/grafana-registration values: replicaCount: 1 @@ -116,7 +23,7 @@ spec: chart: grafana releaseName: grafana repoType: helm - targetNamespace: observability + targetNamespace: vela-system url: https://charts.kubevela.net/addons version: 6.14.1 traits: @@ -127,9 +34,9 @@ spec: type: pure-ingress - properties: credentialSecret: grafana - credentialSecretNamespace: observability + credentialSecretNamespace: vela-system grafanaServiceName: grafana - grafanaServiceNamespace: observability + grafanaServiceNamespace: vela-system urls: - https://charts.kubevela.net/addons/dashboards/kubevela_core_logging.json - https://charts.kubevela.net/addons/dashboards/kubevela_core_monitoring.json @@ -142,18 +49,18 @@ spec: chart: loki-stack releaseName: loki repoType: helm - targetNamespace: observability + targetNamespace: vela-system url: https://charts.kubevela.net/addons version: 2.4.1 traits: - properties: access: proxy credentialSecret: grafana - credentialSecretNamespace: observability + credentialSecretNamespace: vela-system grafanaServiceName: grafana - grafanaServiceNamespace: observability + grafanaServiceNamespace: vela-system name: loki - namespace: observability + namespace: vela-system service: loki type: loki type: register-grafana-datasource @@ -163,7 +70,7 @@ spec: chart: prometheus releaseName: prometheus repoType: helm - targetNamespace: observability + targetNamespace: vela-system url: https://charts.kubevela.net/addons values: alertmanager: @@ -181,11 +88,11 @@ spec: - properties: access: proxy credentialSecret: grafana - credentialSecretNamespace: observability + credentialSecretNamespace: vela-system grafanaServiceName: grafana - grafanaServiceNamespace: observability + grafanaServiceNamespace: vela-system name: prometheus - namespace: observability + namespace: vela-system service: prometheus-server type: prometheus type: register-grafana-datasource @@ -194,7 +101,7 @@ spec: properties: chart: kube-state-metrics repoType: helm - targetNamespace: observability + targetNamespace: vela-system url: https://charts.kubevela.net/addons values: image: @@ -209,22 +116,6 @@ spec: name: fluxcd namespace: vela-system type: depends-on-app - - name: apply-ns - properties: - component: ns-observability - type: apply-component - - name: apply-trait-1 - properties: - component: import-grafana-dashboard-traitdef - type: apply-component - - name: apply-trait-2 - properties: - component: pure-ingress-traitdef - type: apply-component - - name: apply-trait-3 - properties: - component: register-grafana-datasource-traitdef - type: apply-component - name: apply-resources type: apply-remaining status: diff --git a/vela-templates/addons/observability/template.yaml b/vela-templates/addons/observability/template.yaml index ebd62767f..e0439f45f 100644 --- a/vela-templates/addons/observability/template.yaml +++ b/vela-templates/addons/observability/template.yaml @@ -13,173 +13,9 @@ spec: properties: name: fluxcd namespace: vela-system - - name: apply-ns - type: apply-component - properties: - component: ns-observability - - name: apply-trait-1 - type: apply-component - properties: - component: import-grafana-dashboard-traitdef - - name: apply-trait-2 - type: apply-component - properties: - component: pure-ingress-traitdef - - name: apply-trait-3 - type: apply-component - properties: - component: register-grafana-datasource-traitdef - name: apply-resources type: apply-remaining components: - - name: ns-observability - type: raw - properties: - apiVersion: v1 - kind: Namespace - metadata: - name: observability - - name: import-grafana-dashboard-traitdef - type: raw - properties: - apiVersion: core.oam.dev/v1beta1 - kind: TraitDefinition - metadata: - annotations: - definition.oam.dev/description: "Import dashboards to Grafana" - name: import-grafana-dashboard - namespace: vela-system - spec: - schematic: - cue: - template: | - outputs: registerdatasource: { - apiVersion: "grafana.extension.oam.dev/v1alpha1" - kind: "ImportDashboard" - spec: { - grafana: { - service: parameter.grafanaServiceName - namespace: parameter.grafanaServiceNamespace - credentialSecret: parameter.credentialSecret - credentialSecretNamespace: parameter.credentialSecretNamespace - } - urls: parameter.urls - } - } - parameter: { - grafanaServiceName: string - grafanaServiceNamespace: *"default" | string - credentialSecret: string - credentialSecretNamespace: *"default" | string - urls: [...string] - } - - name: pure-ingress-traitdef - type: raw - properties: - apiVersion: core.oam.dev/v1beta1 - kind: TraitDefinition - metadata: - annotations: - definition.oam.dev/description: "Enable public web traffic for the component without creating a Service." - name: pure-ingress - namespace: vela-system - spec: - status: - customStatus: |- - let igs = context.outputs.ingress.status.loadBalancer.ingress - if igs == _|_ { - message: "No loadBalancer found, visiting by using 'vela port-forward " + context.appName + " --route'\n" - } - if len(igs) > 0 { - if igs[0].ip != _|_ { - message: "Visiting URL: " + context.outputs.ingress.spec.rules[0].host + ", IP: " + igs[0].ip - } - if igs[0].ip == _|_ { - message: "Visiting URL: " + context.outputs.ingress.spec.rules[0].host - } - } - healthPolicy: | - isHealth: len(context.outputs.ingress.status.loadBalancer.ingress) > 0 - schematic: - cue: - template: | - - outputs: ingress: { - apiVersion: "networking.k8s.io/v1beta1" - kind: "Ingress" - metadata: - name: context.name - spec: { - rules: [{ - host: parameter.domain - http: { - paths: [ - for k, v in parameter.http { - path: k - backend: { - serviceName: context.name - servicePort: v - } - }, - ] - } - }] - } - } - - parameter: { - // +usage=Specify the domain you want to expose - domain: string - - // +usage=Specify the mapping relationship between the http path and the workload port - http: [string]: int - } - - name: register-grafana-datasource-traitdef - type: raw - properties: - apiVersion: core.oam.dev/v1beta1 - kind: TraitDefinition - metadata: - annotations: - definition.oam.dev/description: "Add a datasource to Grafana" - name: register-grafana-datasource - namespace: vela-system - spec: - schematic: - cue: - template: | - outputs: registerdatasource: { - apiVersion: "grafana.extension.oam.dev/v1alpha1" - kind: "DatasourceRegistration" - spec: { - grafana: { - service: parameter.grafanaServiceName - namespace: parameter.grafanaServiceNamespace - credentialSecret: parameter.credentialSecret - credentialSecretNamespace: parameter.credentialSecretNamespace - } - datasource: { - name: parameter.name - type: parameter.type - access: parameter.access - service: parameter.service - namespace: parameter.namespace - } - } - } - - parameter: { - grafanaServiceName: string - grafanaServiceNamespace: *"default" | string - credentialSecret: string - credentialSecretNamespace: string - name: string - type: string - access: *"proxy" | string - service: string - namespace: *"default" | string - } - - name: grafana-registration type: helm properties: @@ -188,7 +24,7 @@ spec: git: branch: master chart: ./chart - targetNamespace: observability + targetNamespace: vela-system values: replicaCount: 1 @@ -200,7 +36,7 @@ spec: repoType: helm # original url: https://grafana.github.io/helm-charts url: https://charts.kubevela.net/addons - targetNamespace: observability + targetNamespace: vela-system releaseName: grafana type: helm traits: @@ -212,9 +48,9 @@ spec: - type: import-grafana-dashboard properties: grafanaServiceName: grafana - grafanaServiceNamespace: observability + grafanaServiceNamespace: vela-system credentialSecret: grafana - credentialSecretNamespace: observability + credentialSecretNamespace: vela-system urls: - https://charts.kubevela.net/addons/dashboards/kubevela_core_logging.json - https://charts.kubevela.net/addons/dashboards/kubevela_core_monitoring.json @@ -230,18 +66,18 @@ spec: repoType: helm # original url: https://grafana.github.io/helm-charts url: https://charts.kubevela.net/addons - targetNamespace: observability + targetNamespace: vela-system releaseName: loki traits: - type: register-grafana-datasource # register loki datasource to Grafana properties: grafanaServiceName: grafana - grafanaServiceNamespace: observability + grafanaServiceNamespace: vela-system credentialSecret: grafana - credentialSecretNamespace: observability + credentialSecretNamespace: vela-system name: loki service: loki - namespace: observability + namespace: vela-system type: loki access: proxy @@ -254,7 +90,7 @@ spec: repoType: helm # original url: https://prometheus-community.github.io/helm-charts url: https://charts.kubevela.net/addons - targetNamespace: observability + targetNamespace: vela-system releaseName: prometheus values: alertmanager: @@ -271,12 +107,12 @@ spec: - type: register-grafana-datasource # register Prometheus datasource to Grafana properties: grafanaServiceName: grafana - grafanaServiceNamespace: observability + grafanaServiceNamespace: vela-system credentialSecret: grafana - credentialSecretNamespace: observability + credentialSecretNamespace: vela-system name: prometheus service: prometheus-server - namespace: observability + namespace: vela-system type: prometheus access: proxy @@ -289,7 +125,7 @@ spec: repoType: helm # original url: https://prometheus-community.github.io/helm-charts url: https://charts.kubevela.net/addons - targetNamespace: observability + targetNamespace: vela-system values: image: repository: oamdev/kube-state-metrics diff --git a/vela-templates/definitions/internal/import-grafana-dashboard.cue b/vela-templates/definitions/internal/import-grafana-dashboard.cue new file mode 100644 index 000000000..39502711f --- /dev/null +++ b/vela-templates/definitions/internal/import-grafana-dashboard.cue @@ -0,0 +1,35 @@ +"import-grafana-dashboard": { + attributes: { + appliesToWorkloads: [] + conflictsWith: [] + podDisruptive: false + workloadRefPath: "" + } + description: "Import dashboards to Grafana" + labels: {} + type: "trait" +} + +template: { + outputs: registerdatasource: { + apiVersion: "grafana.extension.oam.dev/v1alpha1" + kind: "ImportDashboard" + spec: { + grafana: { + service: parameter.grafanaServiceName + namespace: parameter.grafanaServiceNamespace + credentialSecret: parameter.credentialSecret + credentialSecretNamespace: parameter.credentialSecretNamespace + } + urls: parameter.urls + } + } + parameter: { + grafanaServiceName: string + grafanaServiceNamespace: *"default" | string + credentialSecret: string + credentialSecretNamespace: *"default" | string + urls: [...string] + + } +} diff --git a/vela-templates/definitions/internal/pure-ingress.cue b/vela-templates/definitions/internal/pure-ingress.cue new file mode 100644 index 000000000..1ce26ee9d --- /dev/null +++ b/vela-templates/definitions/internal/pure-ingress.cue @@ -0,0 +1,60 @@ +"pure-ingress": { + annotations: {} + attributes: { + appliesToWorkloads: [] + conflictsWith: [] + podDisruptive: false + status: { + customStatus: #""" + let igs = context.outputs.ingress.status.loadBalancer.ingress + if igs == _|_ { + message: "No loadBalancer found, visiting by using 'vela port-forward " + context.appName + " --route'\n" + } + if len(igs) > 0 { + if igs[0].ip != _|_ { + message: "Visiting URL: " + context.outputs.ingress.spec.rules[0].host + ", IP: " + igs[0].ip + } + if igs[0].ip == _|_ { + message: "Visiting URL: " + context.outputs.ingress.spec.rules[0].host + } + } + """# + } + workloadRefPath: "" + } + description: "Enable public web traffic for the component without creating a Service." + labels: {} + type: "trait" +} + +template: { + outputs: ingress: { + apiVersion: "networking.k8s.io/v1beta1" + kind: "Ingress" + metadata: + name: context.name + spec: { + rules: [{ + host: parameter.domain + http: { + paths: [ + for k, v in parameter.http { + path: k + backend: { + serviceName: context.name + servicePort: v + } + }, + ] + } + }] + } + } + parameter: { + // +usage=Specify the domain you want to expose + domain: string + + // +usage=Specify the mapping relationship between the http path and the workload port + http: [string]: int + } +} diff --git a/vela-templates/definitions/internal/register-grafana-datasource.cue b/vela-templates/definitions/internal/register-grafana-datasource.cue new file mode 100644 index 000000000..64ab4e711 --- /dev/null +++ b/vela-templates/definitions/internal/register-grafana-datasource.cue @@ -0,0 +1,46 @@ +"register-grafana-datasource": { + annotations: {} + attributes: { + appliesToWorkloads: [] + conflictsWith: [] + podDisruptive: false + workloadRefPath: "" + } + description: "Add a datasource to Grafana" + labels: {} + type: "trait" +} + +template: { + outputs: registerdatasource: { + apiVersion: "grafana.extension.oam.dev/v1alpha1" + kind: "DatasourceRegistration" + spec: { + grafana: { + service: parameter.grafanaServiceName + namespace: parameter.grafanaServiceNamespace + credentialSecret: parameter.credentialSecret + credentialSecretNamespace: parameter.credentialSecretNamespace + } + datasource: { + name: parameter.name + type: parameter.type + access: parameter.access + service: parameter.service + namespace: parameter.namespace + } + } + } + parameter: { + grafanaServiceName: string + grafanaServiceNamespace: *"default" | string + credentialSecret: string + credentialSecretNamespace: string + name: string + type: string + access: *"proxy" | string + service: string + namespace: *"default" | string + } + +}