mirror of
https://github.com/kubevela/kubevela.git
synced 2026-05-16 22:37:16 +00:00
[Backport release-1.5] Fix: address failure when rendering addon API schemas (#4445)
* Fix: address failure when rendering addon API schemas Signed-off-by: Charlie Chiang <charlie_c_0129@outlook.com> (cherry picked from commitde7a64346c) * Fix: address failure when rendering addon API schemas Signed-off-by: Charlie Chiang <charlie_c_0129@outlook.com> (cherry picked from commit284e673bad) * Test: add tests Signed-off-by: Charlie Chiang <charlie_c_0129@outlook.com> (cherry picked from commit1c0653e449) * Test: fix tests Signed-off-by: Charlie Chiang <charlie_c_0129@outlook.com> (cherry picked from commit78104068b1) * Test: fix tests Signed-off-by: Charlie Chiang <charlie_c_0129@outlook.com> (cherry picked from commit0442f823c8) Co-authored-by: Charlie Chiang <charlie_c_0129@outlook.com>
This commit is contained in:
committed by
GitHub
parent
853f44cf61
commit
35ae4e5ef5
@@ -306,13 +306,16 @@ func GetUIDataFromReader(r AsyncReader, meta *SourceMeta, opt ListOptions) (*UID
|
||||
}
|
||||
|
||||
if opt.GetParameter && (len(addon.Parameters) != 0 || len(addon.GlobalParameters) != 0) {
|
||||
if addon.GlobalParameters != "" {
|
||||
if addon.Parameters != "" {
|
||||
klog.Warning("both legacy parameter and global parameter are provided, but only global parameter will be used. Consider removing the legacy parameters.")
|
||||
}
|
||||
addon.Parameters = addon.GlobalParameters
|
||||
}
|
||||
err := genAddonAPISchema(addon)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("fail to generate openAPIschema for addon %s : %w", meta.Name, err)
|
||||
}
|
||||
if len(addon.GlobalParameters) != 0 {
|
||||
addon.Parameters = addon.GlobalParameters
|
||||
}
|
||||
}
|
||||
addon.AvailableVersions = []string{addon.Version}
|
||||
return addon, nil
|
||||
|
||||
@@ -58,12 +58,20 @@ import (
|
||||
var paths = []string{
|
||||
"example/metadata.yaml",
|
||||
"example/readme.md",
|
||||
"example/template.yaml",
|
||||
"example/template.cue",
|
||||
"example/definitions/helm.yaml",
|
||||
"example/resources/configmap.cue",
|
||||
"example/resources/parameter.cue",
|
||||
"example/parameter.cue",
|
||||
"example/resources/service/source-controller.yaml",
|
||||
|
||||
"example-legacy/metadata.yaml",
|
||||
"example-legacy/readme.md",
|
||||
"example-legacy/template.yaml",
|
||||
"example-legacy/definitions/helm.yaml",
|
||||
"example-legacy/resources/configmap.cue",
|
||||
"example-legacy/resources/parameter.cue",
|
||||
"example-legacy/resources/service/source-controller.yaml",
|
||||
|
||||
"terraform/metadata.yaml",
|
||||
"terraform-alibaba/metadata.yaml",
|
||||
|
||||
@@ -159,11 +167,25 @@ func testReaderFunc(t *testing.T, reader AsyncReader) {
|
||||
assert.True(t, uiData.Parameters != "")
|
||||
assert.True(t, len(uiData.Definitions) > 0)
|
||||
|
||||
testAddonName = "example-legacy"
|
||||
for _, m := range registryMeta {
|
||||
if m.Name == testAddonName {
|
||||
testAddonMeta = m
|
||||
break
|
||||
}
|
||||
}
|
||||
assert.NoError(t, err)
|
||||
uiData, err = GetUIDataFromReader(reader, &testAddonMeta, UIMetaOptions)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, uiData.Name, testAddonName)
|
||||
assert.True(t, uiData.Parameters != "")
|
||||
assert.True(t, len(uiData.Definitions) > 0)
|
||||
|
||||
// test get ui data
|
||||
rName := "KubeVela"
|
||||
uiDataList, err := ListAddonUIDataFromReader(reader, registryMeta, rName, UIMetaOptions)
|
||||
assert.True(t, strings.Contains(err.Error(), "#parameter.example: preference mark not allowed at this position"))
|
||||
assert.Equal(t, 4, len(uiDataList))
|
||||
assert.Equal(t, 5, len(uiDataList))
|
||||
assert.Equal(t, uiDataList[0].RegistryName, rName)
|
||||
|
||||
// test get install package
|
||||
@@ -1151,13 +1173,13 @@ func TestCheckEnableAddonErrorWhenMissMatch(t *testing.T) {
|
||||
func TestPackageAddon(t *testing.T) {
|
||||
pwd, _ := os.Getwd()
|
||||
|
||||
validAddonDict := "./testdata/example"
|
||||
validAddonDict := "./testdata/example-legacy"
|
||||
archiver, err := PackageAddon(validAddonDict)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, filepath.Join(pwd, "example-1.0.1.tgz"), archiver)
|
||||
assert.Equal(t, filepath.Join(pwd, "example-legacy-1.0.1.tgz"), archiver)
|
||||
// Remove generated package after tests
|
||||
defer func() {
|
||||
_ = os.RemoveAll(filepath.Join(pwd, "example-1.0.1.tgz"))
|
||||
_ = os.RemoveAll(filepath.Join(pwd, "example-legacy-1.0.1.tgz"))
|
||||
}()
|
||||
|
||||
invalidAddonDict := "./testdata"
|
||||
|
||||
@@ -141,6 +141,7 @@ var _ = Describe("test FindWholeAddonPackagesFromRegistry", func() {
|
||||
cmYaml := strings.ReplaceAll(registryCmYaml, "TEST_SERVER_URL", server.URL)
|
||||
cmYaml = strings.ReplaceAll(cmYaml, "KubeVela", "testreg")
|
||||
Expect(yaml.Unmarshal([]byte(cmYaml), &cm)).Should(BeNil())
|
||||
_ = k8sClient.Create(ctx, &cm)
|
||||
Expect(k8sClient.Update(ctx, &cm)).Should(BeNil())
|
||||
})
|
||||
|
||||
|
||||
@@ -146,7 +146,7 @@ func renderCompAccordingCUETemplate(cueTemplate ElementFile, addon *InstallPacka
|
||||
inputArgs: args,
|
||||
}
|
||||
if err := r.toObject(cueTemplate.Data, &comp); err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("error rendering file %s: %w", cueTemplate.Name, err)
|
||||
}
|
||||
// If the name of component has been set, just keep it, otherwise will set with file name.
|
||||
if len(comp.Name) == 0 {
|
||||
|
||||
12
pkg/addon/testdata/example-legacy/Chart.yaml
vendored
Normal file
12
pkg/addon/testdata/example-legacy/Chart.yaml
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
apiVersion: v2
|
||||
appVersion: 1.0.1
|
||||
description: Extended workload to do continuous and progressive delivery
|
||||
home: https://fluxcd.io
|
||||
icon: https://raw.githubusercontent.com/fluxcd/flux/master/docs/_files/weave-flux.png
|
||||
keywords:
|
||||
- extended_workload
|
||||
- gitops
|
||||
- only_example
|
||||
name: example-legacy
|
||||
type: library
|
||||
version: 1.0.1
|
||||
0
pkg/addon/testdata/example-legacy/definitions/dummy.txt
vendored
Normal file
0
pkg/addon/testdata/example-legacy/definitions/dummy.txt
vendored
Normal file
62
pkg/addon/testdata/example-legacy/definitions/helm.yaml
vendored
Normal file
62
pkg/addon/testdata/example-legacy/definitions/helm.yaml
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: ComponentDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: helm release is a group of K8s resources
|
||||
from either git repository or helm repo
|
||||
name: helm-example
|
||||
namespace: vela-system
|
||||
spec:
|
||||
schematic:
|
||||
cue:
|
||||
template: "output: {\n\tapiVersion: \"source.toolkit.fluxcd.io/v1beta1\"\n\tmetadata:
|
||||
{\n\t\tname: context.name\n\t}\n\tif parameter.repoType == \"git\" {\n\t\tkind:
|
||||
\"GitRepository\"\n\t\tspec: {\n\t\t\turl: parameter.url\n\t\t\tif parameter.git.branch
|
||||
!= _|_ {\n\t\t\t\tref: branch: parameter.git.branch\n\t\t\t}\n\t\t\t_secret\n\t\t\t_sourceCommonArgs\n\t\t}\n\t}\n\tif
|
||||
parameter.repoType == \"oss\" {\n\t\tkind: \"Bucket\"\n\t\tspec: {\n\t\t\tendpoint:
|
||||
\ parameter.url\n\t\t\tbucketName: parameter.oss.bucketName\n\t\t\tprovider:
|
||||
\ parameter.oss.provider\n\t\t\tif parameter.oss.region != _|_ {\n\t\t\t\tregion:
|
||||
parameter.oss.region\n\t\t\t}\n\t\t\t_secret\n\t\t\t_sourceCommonArgs\n\t\t}\n\t}\n\tif
|
||||
parameter.repoType == \"helm\" {\n\t\tkind: \"HelmRepository\"\n\t\tspec:
|
||||
{\n\t\t\turl: parameter.url\n\t\t\t_secret\n\t\t\t_sourceCommonArgs\n\t\t}\n\t}\n}\n\noutputs:
|
||||
release: {\n\tapiVersion: \"helm.toolkit.fluxcd.io/v2beta1\"\n\tkind:
|
||||
\ \"HelmRelease\"\n\tmetadata: {\n\t\tname: context.name\n\t}\n\tspec:
|
||||
{\n\t\tinterval: parameter.pullInterval\n\t\tchart: {\n\t\t\tspec: {\n\t\t\t\tchart:
|
||||
\ parameter.chart\n\t\t\t\tversion: parameter.version\n\t\t\t\tsourceRef:
|
||||
{\n\t\t\t\t\tif parameter.repoType == \"git\" {\n\t\t\t\t\t\tkind: \"GitRepository\"\n\t\t\t\t\t}\n\t\t\t\t\tif
|
||||
parameter.repoType == \"helm\" {\n\t\t\t\t\t\tkind: \"HelmRepository\"\n\t\t\t\t\t}\n\t\t\t\t\tif
|
||||
parameter.repoType == \"oss\" {\n\t\t\t\t\t\tkind: \"Bucket\"\n\t\t\t\t\t}\n\t\t\t\t\tname:
|
||||
\ context.name\n\t\t\t\t\tnamespace: context.namespace\n\t\t\t\t}\n\t\t\t\tinterval:
|
||||
parameter.pullInterval\n\t\t\t}\n\t\t}\n\t\tif parameter.targetNamespace
|
||||
!= _|_ {\n\t\t\ttargetNamespace: parameter.targetNamespace\n\t\t}\n\t\tif
|
||||
parameter.releaseName != _|_ {\n\t\t\treleaseName: parameter.releaseName\n\t\t}\n\t\tif
|
||||
parameter.values != _|_ {\n\t\t\tvalues: parameter.values\n\t\t}\n\t}\n}\n\n_secret:
|
||||
{\n\tif parameter.secretRef != _|_ {\n\t\tsecretRef: {\n\t\t\tname:
|
||||
parameter.secretRef\n\t\t}\n\t}\n}\n\n_sourceCommonArgs: {\n\tinterval:
|
||||
parameter.pullInterval\n\tif parameter.timeout != _|_ {\n\t\ttimeout:
|
||||
parameter.timeout\n\t}\n}\n\nparameter: {\n\trepoType: *\"helm\" | \"git\"
|
||||
| \"oss\"\n\t// +usage=The interval at which to check for repository/bucket
|
||||
and relese updates, default to 5m\n\tpullInterval: *\"5m\" | string\n\t//
|
||||
+usage=The Git or Helm repository URL, OSS endpoint, accept HTTP/S or
|
||||
SSH address as git url,\n\turl: string\n\t// +usage=The name of the
|
||||
secret containing authentication credentials\n\tsecretRef?: string\n\t//
|
||||
+usage=The timeout for operations like download index/clone repository,
|
||||
optional\n\ttimeout?: string\n\n\tgit?: {\n\t\t// +usage=The Git reference
|
||||
to checkout and monitor for changes, defaults to master branch\n\t\tbranch:
|
||||
string\n\t}\n\toss?: {\n\t\t// +usage=The bucket's name, required if
|
||||
repoType is oss\n\t\tbucketName: string\n\t\t// +usage=\"generic\" for
|
||||
Minio, Amazon S3, Google Cloud Storage, Alibaba Cloud OSS, \"aws\" for
|
||||
retrieve credentials from the EC2 service when credentials not specified,
|
||||
default \"generic\"\n\t\tprovider: *\"generic\" | \"aws\"\n\t\t// +usage=The
|
||||
bucket region, optional\n\t\tregion?: string\n\t}\n\n\t// +usage=1.The
|
||||
relative path to helm chart for git/oss source. 2. chart name for helm
|
||||
resource 3. relative path for chart package(e.g. ./charts/podinfo-1.2.3.tgz)\n\tchart:
|
||||
string\n\t// +usage=Chart version\n\tversion: *\"*\" | string\n\t//
|
||||
+usage=The namespace for helm chart, optional\n\ttargetNamespace?: string\n\t//
|
||||
+usage=The release name\n\treleaseName?: string\n\t// +usage=Chart values\n\tvalues?:
|
||||
#nestedmap\n}\n\n#nestedmap: {\n\t...\n}\n"
|
||||
status:
|
||||
healthPolicy: 'isHealth: len(context.outputs.release.status.conditions)
|
||||
!= 0 && context.outputs.release.status.conditions[0]["status"]=="True"'
|
||||
workload:
|
||||
type: autodetects.core.oam.dev
|
||||
23
pkg/addon/testdata/example-legacy/metadata.yaml
vendored
Normal file
23
pkg/addon/testdata/example-legacy/metadata.yaml
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
name: example-legacy
|
||||
version: 1.0.1
|
||||
description: Extended workload to do continuous and progressive delivery
|
||||
icon: https://raw.githubusercontent.com/fluxcd/flux/master/docs/_files/weave-flux.png
|
||||
url: https://fluxcd.io
|
||||
|
||||
tags:
|
||||
- extended_workload
|
||||
- gitops
|
||||
- only_example
|
||||
|
||||
deployTo:
|
||||
control_plane: true
|
||||
runtime_cluster: false
|
||||
|
||||
dependencies: []
|
||||
#- name: addon_name
|
||||
|
||||
# set invisible means this won't be list and will be enabled when depended on
|
||||
# for example, terraform-alibaba depends on terraform which is invisible,
|
||||
# when terraform-alibaba is enabled, terraform will be enabled automatically
|
||||
# default: false
|
||||
invisible: false
|
||||
19
pkg/addon/testdata/example-legacy/readme.md
vendored
Normal file
19
pkg/addon/testdata/example-legacy/readme.md
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
# Example FluxCD Addon
|
||||
|
||||
This is an example addon based [FluxCD](https://fluxcd.io/)
|
||||
|
||||
## Directory Structure
|
||||
|
||||
- `template.yaml`: contains the basic app, you can add some component and workflow to meet your requirements. Other files
|
||||
in `resources/` and `definitions/` will be rendered as Components and appended in `spec.components`
|
||||
- `metadata.yaml`: contains addon metadata information.
|
||||
- `definitions/`: contains the X-Definition yaml/cue files. These file will be rendered as KubeVela Component in `template.yaml`
|
||||
- `resources/`:
|
||||
- `parameter.cue` to expose parameters. It will be converted to JSON schema and rendered in UI forms.
|
||||
- All other files will be rendered as KubeVela Components. It can be one of the two types:
|
||||
- YAML file that contains only one resource. This will be rendered as a `raw` component
|
||||
- CUE template file that can read user input as `parameter.XXX` as defined `parameter.cue`.
|
||||
Basically the CUE template file will be combined with `parameter.cue` to render a resource.
|
||||
**You can specify the type and trait in this format**
|
||||
|
||||
|
||||
15
pkg/addon/testdata/example-legacy/resources/configmap.cue
vendored
Normal file
15
pkg/addon/testdata/example-legacy/resources/configmap.cue
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
output: {
|
||||
type: "raw"
|
||||
properties: {
|
||||
apiVersion: "v1"
|
||||
kind: "ConfigMap"
|
||||
metadata: {
|
||||
name: "exampleinput"
|
||||
namespace: "default"
|
||||
labels: {
|
||||
version: context.metadata.version
|
||||
}
|
||||
}
|
||||
data: input: parameter.example
|
||||
}
|
||||
}
|
||||
0
pkg/addon/testdata/example-legacy/resources/dummy.txt
vendored
Normal file
0
pkg/addon/testdata/example-legacy/resources/dummy.txt
vendored
Normal file
17
pkg/addon/testdata/example-legacy/resources/service/source-controller.yaml
vendored
Normal file
17
pkg/addon/testdata/example-legacy/resources/service/source-controller.yaml
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/instance: flux-system
|
||||
control-plane: controller
|
||||
name: source-controller
|
||||
namespace: example-system
|
||||
spec:
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
protocol: TCP
|
||||
targetPort: http
|
||||
selector:
|
||||
app: source-controller
|
||||
type: ClusterIP
|
||||
@@ -1,7 +1,7 @@
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: example
|
||||
name: example-legacy
|
||||
namespace: vela-system
|
||||
spec:
|
||||
workflow:
|
||||
3
pkg/addon/testdata/example/parameter.cue
vendored
Normal file
3
pkg/addon/testdata/example/parameter.cue
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
parameter: {
|
||||
example: string
|
||||
}
|
||||
27
pkg/addon/testdata/example/template.cue
vendored
Normal file
27
pkg/addon/testdata/example/template.cue
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
output: {
|
||||
apiVersion: "core.oam.dev/v1beta1"
|
||||
kind: "Application"
|
||||
metadata: {
|
||||
name: "example"
|
||||
namespace: "vela-system"
|
||||
}
|
||||
spec: {
|
||||
workflow: steps: [{
|
||||
name: "apply-ns"
|
||||
type: "apply-component"
|
||||
properties: component: "ns-example-system"
|
||||
}, {
|
||||
name: "apply-resources"
|
||||
type: "apply-remaining"
|
||||
}]
|
||||
components: [{
|
||||
name: "ns-example-system"
|
||||
type: "raw"
|
||||
properties: {
|
||||
apiVersion: "v1"
|
||||
kind: "Namespace"
|
||||
metadata: name: "example-system"
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user