From 3bdf7a044f9e4c195c6f43c86ea0c76b582fe9e1 Mon Sep 17 00:00:00 2001 From: Yue Wang Date: Wed, 31 Mar 2021 18:31:54 +0900 Subject: [PATCH] fix generate schema for helm values (#1375) Signed-off-by: roy wang --- pkg/appfile/helm/schema.go | 10 +- pkg/appfile/helm/schema_test.go | 33 +- .../helm/testdata/podinfo.values.schema.json | 345 ++++++++++++++++++ pkg/appfile/helm/testdata/values.schema.json | 29 +- pkg/appfile/helm/testdata/values.yaml | 7 +- 5 files changed, 410 insertions(+), 14 deletions(-) create mode 100644 pkg/appfile/helm/testdata/podinfo.values.schema.json diff --git a/pkg/appfile/helm/schema.go b/pkg/appfile/helm/schema.go index 86711661d..7945a0fe7 100644 --- a/pkg/appfile/helm/schema.go +++ b/pkg/appfile/helm/schema.go @@ -208,9 +208,13 @@ func handleItemsOfArrayType(t map[string]interface{}) { } if t["type"] == "array" { if i, ok := t["items"].([]interface{}); ok { - itemSpec, _ := i[0].(map[string]interface{}) - itemSpec["enum"] = nil - t["items"] = itemSpec + if len(i) > 0 { + if itemSpec, ok := i[0].(map[string]interface{}); ok { + handleItemsOfArrayType(itemSpec) + itemSpec["enum"] = nil + t["items"] = itemSpec + } + } } } } diff --git a/pkg/appfile/helm/schema_test.go b/pkg/appfile/helm/schema_test.go index 2a2ad819a..28d17e187 100644 --- a/pkg/appfile/helm/schema_test.go +++ b/pkg/appfile/helm/schema_test.go @@ -54,7 +54,7 @@ func TestGenerateSchemaFromValues(t *testing.T) { func TestGetChartValuesJSONSchema(t *testing.T) { testHelm := testData("podinfo", "5.1.4", "http://oam.dev/catalog") - wantSchema, err := ioutil.ReadFile("./testdata/values.schema.json") + wantSchema, err := ioutil.ReadFile("./testdata/podinfo.values.schema.json") if err != nil { t.Error(err, "cannot load expected data") } @@ -241,6 +241,37 @@ func TestMakeSwaggerCompatible(t *testing.T) { }}`, want: `{"objectArray":{"items":{"enum":null,"properties":{"f0":{"enum":["v0"],"type":"string"},"f1":{"enum":["v1"],"type":"string"},"f2":{"enum":["v2"],"type":"string"}},"required":["f0","f1","f2"],"type":"object"},"type":"array"}}`, }, + { + caseName: "object type array embeds object type array", + testdata: `{ + "objectArray": { + "type": "array", + "items": [ + { + "type": "array", + "items": [ + { + "type": "object", + "required": [ + "f0" + ], + "properties": { + "f0": { + "type": "string", + "enum": [ + "v0" + ] + } + } + } + ] + } + ] + } +} +`, + want: `{"objectArray":{"items":{"enum":null,"items":{"enum":null,"properties":{"f0":{"enum":["v0"],"type":"string"}},"required":["f0"],"type":"object"},"type":"array"},"type":"array"}}`, + }, } for _, tc := range tests { diff --git a/pkg/appfile/helm/testdata/podinfo.values.schema.json b/pkg/appfile/helm/testdata/podinfo.values.schema.json new file mode 100644 index 000000000..ac637b138 --- /dev/null +++ b/pkg/appfile/helm/testdata/podinfo.values.schema.json @@ -0,0 +1,345 @@ +{ + "properties": { + "affinity": { + "type": "object" + }, + "backend": { + "nullable": true + }, + "backends": { + "default": [], + "type": "array" + }, + "cache": { + "default": "", + "description": "Redis address in the format :", + "type": "string" + }, + "certificate": { + "description": "create a certificate manager certificate", + "properties": { + "create": { + "default": false, + "type": "boolean" + }, + "dnsNames": { + "default": [ + "podinfo" + ], + "description": "the hostname / subject alternative names for the certificate", + "items": { + "type": "string" + }, + "type": "array" + }, + "issuerRef": { + "description": "the issuer used to issue the certificate", + "properties": { + "kind": { + "default": "ClusterIssuer", + "type": "string" + }, + "name": { + "default": "self-signed", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "faults": { + "properties": { + "delay": { + "default": false, + "type": "boolean" + }, + "error": { + "default": false, + "type": "boolean" + }, + "testFail": { + "default": false, + "type": "boolean" + }, + "testTimeout": { + "default": false, + "type": "boolean" + }, + "unhealthy": { + "default": false, + "type": "boolean" + }, + "unready": { + "default": false, + "type": "boolean" + } + }, + "type": "object" + }, + "h2c": { + "properties": { + "enabled": { + "default": false, + "type": "boolean" + } + }, + "type": "object" + }, + "hpa": { + "description": "metrics-server add-on required", + "properties": { + "cpu": { + "description": "average total CPU usage per pod (1-100)", + "nullable": true + }, + "enabled": { + "default": false, + "type": "boolean" + }, + "maxReplicas": { + "default": 10, + "type": "integer" + }, + "memory": { + "description": "average memory usage per pod (100Mi-1Gi)", + "nullable": true + }, + "requests": { + "description": "average http requests per second per pod (k8s-prometheus-adapter)", + "nullable": true + } + }, + "type": "object" + }, + "image": { + "properties": { + "pullPolicy": { + "default": "IfNotPresent", + "type": "string" + }, + "repository": { + "default": "ghcr.io/stefanprodan/podinfo", + "type": "string" + }, + "tag": { + "default": "5.1.4", + "type": "string" + } + }, + "type": "object" + }, + "ingress": { + "properties": { + "annotations": { + "type": "object" + }, + "enabled": { + "default": false, + "type": "boolean" + }, + "hosts": { + "default": [], + "type": "array" + }, + "path": { + "default": "/*", + "description": "kubernetes.io/ingress.class: nginx\nkubernetes.io/tls-acme: \"true\"", + "type": "string" + }, + "tls": { + "default": [], + "description": "- podinfo.local", + "type": "array" + } + }, + "type": "object" + }, + "linkerd": { + "properties": { + "profile": { + "properties": { + "enabled": { + "default": false, + "type": "boolean" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "logLevel": { + "default": "info", + "type": "string" + }, + "nodeSelector": { + "type": "object" + }, + "podAnnotations": { + "type": "object" + }, + "redis": { + "description": "Redis deployment", + "properties": { + "enabled": { + "default": false, + "type": "boolean" + }, + "repository": { + "default": "redis", + "type": "string" + }, + "tag": { + "default": "6.0.8", + "type": "string" + } + }, + "type": "object" + }, + "replicaCount": { + "default": 1, + "type": "integer" + }, + "resources": { + "properties": { + "limits": { + "nullable": true + }, + "requests": { + "properties": { + "cpu": { + "default": "1m", + "type": "string" + }, + "memory": { + "default": "16Mi", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "service": { + "properties": { + "enabled": { + "default": true, + "type": "boolean" + }, + "externalPort": { + "default": 9898, + "type": "integer" + }, + "grpcPort": { + "default": 9999, + "type": "integer" + }, + "grpcService": { + "default": "podinfo", + "type": "string" + }, + "hostPort": { + "description": "the port used to bind the http port to the host\nNOTE: requires privileged container with NET_BIND_SERVICE capability -- this is useful for testing\nin local clusters such as kind without port forwarding", + "nullable": true + }, + "httpPort": { + "default": 9898, + "type": "integer" + }, + "metricsPort": { + "default": 9797, + "type": "integer" + }, + "nodePort": { + "default": 31198, + "type": "integer" + }, + "type": { + "default": "ClusterIP", + "type": "string" + } + }, + "type": "object" + }, + "serviceAccount": { + "properties": { + "enabled": { + "default": false, + "description": "Specifies whether a service account should be created", + "type": "boolean" + }, + "name": { + "description": "The name of the service account to use.\nIf not set and create is true, a name is generated using the fullname template", + "nullable": true + } + }, + "type": "object" + }, + "serviceMonitor": { + "properties": { + "enabled": { + "default": false, + "type": "boolean" + }, + "interval": { + "default": "15s", + "type": "string" + } + }, + "type": "object" + }, + "tls": { + "description": "enable tls on the podinfo service", + "properties": { + "certPath": { + "default": "/data/cert", + "description": "the path where the certificate key pair will be mounted", + "type": "string" + }, + "enabled": { + "default": false, + "type": "boolean" + }, + "hostPort": { + "description": "the port used to bind the tls port to the host\nNOTE: requires privileged container with NET_BIND_SERVICE capability -- this is useful for testing\nin local clusters such as kind without port forwarding", + "nullable": true + }, + "port": { + "default": 9899, + "description": "the port used to host the tls endpoint on the service", + "type": "integer" + }, + "secretName": { + "description": "the name of the secret used to mount the certificate key pair", + "nullable": true + } + }, + "type": "object" + }, + "tolerations": { + "default": [], + "type": "array" + }, + "ui": { + "properties": { + "color": { + "default": "#34577c", + "type": "string" + }, + "logo": { + "default": "", + "type": "string" + }, + "message": { + "default": "", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" +} diff --git a/pkg/appfile/helm/testdata/values.schema.json b/pkg/appfile/helm/testdata/values.schema.json index ac637b138..ba717ad13 100644 --- a/pkg/appfile/helm/testdata/values.schema.json +++ b/pkg/appfile/helm/testdata/values.schema.json @@ -140,17 +140,32 @@ "type": "boolean" }, "hosts": { - "default": [], - "type": "array" - }, - "path": { - "default": "/*", "description": "kubernetes.io/ingress.class: nginx\nkubernetes.io/tls-acme: \"true\"", - "type": "string" + "items": { + "properties": { + "host": { + "default": "chart-example.local", + "type": "string" + }, + "paths": { + "items": { + "properties": { + "path": { + "default": "/", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + } + }, + "type": "object" + }, + "type": "array" }, "tls": { "default": [], - "description": "- podinfo.local", "type": "array" } }, diff --git a/pkg/appfile/helm/testdata/values.yaml b/pkg/appfile/helm/testdata/values.yaml index 42ae5057c..1be28d8cd 100644 --- a/pkg/appfile/helm/testdata/values.yaml +++ b/pkg/appfile/helm/testdata/values.yaml @@ -104,9 +104,10 @@ ingress: annotations: {} # kubernetes.io/ingress.class: nginx # kubernetes.io/tls-acme: "true" - path: /* - hosts: [] -# - podinfo.local + hosts: + - host: chart-example.local + paths: + - path: / tls: [] # - secretName: chart-example-tls # hosts: