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:
qiaozp
2021-08-11 11:49:44 +08:00
committed by GitHub
parent abbec2c36b
commit 356db2dc97
5 changed files with 159 additions and 49 deletions
@@ -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
View File
@@ -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
View File
@@ -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
}
+7 -7
View File
@@ -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: {
...
}
}