feat: set markdown and html descriptions in config json schema

Set the additional description fields for vscode/monaco/jetbrains editors.

Strip the markdown formatting from the plain description.

Additionally, fix the description of the field `aescbcEncryptionSecret`.

Related to siderolabs/talos#6705.

Signed-off-by: Utku Ozdemir <utku.ozdemir@siderolabs.com>
This commit is contained in:
Utku Ozdemir 2023-01-23 23:42:54 +01:00
parent f0804027a4
commit 2d136f1879
No known key found for this signature in database
GPG Key ID: 65933E76F0549B0D
8 changed files with 1747 additions and 571 deletions

View File

@ -7,8 +7,10 @@ go 1.19
replace gopkg.in/yaml.v3 => github.com/unix4ever/yaml v0.0.0-20210315173758-8fb30b8e5a5b replace gopkg.in/yaml.v3 => github.com/unix4ever/yaml v0.0.0-20210315173758-8fb30b8e5a5b
require ( require (
github.com/gomarkdown/markdown v0.0.0-20221013030248-663e2500819c
github.com/iancoleman/orderedmap v0.2.0 github.com/iancoleman/orderedmap v0.2.0
github.com/invopop/jsonschema v0.7.0 github.com/invopop/jsonschema v0.7.0
github.com/microcosm-cc/bluemonday v1.0.21
github.com/santhosh-tekuri/jsonschema/v5 v5.1.1 github.com/santhosh-tekuri/jsonschema/v5 v5.1.1
github.com/siderolabs/gen v0.4.3 github.com/siderolabs/gen v0.4.3
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
@ -16,7 +18,10 @@ require (
) )
require ( require (
github.com/aymerick/douceur v0.2.0 // indirect
github.com/google/go-cmp v0.5.8 // indirect github.com/google/go-cmp v0.5.8 // indirect
github.com/gorilla/css v1.0.0 // indirect
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
golang.org/x/net v0.5.0 // indirect
golang.org/x/tools v0.1.12 // indirect golang.org/x/tools v0.1.12 // indirect
) )

View File

@ -1,8 +1,14 @@
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
github.com/gomarkdown/markdown v0.0.0-20221013030248-663e2500819c h1:iyaGYbCmcYK0Ja9a3OUa2Fo+EaN0cbLu0eKpBwPFzc8=
github.com/gomarkdown/markdown v0.0.0-20221013030248-663e2500819c/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA= github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA=
github.com/iancoleman/orderedmap v0.2.0 h1:sq1N/TFpYH++aViPcaKjys3bDClUEU7s5B+z6jq8pNA= github.com/iancoleman/orderedmap v0.2.0 h1:sq1N/TFpYH++aViPcaKjys3bDClUEU7s5B+z6jq8pNA=
github.com/iancoleman/orderedmap v0.2.0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA= github.com/iancoleman/orderedmap v0.2.0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA=
@ -10,6 +16,8 @@ github.com/invopop/jsonschema v0.7.0 h1:2vgQcBz1n256N+FpX3Jq7Y17AjYt46Ig3zIWyy77
github.com/invopop/jsonschema v0.7.0/go.mod h1:O9uiLokuu0+MGFlyiaqtWxwqJm41/+8Nj0lD7A36YH0= github.com/invopop/jsonschema v0.7.0/go.mod h1:O9uiLokuu0+MGFlyiaqtWxwqJm41/+8Nj0lD7A36YH0=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/microcosm-cc/bluemonday v1.0.21 h1:dNH3e4PSyE4vNX+KlRGHT5KrSvjeUkoNPwEORjffHJg=
github.com/microcosm-cc/bluemonday v1.0.21/go.mod h1:ytNkv4RrDrLJ2pqlsSI46O6IVXmZOBBD4SaJyDwwTkM=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
@ -24,7 +32,9 @@ github.com/unix4ever/yaml v0.0.0-20210315173758-8fb30b8e5a5b h1:8pnPjZJU0SYanlmH
github.com/unix4ever/yaml v0.0.0-20210315173758-8fb30b8e5a5b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= github.com/unix4ever/yaml v0.0.0-20210315173758-8fb30b8e5a5b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 h1:v6hYoSR9T5oet+pMXwUWkbiVqx/63mlHjefrHmxwfeY= golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw=
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=

View File

@ -11,8 +11,11 @@ import (
"os" "os"
"strings" "strings"
"github.com/gomarkdown/markdown"
"github.com/gomarkdown/markdown/html"
"github.com/iancoleman/orderedmap" "github.com/iancoleman/orderedmap"
"github.com/invopop/jsonschema" "github.com/invopop/jsonschema"
"github.com/microcosm-cc/bluemonday"
validatejsonschema "github.com/santhosh-tekuri/jsonschema/v5" validatejsonschema "github.com/santhosh-tekuri/jsonschema/v5"
"github.com/siderolabs/gen/slices" "github.com/siderolabs/gen/slices"
) )
@ -132,10 +135,7 @@ func fieldToSchema(field *Field) *jsonschema.Schema {
schema.Title = strings.ReplaceAll(field.Tag, "\\n", "\n") schema.Title = strings.ReplaceAll(field.Tag, "\\n", "\n")
} }
// if no description is provided on the explicit schema, grab it from the comment populateDescriptionFields(field, &schema)
if schema.Description == "" {
schema.Description = normalizeDescription(field.Text.Description)
}
// if an explicit schema was provided, return it // if an explicit schema was provided, return it
if field.Text.Schema != nil { if field.Text.Schema != nil {
@ -172,6 +172,39 @@ func fieldToSchema(field *Field) *jsonschema.Schema {
return &schema return &schema
} }
func populateDescriptionFields(field *Field, schema *jsonschema.Schema) {
if schema.Extras == nil {
schema.Extras = make(map[string]any)
}
markdownDescription := normalizeDescription(field.Text.Description)
htmlFlags := html.CommonFlags | html.HrefTargetBlank
opts := html.RendererOptions{Flags: htmlFlags}
renderer := html.NewRenderer(opts)
htmlDescription := string(markdown.ToHTML([]byte(markdownDescription), nil, renderer))
policy := bluemonday.StrictPolicy()
plaintextDescription := policy.Sanitize(htmlDescription)
// set description
if schema.Description == "" {
schema.Description = plaintextDescription
}
// set markdownDescription for vscode/monaco editor
if schema.Extras["markdownDescription"] == nil {
schema.Extras["markdownDescription"] = markdownDescription
}
// set htmlDescription for Jetbrains IDEs
if schema.Extras["x-intellij-html-description"] == nil {
schema.Extras["x-intellij-html-description"] = htmlDescription
}
}
func structToSchema(st *Struct) *jsonschema.Schema { func structToSchema(st *Struct) *jsonschema.Schema {
schema := jsonschema.Schema{ schema := jsonschema.Schema{
Type: "object", Type: "object",

View File

@ -908,9 +908,9 @@ type ClusterConfig struct {
BootstrapToken string `yaml:"token,omitempty"` BootstrapToken string `yaml:"token,omitempty"`
// description: | // description: |
// A key used for the [encryption of secret data at rest](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/). // A key used for the [encryption of secret data at rest](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/).
// Enables encryption with AESCBC.
// examples: // examples:
// - name: Decryption secret example (do not use in production!). // - name: Decryption secret example (do not use in production!).
// Enables encryption with AESCBC.
// value: '"z01mye6j16bspJYtTB/5SFX8j7Ph4JXxM2Xuu4vsBPM="' // value: '"z01mye6j16bspJYtTB/5SFX8j7Ph4JXxM2Xuu4vsBPM="'
ClusterAESCBCEncryptionSecret string `yaml:"aescbcEncryptionSecret,omitempty"` ClusterAESCBCEncryptionSecret string `yaml:"aescbcEncryptionSecret,omitempty"`
// description: | // description: |

View File

@ -396,8 +396,10 @@ func init() {
ClusterConfigDoc.Fields[6].Name = "aescbcEncryptionSecret" ClusterConfigDoc.Fields[6].Name = "aescbcEncryptionSecret"
ClusterConfigDoc.Fields[6].Type = "string" ClusterConfigDoc.Fields[6].Type = "string"
ClusterConfigDoc.Fields[6].Note = "" ClusterConfigDoc.Fields[6].Note = ""
ClusterConfigDoc.Fields[6].Description = "description: |\n A key used for the [encryption of secret data at rest](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/).\n examples:\n - name: Decryption secret example (do not use in production!).\n Enables encryption with AESCBC.\n value: '\"z01mye6j16bspJYtTB/5SFX8j7Ph4JXxM2Xuu4vsBPM=\"'\n" ClusterConfigDoc.Fields[6].Description = "A key used for the [encryption of secret data at rest](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/).\nEnables encryption with AESCBC."
ClusterConfigDoc.Fields[6].Comments[encoder.LineComment] = "description: |" ClusterConfigDoc.Fields[6].Comments[encoder.LineComment] = "A key used for the [encryption of secret data at rest](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/)."
ClusterConfigDoc.Fields[6].AddExample("Decryption secret example (do not use in production!).", "z01mye6j16bspJYtTB/5SFX8j7Ph4JXxM2Xuu4vsBPM=")
ClusterConfigDoc.Fields[7].Name = "secretboxEncryptionSecret" ClusterConfigDoc.Fields[7].Name = "secretboxEncryptionSecret"
ClusterConfigDoc.Fields[7].Type = "string" ClusterConfigDoc.Fields[7].Type = "string"
ClusterConfigDoc.Fields[7].Note = "" ClusterConfigDoc.Fields[7].Note = ""

View File

@ -489,7 +489,9 @@ network:
|`token` |string |The [bootstrap token](https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/) used to join the cluster. <details><summary>Show example(s)</summary>{{< highlight yaml >}} |`token` |string |The [bootstrap token](https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/) used to join the cluster. <details><summary>Show example(s)</summary>{{< highlight yaml >}}
token: wlzjyw.bei2zfylhs2by0wd token: wlzjyw.bei2zfylhs2by0wd
{{< /highlight >}}</details> | | {{< /highlight >}}</details> | |
|`aescbcEncryptionSecret` |string |<details><summary>description: |</summary> A key used for the [encryption of secret data at rest](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/).<br /> examples:<br /> - name: Decryption secret example (do not use in production!).<br /> Enables encryption with AESCBC.<br /> value: '"z01mye6j16bspJYtTB/5SFX8j7Ph4JXxM2Xuu4vsBPM="'<br /></details> | | |`aescbcEncryptionSecret` |string |<details><summary>A key used for the [encryption of secret data at rest](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/).</summary>Enables encryption with AESCBC.</details> <details><summary>Show example(s)</summary>{{< highlight yaml >}}
aescbcEncryptionSecret: z01mye6j16bspJYtTB/5SFX8j7Ph4JXxM2Xuu4vsBPM=
{{< /highlight >}}</details> | |
|`secretboxEncryptionSecret` |string |<details><summary>A key used for the [encryption of secret data at rest](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/).</summary>Enables encryption with secretbox.<br />Secretbox has precedence over AESCBC.</details> <details><summary>Show example(s)</summary>{{< highlight yaml >}} |`secretboxEncryptionSecret` |string |<details><summary>A key used for the [encryption of secret data at rest](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/).</summary>Enables encryption with secretbox.<br />Secretbox has precedence over AESCBC.</details> <details><summary>Show example(s)</summary>{{< highlight yaml >}}
secretboxEncryptionSecret: z01mye6j16bspJYtTB/5SFX8j7Ph4JXxM2Xuu4vsBPM= secretboxEncryptionSecret: z01mye6j16bspJYtTB/5SFX8j7Ph4JXxM2Xuu4vsBPM=
{{< /highlight >}}</details> | | {{< /highlight >}}</details> | |

File diff suppressed because it is too large Load Diff