英文:
Ensure the type is a list while executing against YAML using text/template package
问题
我正在使用text/template
包来动态构建我的k8s清单,我几乎成功地创建了所需的输出。
由于目标类型是YAML,我希望确保生成的.ownerReferences
和.secrets
的类型在YAML中被创建为列表类型,即每个条目前面有一个-
。
我期望实现的输出是:
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: Foobar
labels:
app: Foobar
ownerReferences:
- uid: 123456789
kind: FoobarOrchestrator
secrets:
- name: thisisasecret1
- name: thisisasecret2
但是,使用下面的代码尝试后:
package main
import (
"os"
"text/template"
)
const serviceAccountTemplate = `---
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{.Name}}
{{- if .Labels}}
labels:
{{- end }}
{{- range $key, $value := .Labels }}
{{ $key }}: {{ $value }}
{{- end }}
{{- if .OwnerRef}}
ownerReferences:
{{- end }}
{{- range .OwnerRef }}
uid: {{ .UID }}
kind: {{ .Kind }}
{{- end }}
{{- if .Secrets}}
secrets:
{{- end }}
{{- range $value := .Secrets }}
name: {{ $value }}
{{- end }}
`
func main() {
type OwnerRef struct {
UID string
Kind string
}
data := struct {
Name string
Secrets []string
Labels map[string]string
OwnerRef []OwnerRef
}{
"dude",
[]string{"thisisasecret1", "thisisasecret2"},
map[string]string{"app": "Foobar"},
[]OwnerRef{OwnerRef{UID: "123456789", Kind: "Foobar"}},
}
t := template.New("t")
t, err := t.Parse(serviceAccountTemplate)
if err != nil {
panic(err)
}
err = t.Execute(os.Stdout, data)
if err != nil {
panic(err)
}
}
我能够生成以下输出:
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: dude
labels:
app: Foobar
ownerReferences:
uid: 123456789
kind: Foobar
secrets:
name: thisisasecret1
name: thisisasecret2
但我想确保类型准确,以便被正确的YAML解码器接受。
同时,我也希望对我现有的模板定义进行任何改进。
Playground链接- https://go.dev/play/p/EbxcvGcYr9r
英文:
I'm using the text/template
package to dynamically construct my k8s manifest and I was almost successful in creating it the required output.
Since the target type is YAML, I want to ensure, the generated type of .ownerReferences
and .secrets
are created as list types in YAML, i.e. with a leading -
on each entry.
The output I'm expecting to achieve is
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: Foobar
labels:
app: Foobar
ownerReferences:
- uid: 123456789
kind: FoobarOrchestrator
secrets:
- name: thisisasecret1
- name: thisisasecret2
But with the attempt I have below
package main
import (
"os"
"text/template"
)
const serviceAccountTemplate = `---
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{.Name}}
{{- if .Labels}}
labels:
{{- end }}
{{- range $key, $value := .Labels }}
{{ $key }}: {{ $value }}
{{- end }}
{{- if .OwnerRef}}
ownerReferences:
{{- end }}
{{- range .OwnerRef }}
uid: {{ .UID }}
kind: {{ .Kind }}
{{- end }}
{{- if .Secrets}}
secrets:
{{- end }}
{{- range $value := .Secrets }}
name: {{ $value }}
{{- end }}
`
func main() {
type OwnerRef struct {
UID string
Kind string
}
data := struct {
Name string
Secrets []string
Labels map[string]string
OwnerRef []OwnerRef
}{
"dude",
[]string{"thisisasecret1", "thisisasecret2"},
map[string]string{"app": "Foobar"},
[]OwnerRef{OwnerRef{UID: "123456789", Kind: "Foobar"}},
}
t := template.New("t")
t, err := t.Parse(serviceAccountTemplate)
if err != nil {
panic(err)
}
err = t.Execute(os.Stdout, data)
if err != nil {
panic(err)
}
}
I was able to produce below
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: dude
labels:
app: Foobar
ownerReferences:
uid: 123456789
kind: Foobar
secrets:
name: thisisasecret1
name: thisisasecret2
but I want to be sure, if the types are accurate to be accepted by a proper YAML decoder.
Also would appreciate any enhancements to my existing template definition.
Playground link - https://go.dev/play/p/EbxcvGcYr9r
答案1
得分: 2
要使示例模板输出所需节点的YAML序列,只需在子节点前面加上-
。例如:
const serviceAccountTemplate = `
...
{{- if .OwnerRef}}
ownerReferences:
{{- end }}
{{- range .OwnerRef }}
- uid: {{ .UID }}
kind: {{ .Kind }}
{{- end }}
{{- if .Secrets}}
secrets:
{{- end }}
{{- range $value := .Secrets }}
- name: {{ $value }}
{{- end }}
`
https://go.dev/play/p/R86Feu5VZOK
然而,text/template
没有支持检查正确的YAML语法。如果您需要确保生成的文本是有效的YAML,您需要编写相应的测试。
但是,就像在Go中生成JSON时通常使用结构体和encoding/json
一样,使用结构体和gopkg.in/yaml.v3
可以生成一致有效的YAML。
英文:
To make the example template output YAML sequences for the desired nodes you can simply prepend -
in front of the child nodes. E.g.
const serviceAccountTemplate = `
...
{{- if .OwnerRef}}
ownerReferences:
{{- end }}
{{- range .OwnerRef }}
- uid: {{ .UID }}
kind: {{ .Kind }}
{{- end }}
{{- if .Secrets}}
secrets:
{{- end }}
{{- range $value := .Secrets }}
- name: {{ $value }}
{{- end }}
`
https://go.dev/play/p/R86Feu5VZOK
There's however no support in text/template
to check for proper YAML syntax. If you need guarantee that the generated text is valid YAML you'll have to write the tests for that.
But, just like when you want to generate JSON in Go you'd normally use structs and encoding/json
, so too with YAML you can use structs and gopkg.in/yaml.v3
to generate consistently valid YAML.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论