mirror of
https://github.com/kubevela/kubevela.git
synced 2026-08-19 12:36:34 +00:00
Add add-on input go-template implementation (#2049)
* add addon parameter template implementation * add test * fix test * fix helm version parameter
This commit is contained in:
@@ -5940,13 +5940,13 @@ data:
|
||||
+usage=The interval at which to check for repository and relese
|
||||
updates.\n\tpullInterval: *\"5m\" | string\n\t// +usage=1.The relative
|
||||
path to helm chart for git source. 2. chart name for helm resource\n\tchart:
|
||||
string\n\t// +usage=Chart version\n\tversion?: string\n\t// +usage=The
|
||||
Git reference to checkout and monitor for changes, defaults to master
|
||||
branch.\n\tbranch: *\"master\" | string\n\t// +usage=The name of
|
||||
the secret containing authentication credentials for the Helm repository.\n\tsecretRef?:
|
||||
string\n\t// +usage=The namespace for helm chart\n\ttargetNamespace?:
|
||||
string\n\t// +usage=Chart version\n\tvalue?: #nestedmap\n}\n\n#nestedmap:
|
||||
{\n\t...\n}\n"
|
||||
string\n\t// +usage=Chart version\n\tversion: *\"*\" | string\n\t//
|
||||
+usage=The Git reference to checkout and monitor for changes, defaults
|
||||
to master branch.\n\tbranch: *\"master\" | string\n\t// +usage=The
|
||||
name of the secret containing authentication credentials for the
|
||||
Helm repository.\n\tsecretRef?: string\n\t// +usage=The namespace
|
||||
for helm chart\n\ttargetNamespace?: string\n\t// +usage=Chart version\n\tvalue?:
|
||||
#nestedmap\n}\n\n#nestedmap: {\n\t...\n} \n"
|
||||
workload:
|
||||
type: autodetects.core.oam.dev
|
||||
type: raw
|
||||
|
||||
+85
-14
@@ -32,44 +32,68 @@ import (
|
||||
|
||||
var _ = Describe("Addon Test", func() {
|
||||
args := common.Args{}
|
||||
var cm v1.ConfigMap
|
||||
var cmSimpleAddon v1.ConfigMap
|
||||
var cmInputAddon v1.ConfigMap
|
||||
Context("Prepare test addon", func() {
|
||||
It("apply test addon", func() {
|
||||
Expect(yaml.Unmarshal([]byte(test_addon), &cm)).Should(BeNil())
|
||||
k8sClient, err := args.GetClient()
|
||||
Expect(err).Should(BeNil())
|
||||
err = k8sClient.Create(context.Background(), &cm)
|
||||
k8sClient, err := args.GetClient()
|
||||
Expect(err).Should(BeNil())
|
||||
It("Apply test addon", func() {
|
||||
Expect(yaml.Unmarshal([]byte(test_addon), &cmSimpleAddon)).Should(BeNil())
|
||||
err = k8sClient.Create(context.Background(), &cmSimpleAddon)
|
||||
Expect(err).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{}))
|
||||
})
|
||||
It("Apply test input addon", func() {
|
||||
Expect(yaml.Unmarshal([]byte(test_input_addon), &cmInputAddon)).Should(BeNil())
|
||||
err = k8sClient.Create(context.Background(), &cmInputAddon)
|
||||
Expect(err).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{}))
|
||||
})
|
||||
})
|
||||
|
||||
Context("list addons", func() {
|
||||
It("list all addon", func() {
|
||||
Context("List addons", func() {
|
||||
It("List all addon", func() {
|
||||
output, err := e2e.Exec("vela addon list")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(output).To(ContainSubstring("test-addon"))
|
||||
})
|
||||
})
|
||||
Context("enable addon", func() {
|
||||
It("enable addon fluxcd", func() {
|
||||
Context("Enable addon", func() {
|
||||
It("Enable addon fluxcd", func() {
|
||||
output, err := e2e.Exec("vela addon enable test-addon")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(output).To(ContainSubstring("Successfully enable addon"))
|
||||
})
|
||||
})
|
||||
Context("disable addon", func() {
|
||||
It("disable addon fluxcd", func() {
|
||||
Context("Disable addon", func() {
|
||||
It("Disable addon fluxcd", func() {
|
||||
output, err := e2e.LongTimeExec("vela addon disable test-addon", 600*time.Second)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(output).To(ContainSubstring("Successfully disable addon"))
|
||||
})
|
||||
})
|
||||
|
||||
Context("Test addon receive input", func() {
|
||||
It("Enable addon with input", func() {
|
||||
output, err := e2e.LongTimeExec("vela addon enable test-input-addon repoUrl=https://charts.bitnami.com/bitnami chart=redis", 300*time.Second)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(output).To(ContainSubstring("Successfully enable addon"))
|
||||
})
|
||||
})
|
||||
|
||||
Context("Disable addon", func() {
|
||||
It("Disable addon fluxcd", func() {
|
||||
output, err := e2e.LongTimeExec("vela addon disable test-input-addon", 600*time.Second)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(output).To(ContainSubstring("Successfully disable addon"))
|
||||
})
|
||||
})
|
||||
|
||||
Context("Clean test environment", func() {
|
||||
It("Delete test addon", func() {
|
||||
It("Delete test addon and test-input addon", func() {
|
||||
k8sClient, err := args.GetClient()
|
||||
Expect(err).Should(BeNil())
|
||||
err = k8sClient.Delete(context.Background(), &cm)
|
||||
err = k8sClient.Delete(context.Background(), &cmSimpleAddon)
|
||||
Expect(err).Should(BeNil())
|
||||
err = k8sClient.Delete(context.Background(), &cmInputAddon)
|
||||
Expect(err).Should(BeNil())
|
||||
})
|
||||
})
|
||||
@@ -112,3 +136,50 @@ data:
|
||||
- name: test-addon-pod-container
|
||||
image: nginx
|
||||
`
|
||||
|
||||
var test_input_addon = `
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
annotations:
|
||||
addons.oam.dev/description: This is a test addon for test addon input
|
||||
labels:
|
||||
addons.oam.dev/type: test
|
||||
name: test-input-addon
|
||||
namespace: vela-system
|
||||
apiVersion: v1
|
||||
data:
|
||||
initializer: |
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Initializer
|
||||
metadata:
|
||||
annotations:
|
||||
addons.oam.dev/description: This is a test addon for test addon input
|
||||
name: test-input-addon
|
||||
namespace: vela-system
|
||||
spec:
|
||||
appTemplate:
|
||||
spec:
|
||||
components:
|
||||
- name: test-chart
|
||||
properties:
|
||||
chart: {{ index .Args "chart" }}
|
||||
repoType: helm
|
||||
repoUrl: {{ index .Args "repoUrl" }}
|
||||
type: helm
|
||||
status:
|
||||
rollout:
|
||||
batchRollingState: ""
|
||||
currentBatch: 0
|
||||
lastTargetAppRevision: ""
|
||||
rollingState: ""
|
||||
upgradedReadyReplicas: 0
|
||||
upgradedReplicas: 0
|
||||
dependsOn:
|
||||
- ref:
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Initializer
|
||||
name: fluxcd
|
||||
namespace: vela-system
|
||||
status:
|
||||
observedGeneration: 0
|
||||
`
|
||||
|
||||
+58
-19
@@ -17,8 +17,11 @@ limitations under the License.
|
||||
package cli
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/gosuri/uitable"
|
||||
@@ -111,7 +114,11 @@ func NewAddonEnableCommand(ioStream cmdutil.IOStreams) *cobra.Command {
|
||||
}
|
||||
}
|
||||
name := args[0]
|
||||
err := enableAddon(name)
|
||||
addonArgs, err := parseToMap(args[1:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = enableAddon(name, addonArgs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -120,6 +127,22 @@ func NewAddonEnableCommand(ioStream cmdutil.IOStreams) *cobra.Command {
|
||||
}
|
||||
}
|
||||
|
||||
func parseToMap(args []string) (map[string]string, error) {
|
||||
res := map[string]string{}
|
||||
for _, pair := range args {
|
||||
line := strings.Split(pair, "=")
|
||||
if len(line) != 2 {
|
||||
return nil, fmt.Errorf("parameter format should be foo=bar, %s not match", pair)
|
||||
}
|
||||
k := strings.TrimSpace(line[0])
|
||||
v := strings.TrimSpace(line[1])
|
||||
if k != "" && v != "" {
|
||||
res[k] = v
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// NewAddonDisableCommand create addon disable command
|
||||
func NewAddonDisableCommand(ioStream cmdutil.IOStreams) *cobra.Command {
|
||||
return &cobra.Command{
|
||||
@@ -159,7 +182,7 @@ func listAddons() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func enableAddon(name string) error {
|
||||
func enableAddon(name string, args map[string]string) error {
|
||||
repo, err := NewAddonRepo()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -168,6 +191,7 @@ func enableAddon(name string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
addon.setArgs(args)
|
||||
err = addon.enable()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -199,7 +223,7 @@ func disableAddon(name string) error {
|
||||
func newAddon(data *v1.ConfigMap) *Addon {
|
||||
description := data.ObjectMeta.Annotations[DescAnnotation]
|
||||
a := Addon{name: data.Name, description: description, initYaml: data.Data["initializer"]}
|
||||
init, _ := a.getInitializer()
|
||||
init, _ := a.renderInitializer()
|
||||
a.addonNamespace = init.GetNamespace()
|
||||
return &a
|
||||
}
|
||||
@@ -258,14 +282,16 @@ type Addon struct {
|
||||
addonNamespace string // addonNamespace is where Initializer will be apply
|
||||
description string
|
||||
initYaml string
|
||||
initializer *unstructured.Unstructured
|
||||
gvk *schema.GroupVersionKind
|
||||
// Args is map for renderInitializer
|
||||
Args map[string]string
|
||||
initializer *unstructured.Unstructured
|
||||
gvk *schema.GroupVersionKind
|
||||
}
|
||||
|
||||
func (a *Addon) getGVK() (*schema.GroupVersionKind, error) {
|
||||
if a.gvk == nil {
|
||||
if a.initializer == nil {
|
||||
_, err := a.getInitializer()
|
||||
_, err := a.renderInitializer()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -276,25 +302,34 @@ func (a *Addon) getGVK() (*schema.GroupVersionKind, error) {
|
||||
return a.gvk, nil
|
||||
}
|
||||
|
||||
func (a *Addon) getInitializer() (*unstructured.Unstructured, error) {
|
||||
if a.initializer == nil {
|
||||
res := a.initYaml
|
||||
obj := &unstructured.Unstructured{}
|
||||
dec := yaml.NewDecodingSerializer(unstructured.UnstructuredJSONScheme)
|
||||
_, gvk, err := dec.Decode([]byte(res), nil, obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
a.initializer = obj
|
||||
a.gvk = gvk
|
||||
func (a *Addon) renderInitializer() (*unstructured.Unstructured, error) {
|
||||
if a.Args == nil {
|
||||
a.Args = map[string]string{}
|
||||
}
|
||||
t, err := template.New("addon-template").Parse(a.initYaml)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "parsing addon initializer template error")
|
||||
}
|
||||
buf := bytes.Buffer{}
|
||||
err = t.Execute(&buf, a)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "initializer template render fail")
|
||||
}
|
||||
dec := yaml.NewDecodingSerializer(unstructured.UnstructuredJSONScheme)
|
||||
obj := &unstructured.Unstructured{}
|
||||
_, gvk, err := dec.Decode(buf.Bytes(), nil, obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
a.initializer = obj
|
||||
a.gvk = gvk
|
||||
return a.initializer, nil
|
||||
}
|
||||
|
||||
func (a *Addon) enable() error {
|
||||
applicator := apply.NewAPIApplicator(clt)
|
||||
ctx := context.Background()
|
||||
obj, err := a.getInitializer()
|
||||
obj, err := a.renderInitializer()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -349,7 +384,7 @@ func (a *Addon) disable() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
obj, err := a.getInitializer()
|
||||
obj, err := a.renderInitializer()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -392,3 +427,7 @@ func (a *Addon) getStatus() string {
|
||||
}
|
||||
return statusInstalled
|
||||
}
|
||||
|
||||
func (a *Addon) setArgs(args map[string]string) {
|
||||
a.Args = args
|
||||
}
|
||||
|
||||
@@ -5937,13 +5937,13 @@ spec:
|
||||
+usage=The interval at which to check for repository and relese
|
||||
updates.\n\tpullInterval: *\"5m\" | string\n\t// +usage=1.The relative
|
||||
path to helm chart for git source. 2. chart name for helm resource\n\tchart:
|
||||
string\n\t// +usage=Chart version\n\tversion?: string\n\t// +usage=The
|
||||
Git reference to checkout and monitor for changes, defaults to master
|
||||
branch.\n\tbranch: *\"master\" | string\n\t// +usage=The name of
|
||||
the secret containing authentication credentials for the Helm repository.\n\tsecretRef?:
|
||||
string\n\t// +usage=The namespace for helm chart\n\ttargetNamespace?:
|
||||
string\n\t// +usage=Chart version\n\tvalue?: #nestedmap\n}\n\n#nestedmap:
|
||||
{\n\t...\n}\n"
|
||||
string\n\t// +usage=Chart version\n\tversion: *\"*\" | string\n\t//
|
||||
+usage=The Git reference to checkout and monitor for changes, defaults
|
||||
to master branch.\n\tbranch: *\"master\" | string\n\t// +usage=The
|
||||
name of the secret containing authentication credentials for the
|
||||
Helm repository.\n\tsecretRef?: string\n\t// +usage=The namespace
|
||||
for helm chart\n\ttargetNamespace?: string\n\t// +usage=Chart version\n\tvalue?:
|
||||
#nestedmap\n}\n\n#nestedmap: {\n\t...\n} \n"
|
||||
workload:
|
||||
type: autodetects.core.oam.dev
|
||||
type: raw
|
||||
|
||||
@@ -82,7 +82,7 @@ spec:
|
||||
// +usage=1.The relative path to helm chart for git source. 2. chart name for helm resource
|
||||
chart: string
|
||||
// +usage=Chart version
|
||||
version?: string
|
||||
version: *"*" | string
|
||||
// +usage=The Git reference to checkout and monitor for changes, defaults to master branch.
|
||||
branch: *"master" | string
|
||||
// +usage=The name of the secret containing authentication credentials for the Helm repository.
|
||||
@@ -95,4 +95,4 @@ spec:
|
||||
|
||||
#nestedmap: {
|
||||
...
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user