mirror of
https://github.com/kubevela/kubevela.git
synced 2026-08-18 03:56:36 +00:00
fix cli: vela show support list the parameter of ComponentDefinition which use helm charts (#1543)
* vela show support helm * show helm parameter in web * add test * support link jump * add test
This commit is contained in:
@@ -38,15 +38,16 @@ type CRDInfo struct {
|
||||
|
||||
// Capability defines the content of a capability
|
||||
type Capability struct {
|
||||
Name string `json:"name"`
|
||||
Type CapType `json:"type"`
|
||||
CueTemplate string `json:"template,omitempty"`
|
||||
CueTemplateURI string `json:"templateURI,omitempty"`
|
||||
Parameters []Parameter `json:"parameters,omitempty"`
|
||||
CrdName string `json:"crdName,omitempty"`
|
||||
Center string `json:"center,omitempty"`
|
||||
Status string `json:"status,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Name string `json:"name"`
|
||||
Type CapType `json:"type"`
|
||||
CueTemplate string `json:"template,omitempty"`
|
||||
CueTemplateURI string `json:"templateURI,omitempty"`
|
||||
Parameters []Parameter `json:"parameters,omitempty"`
|
||||
CrdName string `json:"crdName,omitempty"`
|
||||
Center string `json:"center,omitempty"`
|
||||
Status string `json:"status,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Category CapabilityCategory `json:"category,omitempty"`
|
||||
|
||||
// trait only
|
||||
AppliesTo []string `json:"appliesTo,omitempty"`
|
||||
@@ -121,6 +122,7 @@ type Parameter struct {
|
||||
Usage string `json:"usage,omitempty"`
|
||||
Type cue.Kind `json:"type,omitempty"`
|
||||
Alias string `json:"alias,omitempty"`
|
||||
JSONType string `json:"jsonType,omitempty"`
|
||||
}
|
||||
|
||||
// SetFlagBy set cli flag from Parameter
|
||||
|
||||
@@ -43,6 +43,7 @@ var app v1beta1.Application
|
||||
var testShowCdDef v1beta1.ComponentDefinition
|
||||
var testShowTdDef v1beta1.TraitDefinition
|
||||
var testCdDef v1beta1.ComponentDefinition
|
||||
var testCdDefWithHelm v1beta1.ComponentDefinition
|
||||
var testTdDef v1beta1.TraitDefinition
|
||||
|
||||
func TestKubectlPlugin(t *testing.T) {
|
||||
@@ -75,6 +76,10 @@ var _ = BeforeSuite(func(done Done) {
|
||||
err = k8sClient.Create(ctx, &testCdDef)
|
||||
Expect(err).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{}))
|
||||
|
||||
Expect(yaml.Unmarshal([]byte(componentDefWithHelm), &testCdDefWithHelm)).Should(BeNil())
|
||||
err = k8sClient.Create(ctx, &testCdDefWithHelm)
|
||||
Expect(err).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{}))
|
||||
|
||||
Expect(yaml.Unmarshal([]byte(traitDef), &testTdDef)).Should(BeNil())
|
||||
err = k8sClient.Create(ctx, &testTdDef)
|
||||
Expect(err).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{}))
|
||||
@@ -99,6 +104,7 @@ var _ = AfterSuite(func() {
|
||||
By("delete application and definitions")
|
||||
Expect(k8sClient.Delete(ctx, &app)).Should(BeNil())
|
||||
Expect(k8sClient.Delete(ctx, &testCdDef)).Should(BeNil())
|
||||
Expect(k8sClient.Delete(ctx, &testCdDefWithHelm)).Should(BeNil())
|
||||
Expect(k8sClient.Delete(ctx, &testTdDef)).Should(BeNil())
|
||||
Expect(k8sClient.Delete(ctx, &testShowCdDef)).Should(BeNil())
|
||||
Expect(k8sClient.Delete(ctx, &testShowTdDef)).Should(BeNil())
|
||||
|
||||
@@ -117,6 +117,12 @@ var _ = Describe("Test Kubectl Plugin", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(output).Should(Equal(showTdResult))
|
||||
})
|
||||
It("Test show componentDefinition use Helm Charts as Workload", func() {
|
||||
cdName := "test-webapp-chart"
|
||||
output, err := e2e.Exec(fmt.Sprintf("kubectl-vela show %s", cdName))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(output).Should(ContainSubstring("Properties"))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -344,6 +350,30 @@ spec:
|
||||
|
||||
`
|
||||
|
||||
var componentDefWithHelm = `
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: ComponentDefinition
|
||||
metadata:
|
||||
name: test-webapp-chart
|
||||
namespace: default
|
||||
annotations:
|
||||
definition.oam.dev/description: helm chart for webapp
|
||||
spec:
|
||||
workload:
|
||||
definition:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
schematic:
|
||||
helm:
|
||||
release:
|
||||
chart:
|
||||
spec:
|
||||
chart: "podinfo"
|
||||
version: "5.1.4"
|
||||
repository:
|
||||
url: "http://oam.dev/catalog/"
|
||||
`
|
||||
|
||||
var traitDef = `
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: TraitDefinition
|
||||
|
||||
@@ -17,6 +17,7 @@ limitations under the License.
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
@@ -25,7 +26,8 @@ import (
|
||||
|
||||
func main() {
|
||||
ref := &plugins.MarkdownReference{}
|
||||
if err := ref.GenerateReferenceDocs(plugins.BaseRefPath); err != nil {
|
||||
ctx := context.Background()
|
||||
if err := ref.GenerateReferenceDocs(ctx, plugins.BaseRefPath); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
+34
-4
@@ -132,8 +132,18 @@ func startReferenceDocsSite(ctx context.Context, c common.Args, ioStreams cmduti
|
||||
if !capabilityIsValid {
|
||||
return fmt.Errorf("%s is not a valid component type or trait", capabilityName)
|
||||
}
|
||||
ref := &plugins.MarkdownReference{}
|
||||
if err := ref.CreateMarkdown(capabilities, docsPath, plugins.ReferenceSourcePath); err != nil {
|
||||
|
||||
cli, err := c.GetClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ref := &plugins.MarkdownReference{
|
||||
ParseReference: plugins.ParseReference{
|
||||
Client: cli,
|
||||
},
|
||||
}
|
||||
|
||||
if err := ref.CreateMarkdown(ctx, capabilities, docsPath, plugins.ReferenceSourcePath); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -345,11 +355,31 @@ func ShowReferenceConsole(ctx context.Context, c common.Args, ioStreams cmdutil.
|
||||
return err
|
||||
}
|
||||
|
||||
ref := &plugins.ConsoleReference{}
|
||||
propertyConsole, err := ref.GenerateCapabilityProperties(capability)
|
||||
cli, err := c.GetClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ref := &plugins.ConsoleReference{
|
||||
ParseReference: plugins.ParseReference{
|
||||
Client: cli,
|
||||
},
|
||||
}
|
||||
|
||||
var propertyConsole []plugins.ConsoleReference
|
||||
switch capability.Category {
|
||||
case types.HelmCategory:
|
||||
_, propertyConsole, err = ref.GenerateHELMProperties(ctx, capability)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case types.CUECategory:
|
||||
propertyConsole, err = ref.GenerateCUETemplateProperties(capability)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("unsupport capability category %s", capability.Category)
|
||||
}
|
||||
for _, p := range propertyConsole {
|
||||
ioStreams.Info(p.TableName)
|
||||
p.TableObject.Render()
|
||||
|
||||
@@ -205,15 +205,17 @@ func HandleTemplate(in *runtime.RawExtension, schematic *commontypes.Schematic,
|
||||
tmp.CueTemplate = string(b)
|
||||
}
|
||||
if tmp.CueTemplate == "" {
|
||||
if schematic != nil && schematic.HELM != nil {
|
||||
tmp.Category = types.HelmCategory
|
||||
return tmp, nil
|
||||
}
|
||||
return types.Capability{}, errors.New("template not exist in definition")
|
||||
}
|
||||
if err != nil {
|
||||
return types.Capability{}, err
|
||||
}
|
||||
tmp.Parameters, err = cue.GetParameters(tmp.CueTemplate)
|
||||
if err != nil {
|
||||
return types.Capability{}, err
|
||||
}
|
||||
tmp.Category = types.CUECategory
|
||||
return tmp, nil
|
||||
}
|
||||
|
||||
@@ -278,6 +280,7 @@ func SyncDefinitionToLocal(ctx context.Context, c common.Args, capabilityName st
|
||||
template, err := HandleDefinition(capabilityName, ref.Name,
|
||||
componentDef.Annotations, componentDef.Spec.Extension, types.TypeComponentDefinition, nil, componentDef.Spec.Schematic)
|
||||
if err == nil {
|
||||
template.Namespace = componentDef.Namespace
|
||||
return &template, nil
|
||||
}
|
||||
}
|
||||
@@ -297,6 +300,7 @@ func SyncDefinitionToLocal(ctx context.Context, c common.Args, capabilityName st
|
||||
template, err := HandleDefinition(capabilityName, traitDef.Spec.Reference.Name,
|
||||
traitDef.Annotations, traitDef.Spec.Extension, types.TypeTrait, nil, traitDef.Spec.Schematic)
|
||||
if err == nil {
|
||||
template.Namespace = traitDef.Namespace
|
||||
return &template, nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ var _ = Describe("DefinitionFiles", func() {
|
||||
Type: types.TypeComponentDefinition,
|
||||
CrdName: "deployments.apps",
|
||||
Description: "description not defined",
|
||||
Category: types.CUECategory,
|
||||
Parameters: []types.Parameter{
|
||||
{
|
||||
Type: cue.ListKind,
|
||||
@@ -80,6 +81,7 @@ var _ = Describe("DefinitionFiles", func() {
|
||||
Name: WebserviceName,
|
||||
Type: types.TypeComponentDefinition,
|
||||
Description: "description not defined",
|
||||
Category: types.CUECategory,
|
||||
Parameters: []types.Parameter{{
|
||||
Name: "env", Type: cue.ListKind,
|
||||
}, {
|
||||
|
||||
@@ -17,12 +17,16 @@ limitations under the License.
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/crossplane/crossplane-runtime/pkg/test"
|
||||
"github.com/getkin/kin-openapi/openapi3"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
@@ -68,11 +72,13 @@ parameter: {
|
||||
Name: workloadName,
|
||||
Type: types.TypeWorkload,
|
||||
CueTemplate: workloadCueTemplate,
|
||||
Category: types.CUECategory,
|
||||
},
|
||||
{
|
||||
Name: traitName,
|
||||
Type: types.TypeTrait,
|
||||
CueTemplate: traitCueTemplate,
|
||||
Category: types.CUECategory,
|
||||
},
|
||||
},
|
||||
want: nil,
|
||||
@@ -89,9 +95,10 @@ parameter: {
|
||||
},
|
||||
}
|
||||
ref := &MarkdownReference{}
|
||||
ctx := context.Background()
|
||||
for name, tc := range cases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
got := ref.CreateMarkdown(tc.capabilities, RefTestDir, ReferenceSourcePath)
|
||||
got := ref.CreateMarkdown(ctx, tc.capabilities, RefTestDir, ReferenceSourcePath)
|
||||
if diff := cmp.Diff(tc.want, got, test.EquateErrors()); diff != "" {
|
||||
t.Errorf("\n%s\nCreateMakrdown(...): -want error, +got error:\n%s", tc.reason, diff)
|
||||
}
|
||||
@@ -113,7 +120,7 @@ func TestPrepareParameterTable(t *testing.T) {
|
||||
parameterName := "cpu"
|
||||
parameterList[0].Name = parameterName
|
||||
parameterList[0].Required = true
|
||||
refContent := ref.prepareParameter(tableName, parameterList)
|
||||
refContent := ref.prepareParameter(tableName, parameterList, types.CUECategory)
|
||||
assert.Contains(t, refContent, parameterName)
|
||||
assert.Contains(t, refContent, "cpu")
|
||||
}
|
||||
@@ -124,3 +131,197 @@ func TestDeleteRefTestDir(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWalkParameterSchema(t *testing.T) {
|
||||
testcases := []struct {
|
||||
data string
|
||||
ExpectRefs map[string]map[string]ReferenceParameter
|
||||
}{
|
||||
{
|
||||
data: `{
|
||||
"properties": {
|
||||
"cmd": {
|
||||
"description": "Commands to run in the container",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"title": "cmd",
|
||||
"type": "array"
|
||||
},
|
||||
"image": {
|
||||
"description": "Which image would you like to use for your service",
|
||||
"title": "image",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"image"
|
||||
],
|
||||
"type": "object"
|
||||
}`,
|
||||
ExpectRefs: map[string]map[string]ReferenceParameter{
|
||||
"# Properties": {
|
||||
"cmd": ReferenceParameter{
|
||||
Parameter: types.Parameter{
|
||||
Name: "cmd",
|
||||
Usage: "Commands to run in the container",
|
||||
JSONType: "array",
|
||||
},
|
||||
PrintableType: "array",
|
||||
},
|
||||
"image": ReferenceParameter{
|
||||
Parameter: types.Parameter{
|
||||
Name: "image",
|
||||
Required: true,
|
||||
Usage: "Which image would you like to use for your service",
|
||||
JSONType: "string",
|
||||
},
|
||||
PrintableType: "string",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
data: `{
|
||||
"properties": {
|
||||
"obj": {
|
||||
"properties": {
|
||||
"f0": {
|
||||
"default": "v0",
|
||||
"type": "string"
|
||||
},
|
||||
"f1": {
|
||||
"default": "v1",
|
||||
"type": "string"
|
||||
},
|
||||
"f2": {
|
||||
"default": "v2",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
},
|
||||
"type": "object"
|
||||
}`,
|
||||
ExpectRefs: map[string]map[string]ReferenceParameter{
|
||||
"# Properties": {
|
||||
"obj": ReferenceParameter{
|
||||
Parameter: types.Parameter{
|
||||
Name: "obj",
|
||||
JSONType: "object",
|
||||
},
|
||||
PrintableType: "[obj](#obj)",
|
||||
},
|
||||
},
|
||||
"## obj": {
|
||||
"f0": ReferenceParameter{
|
||||
Parameter: types.Parameter{
|
||||
Name: "f0",
|
||||
Default: "v0",
|
||||
JSONType: "string",
|
||||
},
|
||||
PrintableType: "string",
|
||||
},
|
||||
"f1": ReferenceParameter{
|
||||
Parameter: types.Parameter{
|
||||
Name: "f1",
|
||||
Default: "v1",
|
||||
JSONType: "string",
|
||||
},
|
||||
PrintableType: "string",
|
||||
},
|
||||
"f2": ReferenceParameter{
|
||||
Parameter: types.Parameter{
|
||||
Name: "f2",
|
||||
Default: "v2",
|
||||
JSONType: "string",
|
||||
},
|
||||
PrintableType: "string",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
data: `{
|
||||
"properties": {
|
||||
"obj": {
|
||||
"properties": {
|
||||
"f0": {
|
||||
"default": "v0",
|
||||
"type": "string"
|
||||
},
|
||||
"f1": {
|
||||
"default": "v1",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"g0": {
|
||||
"default": "v2",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}`,
|
||||
ExpectRefs: map[string]map[string]ReferenceParameter{
|
||||
"# Properties": {
|
||||
"obj": ReferenceParameter{
|
||||
Parameter: types.Parameter{
|
||||
Name: "obj",
|
||||
JSONType: "object",
|
||||
},
|
||||
PrintableType: "[obj](#obj)",
|
||||
},
|
||||
},
|
||||
"## obj": {
|
||||
"f0": ReferenceParameter{
|
||||
Parameter: types.Parameter{
|
||||
Name: "f0",
|
||||
Default: "v0",
|
||||
JSONType: "string",
|
||||
},
|
||||
PrintableType: "string",
|
||||
},
|
||||
"f1": ReferenceParameter{
|
||||
Parameter: types.Parameter{
|
||||
Name: "f1",
|
||||
Default: "v1",
|
||||
JSONType: "object",
|
||||
},
|
||||
PrintableType: "[f1](#f1)",
|
||||
},
|
||||
},
|
||||
"### f1": {
|
||||
"g0": ReferenceParameter{
|
||||
Parameter: types.Parameter{
|
||||
Name: "g0",
|
||||
Default: "v2",
|
||||
JSONType: "string",
|
||||
},
|
||||
PrintableType: "string",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, cases := range testcases {
|
||||
helmRefs = make([]HELMReference, 0)
|
||||
parameterJSON := fmt.Sprintf(BaseOpenAPIV3Template, cases.data)
|
||||
swagger, err := openapi3.NewSwaggerLoader().LoadSwaggerFromData(json.RawMessage(parameterJSON))
|
||||
assert.Equal(t, nil, err)
|
||||
parameters := swagger.Components.Schemas["parameter"].Value
|
||||
WalkParameterSchema(parameters, "Properties", 0)
|
||||
refs := make(map[string]map[string]ReferenceParameter)
|
||||
for _, items := range helmRefs {
|
||||
refs[items.Name] = make(map[string]ReferenceParameter)
|
||||
for _, item := range items.Parameters {
|
||||
refs[items.Name][item.Name] = item
|
||||
}
|
||||
}
|
||||
assert.Equal(t, true, reflect.DeepEqual(cases.ExpectRefs, refs))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ limitations under the License.
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
@@ -25,7 +27,11 @@ import (
|
||||
"strings"
|
||||
|
||||
"cuelang.org/go/cue"
|
||||
"github.com/getkin/kin-openapi/openapi3"
|
||||
"github.com/olekukonko/tablewriter"
|
||||
"github.com/pkg/errors"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/types"
|
||||
mycue "github.com/oam-dev/kubevela/pkg/cue"
|
||||
@@ -62,6 +68,7 @@ type Reference interface {
|
||||
|
||||
// ParseReference is used to include the common function `parseParameter`
|
||||
type ParseReference struct {
|
||||
Client client.Client
|
||||
}
|
||||
|
||||
// MarkdownReference is the struct for capability information in
|
||||
@@ -181,6 +188,21 @@ services:
|
||||
`,
|
||||
}
|
||||
|
||||
// BaseOpenAPIV3Template is Standard OpenAPIV3 Template
|
||||
var BaseOpenAPIV3Template = `{
|
||||
"openapi": "3.0.0",
|
||||
"info": {
|
||||
"title": "definition-parameter",
|
||||
"version": "1.0"
|
||||
},
|
||||
"paths": {},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"parameter": %s
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
// ReferenceParameter is the parameter section of CUE template
|
||||
type ReferenceParameter struct {
|
||||
types.Parameter `json:",inline,omitempty"`
|
||||
@@ -194,13 +216,14 @@ var refContent string
|
||||
var recurseDepth *int
|
||||
var propertyConsole []ConsoleReference
|
||||
var displayFormat *string
|
||||
var helmRefs []HELMReference
|
||||
|
||||
func setDisplayFormat(format string) {
|
||||
displayFormat = &format
|
||||
}
|
||||
|
||||
// GenerateReferenceDocs generates reference docs
|
||||
func (ref *MarkdownReference) GenerateReferenceDocs(baseRefPath string) error {
|
||||
func (ref *MarkdownReference) GenerateReferenceDocs(ctx context.Context, baseRefPath string) error {
|
||||
c, err := common.InitBaseRestConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -212,15 +235,15 @@ func (ref *MarkdownReference) GenerateReferenceDocs(baseRefPath string) error {
|
||||
if baseRefPath == "" {
|
||||
baseRefPath = BaseRefPath
|
||||
}
|
||||
return ref.CreateMarkdown(caps, baseRefPath, ReferenceSourcePath)
|
||||
return ref.CreateMarkdown(ctx, caps, baseRefPath, ReferenceSourcePath)
|
||||
}
|
||||
|
||||
// CreateMarkdown creates markdown based on capabilities
|
||||
func (ref *MarkdownReference) CreateMarkdown(caps []types.Capability, baseRefPath, referenceSourcePath string) error {
|
||||
func (ref *MarkdownReference) CreateMarkdown(ctx context.Context, caps []types.Capability, baseRefPath, referenceSourcePath string) error {
|
||||
setDisplayFormat("markdown")
|
||||
var capabilityType string
|
||||
var specificationType string
|
||||
for _, c := range caps {
|
||||
for i, c := range caps {
|
||||
switch c.Type {
|
||||
case types.TypeWorkload:
|
||||
capabilityType = WorkloadTypePath
|
||||
@@ -253,25 +276,35 @@ func (ref *MarkdownReference) CreateMarkdown(caps []types.Capability, baseRefPat
|
||||
return fmt.Errorf("failed to truncate file %s: %w", markdownFile, err)
|
||||
}
|
||||
capName := c.Name
|
||||
|
||||
cueValue, err := common.GetCUEParameterValue(c.CueTemplate)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to retrieve `parameters` value from %s with err: %w", c.Name, err)
|
||||
}
|
||||
refContent = ""
|
||||
var defaultDepth = 0
|
||||
recurseDepth = &defaultDepth
|
||||
capNameInTitle := strings.Title(capName)
|
||||
if err := ref.parseParameters(cueValue, "Properties", defaultDepth); err != nil {
|
||||
return err
|
||||
switch c.Category {
|
||||
case types.CUECategory:
|
||||
cueValue, err := common.GetCUEParameterValue(c.CueTemplate)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to retrieve `parameters` value from %s with err: %w", c.Name, err)
|
||||
}
|
||||
var defaultDepth = 0
|
||||
recurseDepth = &defaultDepth
|
||||
if err := ref.parseParameters(cueValue, "Properties", defaultDepth); err != nil {
|
||||
return err
|
||||
}
|
||||
case types.HelmCategory:
|
||||
properties, _, err := ref.GenerateHELMProperties(ctx, &caps[i])
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to retrieve `parameters` value from %s with err: %w", c.Name, err)
|
||||
}
|
||||
for _, property := range properties {
|
||||
refContent += ref.prepareParameter("#"+property.Name, property.Parameters, types.HelmCategory)
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("unsupport capability category %s", c.Category)
|
||||
}
|
||||
|
||||
title := fmt.Sprintf("# %s", capNameInTitle)
|
||||
description := fmt.Sprintf("\n\n## Description\n\n%s", c.Description)
|
||||
specificationIntro := fmt.Sprintf("List of all configuration options for a `%s` %s.", capNameInTitle, specificationType)
|
||||
specificationContent := ref.generateSpecification(capName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
specification := fmt.Sprintf("\n\n## Specification\n\n%s\n\n%s", specificationIntro, specificationContent)
|
||||
|
||||
// it's fine if the conflict info files not found
|
||||
@@ -289,26 +322,45 @@ func (ref *MarkdownReference) CreateMarkdown(caps []types.Capability, baseRefPat
|
||||
}
|
||||
|
||||
// prepareParameter prepares the table content for each property
|
||||
func (ref *MarkdownReference) prepareParameter(tableName string, parameterList []ReferenceParameter) string {
|
||||
func (ref *MarkdownReference) prepareParameter(tableName string, parameterList []ReferenceParameter, category types.CapabilityCategory) string {
|
||||
refContent := fmt.Sprintf("\n\n%s\n\n", tableName)
|
||||
refContent += "Name | Description | Type | Required | Default \n"
|
||||
refContent += "------------ | ------------- | ------------- | ------------- | ------------- \n"
|
||||
for _, p := range parameterList {
|
||||
printableDefaultValue := ref.getPrintableDefaultValue(p.Default)
|
||||
refContent += fmt.Sprintf(" %s | %s | %s | %t | %s \n", p.Name, p.Usage, p.PrintableType, p.Required, printableDefaultValue)
|
||||
switch category {
|
||||
case types.CUECategory:
|
||||
for _, p := range parameterList {
|
||||
printableDefaultValue := ref.getCUEPrintableDefaultValue(p.Default)
|
||||
refContent += fmt.Sprintf(" %s | %s | %s | %t | %s \n", p.Name, p.Usage, p.PrintableType, p.Required, printableDefaultValue)
|
||||
}
|
||||
case types.HelmCategory:
|
||||
for _, p := range parameterList {
|
||||
printableDefaultValue := ref.getHELMPrintableDefaultValue(p.JSONType, p.Default)
|
||||
refContent += fmt.Sprintf(" %s | %s | %s | %t | %s \n", p.Name, strings.ReplaceAll(p.Usage, "\n", ""), p.PrintableType, p.Required, printableDefaultValue)
|
||||
}
|
||||
default:
|
||||
}
|
||||
return refContent
|
||||
}
|
||||
|
||||
// prepareParameter prepares the table content for each property
|
||||
func (ref *ConsoleReference) prepareParameter(tableName string, parameterList []ReferenceParameter) ConsoleReference {
|
||||
func (ref *ParseReference) prepareParameter(tableName string, parameterList []ReferenceParameter, category types.CapabilityCategory) ConsoleReference {
|
||||
table := tablewriter.NewWriter(os.Stdout)
|
||||
table.SetColWidth(100)
|
||||
table.SetHeader([]string{"Name", "Description", "Type", "Required", "Default"})
|
||||
for _, p := range parameterList {
|
||||
printableDefaultValue := ref.getPrintableDefaultValue(p.Default)
|
||||
table.Append([]string{p.Name, p.Usage, p.PrintableType, strconv.FormatBool(p.Required), printableDefaultValue})
|
||||
switch category {
|
||||
case types.CUECategory:
|
||||
for _, p := range parameterList {
|
||||
printableDefaultValue := ref.getCUEPrintableDefaultValue(p.Default)
|
||||
table.Append([]string{p.Name, p.Usage, p.PrintableType, strconv.FormatBool(p.Required), printableDefaultValue})
|
||||
}
|
||||
case types.HelmCategory:
|
||||
for _, p := range parameterList {
|
||||
printableDefaultValue := ref.getHELMPrintableDefaultValue(p.JSONType, p.Default)
|
||||
table.Append([]string{p.Name, p.Usage, p.PrintableType, strconv.FormatBool(p.Required), printableDefaultValue})
|
||||
}
|
||||
default:
|
||||
}
|
||||
|
||||
return ConsoleReference{TableName: tableName, TableObject: table}
|
||||
}
|
||||
|
||||
@@ -382,18 +434,18 @@ func (ref *ParseReference) parseParameters(paraValue cue.Value, paramKey string,
|
||||
case "markdown":
|
||||
tableName := fmt.Sprintf("%s %s", strings.Repeat("#", depth+2), paramKey)
|
||||
ref := MarkdownReference{}
|
||||
refContent = ref.prepareParameter(tableName, params) + refContent
|
||||
refContent = ref.prepareParameter(tableName, params, types.CUECategory) + refContent
|
||||
case "console":
|
||||
ref := ConsoleReference{}
|
||||
tableName := fmt.Sprintf("%s %s", strings.Repeat("#", depth+1), paramKey)
|
||||
console := ref.prepareParameter(tableName, params)
|
||||
console := ref.prepareParameter(tableName, params, types.CUECategory)
|
||||
propertyConsole = append([]ConsoleReference{console}, propertyConsole...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// getPrintableDefaultValue converts the value in `interface{}` type to be printable
|
||||
func (ref *ParseReference) getPrintableDefaultValue(v interface{}) string {
|
||||
// getCUEPrintableDefaultValue converts the value in `interface{}` type to be printable
|
||||
func (ref *ParseReference) getCUEPrintableDefaultValue(v interface{}) string {
|
||||
if v == nil {
|
||||
return ""
|
||||
}
|
||||
@@ -411,6 +463,20 @@ func (ref *ParseReference) getPrintableDefaultValue(v interface{}) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (ref *ParseReference) getHELMPrintableDefaultValue(dataType string, value interface{}) string {
|
||||
if value != nil {
|
||||
return strings.TrimSpace(fmt.Sprintf("%v", value))
|
||||
}
|
||||
defaultValueMap := map[string]string{
|
||||
"number": "0",
|
||||
"boolean": "false",
|
||||
"string": "\"\"",
|
||||
"object": "{}",
|
||||
"array": "[]",
|
||||
}
|
||||
return defaultValueMap[dataType]
|
||||
}
|
||||
|
||||
// generateSpecification generates Specification part for reference docs
|
||||
func (ref *MarkdownReference) generateSpecification(capabilityName string) string {
|
||||
return fmt.Sprintf("```yaml%s```", ConfigurationYamlSample[capabilityName])
|
||||
@@ -429,8 +495,8 @@ func (ref *MarkdownReference) generateConflictWithAndMore(capabilityName string,
|
||||
return "\n" + string(data), nil
|
||||
}
|
||||
|
||||
// GenerateCapabilityProperties get all properties of a capability
|
||||
func (ref *ConsoleReference) GenerateCapabilityProperties(capability *types.Capability) ([]ConsoleReference, error) {
|
||||
// GenerateCUETemplateProperties get all properties of a capability
|
||||
func (ref *ConsoleReference) GenerateCUETemplateProperties(capability *types.Capability) ([]ConsoleReference, error) {
|
||||
setDisplayFormat("console")
|
||||
capName := capability.Name
|
||||
|
||||
@@ -446,3 +512,91 @@ func (ref *ConsoleReference) GenerateCapabilityProperties(capability *types.Capa
|
||||
|
||||
return propertyConsole, nil
|
||||
}
|
||||
|
||||
// HELMReference contains parameters info of HelmCategory type capability
|
||||
type HELMReference struct {
|
||||
Name string
|
||||
Parameters []ReferenceParameter
|
||||
Depth int
|
||||
}
|
||||
|
||||
// HELMSchema is a struct contains *openapi3.Schema style parameter
|
||||
type HELMSchema struct {
|
||||
Name string
|
||||
Schemas *openapi3.Schema
|
||||
}
|
||||
|
||||
// GenerateHELMProperties get all properties of a HelmCategory type capability
|
||||
func (ref *ParseReference) GenerateHELMProperties(ctx context.Context, capability *types.Capability) ([]HELMReference, []ConsoleReference, error) {
|
||||
cmName := fmt.Sprintf("%s%s", types.CapabilityConfigMapNamePrefix, capability.Name)
|
||||
var cm v1.ConfigMap
|
||||
helmRefs = make([]HELMReference, 0)
|
||||
if err := ref.Client.Get(ctx, client.ObjectKey{Namespace: capability.Namespace, Name: cmName}, &cm); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
data, ok := cm.Data[types.OpenapiV3JSONSchema]
|
||||
if !ok {
|
||||
return nil, nil, errors.Errorf("configMap doesn't have openapi-v3-json-schema data")
|
||||
}
|
||||
parameterJSON := fmt.Sprintf(BaseOpenAPIV3Template, data)
|
||||
swagger, err := openapi3.NewSwaggerLoader().LoadSwaggerFromData(json.RawMessage(parameterJSON))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
parameters := swagger.Components.Schemas["parameter"].Value
|
||||
WalkParameterSchema(parameters, "Properties", 0)
|
||||
|
||||
var consoleRefs []ConsoleReference
|
||||
for _, item := range helmRefs {
|
||||
consoleRefs = append(consoleRefs, ref.prepareParameter(item.Name, item.Parameters, types.HelmCategory))
|
||||
}
|
||||
return helmRefs, consoleRefs, err
|
||||
}
|
||||
|
||||
// WalkParameterSchema will extract properties from *openapi3.Schema
|
||||
func WalkParameterSchema(parameters *openapi3.Schema, name string, depth int) {
|
||||
if parameters == nil {
|
||||
return
|
||||
}
|
||||
var schemas []HELMSchema
|
||||
var helmParameters []ReferenceParameter
|
||||
for k, v := range parameters.Properties {
|
||||
p := ReferenceParameter{
|
||||
Parameter: types.Parameter{
|
||||
Name: k,
|
||||
Default: v.Value.Default,
|
||||
Usage: v.Value.Description,
|
||||
JSONType: v.Value.Type,
|
||||
},
|
||||
PrintableType: v.Value.Type,
|
||||
}
|
||||
required := false
|
||||
for _, requiredType := range parameters.Required {
|
||||
if k == requiredType {
|
||||
required = true
|
||||
break
|
||||
}
|
||||
}
|
||||
p.Required = required
|
||||
if v.Value.Type == "object" {
|
||||
if v.Value.Properties != nil {
|
||||
schemas = append(schemas, HELMSchema{
|
||||
Name: k,
|
||||
Schemas: v.Value,
|
||||
})
|
||||
}
|
||||
p.PrintableType = fmt.Sprintf("[%s](#%s)", k, k)
|
||||
}
|
||||
helmParameters = append(helmParameters, p)
|
||||
}
|
||||
|
||||
helmRefs = append(helmRefs, HELMReference{
|
||||
Name: fmt.Sprintf("%s %s", strings.Repeat("#", depth+1), name),
|
||||
Parameters: helmParameters,
|
||||
Depth: depth + 1,
|
||||
})
|
||||
|
||||
for _, schema := range schemas {
|
||||
WalkParameterSchema(schema.Schemas, schema.Name, depth+1)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user