docs: rework machine config documentation generation
Generate a structured table of contents following the structure of the config. Make high-level examples follow the full structure of the config. Document new multi-doc machine config. Fixes #8023 Signed-off-by: Andrey Smirnov <andrey.smirnov@siderolabs.com>
This commit is contained in:
parent
e128d3c827
commit
46121c9fec
@ -969,7 +969,7 @@ ARG TARGETOS
|
||||
ARG TARGETARCH
|
||||
WORKDIR /src
|
||||
COPY --from=talosctl-targetarch /talosctl-${TARGETOS}-${TARGETARCH} /bin/talosctl
|
||||
RUN env HOME=/home/user TAG=latest /bin/talosctl docs --config /tmp \
|
||||
RUN env HOME=/home/user TAG=latest /bin/talosctl docs --config /tmp/configuration \
|
||||
&& env HOME=/home/user TAG=latest /bin/talosctl docs --cli /tmp
|
||||
COPY ./pkg/machinery/config/types/v1alpha1/schemas/ /tmp/schemas/
|
||||
|
||||
@ -998,7 +998,7 @@ RUN protoc \
|
||||
/protos/time/*.proto
|
||||
|
||||
FROM scratch AS docs
|
||||
COPY --from=docs-build /tmp/configuration.md /website/content/v1.6/reference/
|
||||
COPY --from=docs-build /tmp/configuration/ /website/content/v1.6/reference/configuration/
|
||||
COPY --from=docs-build /tmp/cli.md /website/content/v1.6/reference/
|
||||
COPY --from=docs-build /tmp/schemas /website/content/v1.6/schemas/
|
||||
COPY --from=proto-docs-build /tmp/api.md /website/content/v1.6/reference/
|
||||
|
@ -16,19 +16,32 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/cobra/doc"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/encoder"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/types/network"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/types/runtime"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/types/siderolink"
|
||||
v1alpha1 "github.com/siderolabs/talos/pkg/machinery/config/types/v1alpha1"
|
||||
)
|
||||
|
||||
func frontmatter(title, description string) string {
|
||||
frontmatter := "---\n"
|
||||
var buf bytes.Buffer
|
||||
|
||||
frontmatter += "title: " + title + "\n"
|
||||
frontmatter += "desription: " + description + "\n"
|
||||
buf.WriteString("---\n")
|
||||
|
||||
frontmatter += "---\n\n"
|
||||
if err := yaml.NewEncoder(&buf).Encode(map[string]string{
|
||||
"title": title,
|
||||
"description": description,
|
||||
}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return frontmatter + "<!-- markdownlint-disable -->\n\n"
|
||||
buf.WriteString("---\n")
|
||||
buf.WriteString("\n")
|
||||
buf.WriteString("<!-- markdownlint-disable -->\n\n")
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func linkHandler(name string) string {
|
||||
@ -39,10 +52,7 @@ func linkHandler(name string) string {
|
||||
return "#" + strings.ToLower(base)
|
||||
}
|
||||
|
||||
const (
|
||||
cliDescription = "Talosctl CLI tool reference."
|
||||
configurationDescription = "Talos node configuration file reference."
|
||||
)
|
||||
const cliDescription = "Talosctl CLI tool reference."
|
||||
|
||||
var (
|
||||
cliDocs bool
|
||||
@ -90,8 +100,36 @@ var docsCmd = &cobra.Command{
|
||||
}
|
||||
|
||||
if configDocs || all {
|
||||
if err := v1alpha1.GetConfigurationDoc().Write(dir, frontmatter("Configuration", configurationDescription)); err != nil {
|
||||
return fmt.Errorf("failed to generate docs: %w", err)
|
||||
for _, pkg := range []struct {
|
||||
name string
|
||||
fileDoc *encoder.FileDoc
|
||||
}{
|
||||
{
|
||||
name: "network",
|
||||
fileDoc: network.GetFileDoc(),
|
||||
},
|
||||
{
|
||||
name: "runtime",
|
||||
fileDoc: runtime.GetFileDoc(),
|
||||
},
|
||||
{
|
||||
name: "siderolink",
|
||||
fileDoc: siderolink.GetFileDoc(),
|
||||
},
|
||||
{
|
||||
name: "v1alpha1",
|
||||
fileDoc: v1alpha1.GetFileDoc(),
|
||||
},
|
||||
} {
|
||||
path := filepath.Join(dir, pkg.name)
|
||||
|
||||
if err := os.MkdirAll(path, 0o777); err != nil {
|
||||
return fmt.Errorf("failed to create output directory %q", path)
|
||||
}
|
||||
|
||||
if err := pkg.fileDoc.Write(path, frontmatter); err != nil {
|
||||
return fmt.Errorf("failed to generate docs: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ func ingressRuleWithinCluster(cidrs []netip.Prefix, gateways []netip.Addr) []net
|
||||
rules = append(rules,
|
||||
network.IngressRule{
|
||||
Subnet: cidrs[i],
|
||||
Except: netip.PrefixFrom(gateways[i], gateways[i].BitLen()),
|
||||
Except: network.Prefix{Prefix: netip.PrefixFrom(gateways[i], gateways[i].BitLen())},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"log"
|
||||
"maps"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
@ -39,7 +40,7 @@ import (
|
||||
{{ range $struct := .Structs -}}
|
||||
func ({{ $struct.Name }}) Doc() *encoder.Doc {
|
||||
doc := &encoder.Doc{
|
||||
Type : "{{ $struct.Name }}",
|
||||
Type : "{{ if $struct.Text.Alias }}{{ $struct.Text.Alias}}{{ else }}{{ $struct.Name }}{{ end }}",
|
||||
Comments: [3]string{ "" /* encoder.HeadComment */, "{{ $struct.Text.Comment }}" /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
Description: "{{ $struct.Text.Description }}",
|
||||
{{ if $struct.AppearsIn -}}
|
||||
@ -100,8 +101,8 @@ func ({{ $struct.Name }}) Doc() *encoder.Doc {
|
||||
}
|
||||
{{ end -}}
|
||||
|
||||
// Get{{ .Name }}Doc returns documentation for the file {{ .File }}.
|
||||
func Get{{ .Name }}Doc() *encoder.FileDoc {
|
||||
// GetFileDoc returns documentation for the file {{ .File }}.
|
||||
func GetFileDoc() *encoder.FileDoc {
|
||||
return &encoder.FileDoc{
|
||||
Name: "{{ .Name }}",
|
||||
Description: "{{ .Header }}",
|
||||
@ -153,6 +154,7 @@ type Text struct {
|
||||
Comment string `json:"-"`
|
||||
Description string `json:"description"`
|
||||
Examples []*Example `json:"examples"`
|
||||
Alias string `json:"alias"`
|
||||
Values []string `json:"values"`
|
||||
Schema *SchemaWrapper `json:"schema"`
|
||||
}
|
||||
@ -346,6 +348,8 @@ func collectFields(s *structType, aliases map[string]aliasType) (fields []*Field
|
||||
for _, f := range s.node.Fields.List {
|
||||
if f.Names == nil {
|
||||
// This is an embedded struct.
|
||||
fields = append(fields, &Field{Type: "unknown"})
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
@ -433,34 +437,52 @@ func render(doc *Doc, dest string) {
|
||||
}
|
||||
}
|
||||
|
||||
func processFile(inputFile, outputFile, schemaOutputFile, versionTagFile, typeName string) {
|
||||
abs, err := in(inputFile)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
func processFile(inputFiles []string, outputFile, schemaOutputFile, versionTagFile string) {
|
||||
var (
|
||||
packageName string
|
||||
packageDoc string
|
||||
structs []*structType
|
||||
)
|
||||
|
||||
aliases := map[string]aliasType{}
|
||||
|
||||
for _, inputFile := range inputFiles {
|
||||
abs, err := in(inputFile)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Printf("creating package file set: %q\n", abs)
|
||||
|
||||
fset := token.NewFileSet()
|
||||
|
||||
node, err := parser.ParseFile(fset, abs, nil, parser.ParseComments)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
packageName = node.Name.Name
|
||||
|
||||
if node.Doc != nil && node.Doc.Text() != "" {
|
||||
packageDoc = node.Doc.Text()
|
||||
}
|
||||
|
||||
tokenFile := fset.File(node.Pos())
|
||||
if tokenFile == nil {
|
||||
log.Fatalf("No token")
|
||||
}
|
||||
|
||||
fmt.Printf("parsing file in package %q: %s\n", packageName, tokenFile.Name())
|
||||
|
||||
fileStructs, fileAliases := collectStructs(node)
|
||||
|
||||
structs = append(structs, fileStructs...)
|
||||
|
||||
maps.Copy(aliases, fileAliases)
|
||||
}
|
||||
|
||||
fmt.Printf("creating package file set: %q\n", abs)
|
||||
|
||||
fset := token.NewFileSet()
|
||||
|
||||
node, err := parser.ParseFile(fset, abs, nil, parser.ParseComments)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
packageName := node.Name.Name
|
||||
|
||||
tokenFile := fset.File(node.Pos())
|
||||
if tokenFile == nil {
|
||||
log.Fatalf("No token")
|
||||
}
|
||||
|
||||
fmt.Printf("parsing file in package %q: %s\n", packageName, tokenFile.Name())
|
||||
|
||||
structs, aliases := collectStructs(node)
|
||||
|
||||
if len(structs) == 0 {
|
||||
log.Fatalf("failed to find types that could be documented in %s", abs)
|
||||
log.Fatalf("failed to find types that could be documented in %v", inputFiles)
|
||||
}
|
||||
|
||||
doc := &Doc{
|
||||
@ -501,6 +523,11 @@ func processFile(inputFile, outputFile, schemaOutputFile, versionTagFile, typeNa
|
||||
}
|
||||
|
||||
for _, s := range doc.Structs {
|
||||
if s.Text.Alias != "" {
|
||||
s.Text.Description = strings.ReplaceAll(s.Text.Description, s.Name, s.Text.Alias)
|
||||
s.Text.Comment = strings.ReplaceAll(s.Text.Comment, s.Name, s.Text.Alias)
|
||||
}
|
||||
|
||||
if extra, ok := extraExamples[s.Name]; ok {
|
||||
s.Text.Examples = append(s.Text.Examples, extra...)
|
||||
}
|
||||
@ -510,14 +537,9 @@ func processFile(inputFile, outputFile, schemaOutputFile, versionTagFile, typeNa
|
||||
}
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
doc.Package = node.Name.Name
|
||||
doc.Name = typeName
|
||||
|
||||
if node.Doc != nil {
|
||||
doc.Header = escape(node.Doc.Text())
|
||||
}
|
||||
}
|
||||
doc.Package = packageName
|
||||
doc.Name = doc.Package
|
||||
doc.Header = escape(packageDoc)
|
||||
|
||||
doc.File = outputFile
|
||||
render(doc, outputFile)
|
||||
@ -528,17 +550,14 @@ func processFile(inputFile, outputFile, schemaOutputFile, versionTagFile, typeNa
|
||||
}
|
||||
|
||||
func main() {
|
||||
outputFile := flag.String("output", "doc.go", "output file name")
|
||||
jsonSchemaOutputFile := flag.String("json-schema-output", "", "output file name for json schema")
|
||||
versionTagFile := flag.String("version-tag-file", "", "file name for version tag")
|
||||
flag.Parse()
|
||||
|
||||
if flag.NArg() != 3 && flag.NArg() != 5 {
|
||||
log.Fatalf("unexpected number of args: %d", flag.NArg())
|
||||
if flag.NArg() == 0 {
|
||||
log.Fatalf("no input files")
|
||||
}
|
||||
|
||||
inputFile := flag.Arg(0)
|
||||
outputFile := flag.Arg(1)
|
||||
typeName := flag.Arg(2)
|
||||
jsonSchemaOutputFile := flag.Arg(3)
|
||||
versionTagFile := flag.Arg(4)
|
||||
|
||||
processFile(inputFile, outputFile, jsonSchemaOutputFile, versionTagFile, typeName)
|
||||
processFile(flag.Args(), *outputFile, *jsonSchemaOutputFile, *versionTagFile)
|
||||
}
|
||||
|
@ -15,6 +15,5 @@ func TestProcessFile(t *testing.T) {
|
||||
outputFile := filepath.Join(t.TempDir(), "out.go")
|
||||
schemaOutputFile := filepath.Join(t.TempDir(), "out.schema.json")
|
||||
versionTagFile := filepath.Join("..", "..", "pkg", "machinery", "gendata", "data", "tag")
|
||||
typeName := "Configuration"
|
||||
processFile(inputFile, outputFile, schemaOutputFile, versionTagFile, typeName)
|
||||
processFile([]string{inputFile}, outputFile, schemaOutputFile, versionTagFile)
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ func (suite *NfTablesChainConfigTestSuite) injectConfig(block bool) {
|
||||
kubeletIngressCfg.Ingress = []networkcfg.IngressRule{
|
||||
{
|
||||
Subnet: netip.MustParsePrefix("10.0.0.0/8"),
|
||||
Except: netip.MustParsePrefix("10.3.0.0/16"),
|
||||
Except: networkcfg.Prefix{Prefix: netip.MustParsePrefix("10.3.0.0/16")},
|
||||
},
|
||||
{
|
||||
Subnet: netip.MustParsePrefix("192.168.0.0/16"),
|
||||
|
@ -6,51 +6,19 @@ package encoder
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"slices"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
var markdownTemplate = `
|
||||
{{ .Description }}
|
||||
{{- $anchors := .Anchors -}}
|
||||
{{- $tick := "` + "`" + `" -}}
|
||||
{{ range $struct := .Structs }}
|
||||
---
|
||||
## {{ $struct.Type }}
|
||||
{{ if $struct.Description -}}
|
||||
{{ $struct.Description }}
|
||||
{{ end }}
|
||||
{{ if $struct.AppearsIn -}}
|
||||
Appears in:
|
||||
|
||||
{{ range $appearance := $struct.AppearsIn -}}
|
||||
- <code>{{ encodeType $appearance.TypeName }}.{{ $appearance.FieldName }}</code>
|
||||
{{ end -}}
|
||||
{{ end }}
|
||||
|
||||
{{ range $example := $struct.Examples }}
|
||||
{{ yaml $example.GetValue "" }}
|
||||
{{ end }}
|
||||
|
||||
{{ if $struct.Fields -}}
|
||||
| Field | Type | Description | Value(s) |
|
||||
|-------|------|-------------|----------|
|
||||
{{ range $field := $struct.Fields -}}
|
||||
{{ if $field.Name -}}
|
||||
| {{- $tick }}{{ $field.Name }}{{ $tick }} |
|
||||
{{- encodeType $field.Type }} |
|
||||
{{- fmtDesc $field.Description }} {{ with $field.Examples }}<details><summary>Show example(s)</summary>{{ range . }}{{ yaml .GetValue $field.Name }}{{ end }}</details>{{ end }} |
|
||||
{{- range $value := $field.Values }}{{ $tick }}{{ $value }}{{ $tick }}<br />{{ end }} |
|
||||
{{ end -}}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}`
|
||||
//go:embed "markdown.tmpl"
|
||||
var markdownTemplate string
|
||||
|
||||
// FileDoc represents a single go file documentation.
|
||||
type FileDoc struct {
|
||||
@ -60,31 +28,33 @@ type FileDoc struct {
|
||||
Description string
|
||||
// Structs structs defined in the file.
|
||||
Structs []*Doc
|
||||
Anchors map[string]string
|
||||
|
||||
t *template.Template
|
||||
// Types is map of all non-trivial types defined in the file.
|
||||
Types map[string]*Doc
|
||||
}
|
||||
|
||||
// Encode encodes file documentation as MD file.
|
||||
func (fd *FileDoc) Encode() ([]byte, error) {
|
||||
anchors := map[string]string{}
|
||||
for _, t := range fd.Structs {
|
||||
anchors[t.Type] = strings.ToLower(t.Type)
|
||||
}
|
||||
|
||||
fd.Anchors = anchors
|
||||
|
||||
fd.t = template.Must(template.New("file_markdown.tpl").
|
||||
func (fd *FileDoc) Encode(root *Doc, frontmatter func(title, description string) string) ([]byte, error) {
|
||||
t := template.Must(template.New("markdown.tmpl").
|
||||
Funcs(template.FuncMap{
|
||||
"yaml": encodeYaml,
|
||||
"fmtDesc": formatDescription,
|
||||
"encodeType": fd.encodeType,
|
||||
"yaml": encodeYaml,
|
||||
"fmtDesc": formatDescription,
|
||||
"dict": tmplDict,
|
||||
"repeat": strings.Repeat,
|
||||
"trimPrefix": strings.TrimPrefix,
|
||||
"add": func(a, b int) int { return a + b },
|
||||
"frontmatter": frontmatter,
|
||||
}).
|
||||
Parse(markdownTemplate))
|
||||
|
||||
buf := bytes.Buffer{}
|
||||
var buf bytes.Buffer
|
||||
|
||||
if err := fd.t.Execute(&buf, fd); err != nil {
|
||||
if err := t.Execute(&buf, struct {
|
||||
Root *Doc
|
||||
Types map[string]*Doc
|
||||
}{
|
||||
Root: root,
|
||||
Types: fd.Types,
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -92,54 +62,85 @@ func (fd *FileDoc) Encode() ([]byte, error) {
|
||||
}
|
||||
|
||||
// Write dumps documentation string to folder.
|
||||
func (fd *FileDoc) Write(path, frontmatter string) error {
|
||||
data, err := fd.Encode()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if stat, e := os.Stat(path); !os.IsNotExist(e) {
|
||||
//
|
||||
//nolint:gocyclo
|
||||
func (fd *FileDoc) Write(path string, frontmatter func(title, description string) string) error {
|
||||
if stat, err := os.Stat(path); !os.IsNotExist(err) {
|
||||
if !stat.IsDir() {
|
||||
return fmt.Errorf("destination path should be a directory")
|
||||
}
|
||||
} else {
|
||||
if e := os.MkdirAll(path, 0o777); e != nil {
|
||||
return e
|
||||
if err := os.MkdirAll(path, 0o777); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
f, err := os.Create(filepath.Join(path, fmt.Sprintf("%s.%s", strings.ToLower(fd.Name), "md")))
|
||||
if err != nil {
|
||||
// generate _index.md
|
||||
if err := os.WriteFile(filepath.Join(path, "_index.md"), []byte(frontmatter(fd.Name, fd.Description)), 0o666); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := f.WriteString(frontmatter); err != nil {
|
||||
return err
|
||||
// find map of all types
|
||||
fd.Types = map[string]*Doc{}
|
||||
|
||||
for _, t := range fd.Structs {
|
||||
if t.Type == "" || strings.ToLower(t.Type) == t.Type {
|
||||
continue
|
||||
}
|
||||
|
||||
fd.Types[t.Type] = t
|
||||
}
|
||||
|
||||
if _, err := f.Write(data); err != nil {
|
||||
return err
|
||||
// find root nodes
|
||||
var roots []*Doc
|
||||
|
||||
for _, t := range fd.Structs {
|
||||
if len(t.AppearsIn) == 0 {
|
||||
roots = append(roots, t)
|
||||
}
|
||||
}
|
||||
|
||||
for _, root := range roots {
|
||||
contents, err := fd.Encode(root, frontmatter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := os.WriteFile(filepath.Join(path, fmt.Sprintf("%s.%s", strings.ToLower(root.Type), "md")), contents, 0o666); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fd *FileDoc) encodeType(t string) string {
|
||||
re := regexp.MustCompile(`\w+`)
|
||||
//nolint:gocyclo
|
||||
func encodeYaml(in any, path string) string {
|
||||
if path != "" {
|
||||
parts := strings.Split(path, ".")
|
||||
|
||||
for _, s := range re.FindAllString(t, -1) {
|
||||
if anchor, ok := fd.Anchors[s]; ok {
|
||||
t = strings.ReplaceAll(t, s, formatLink(s, "#"+anchor))
|
||||
parts = parts[1:] // strip first segment, it's root element
|
||||
|
||||
// if the last element is ""/"-", it means we're at the root of the slice, so we don't need to wrap it once again
|
||||
if len(parts) > 0 && (parts[len(parts)-1] == "" || parts[len(parts)-1] == "-") {
|
||||
parts = parts[:len(parts)-1]
|
||||
}
|
||||
}
|
||||
|
||||
return t
|
||||
}
|
||||
slices.Reverse(parts)
|
||||
|
||||
func encodeYaml(in interface{}, name string) string {
|
||||
if name != "" {
|
||||
in = map[string]interface{}{
|
||||
name: in,
|
||||
for _, part := range parts {
|
||||
switch part {
|
||||
case "":
|
||||
in = []any{in}
|
||||
case "-":
|
||||
in = map[string]any{
|
||||
"example.com": in,
|
||||
}
|
||||
default:
|
||||
in = map[string]any{
|
||||
part: in,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -161,10 +162,6 @@ func encodeYaml(in interface{}, name string) string {
|
||||
return fmt.Sprintf("{{< highlight yaml >}}\n%s{{< /highlight >}}", strings.Join(lines, "\n"))
|
||||
}
|
||||
|
||||
func formatLink(text, link string) string {
|
||||
return fmt.Sprintf(`<a href="%s">%s</a>`, link, text)
|
||||
}
|
||||
|
||||
func formatDescription(description string) string {
|
||||
lines := strings.Split(description, "\n")
|
||||
if len(lines) <= 1 {
|
||||
@ -173,3 +170,22 @@ func formatDescription(description string) string {
|
||||
|
||||
return fmt.Sprintf("<details><summary>%s</summary>%s</details>", lines[0], strings.Join(lines[1:], "<br />"))
|
||||
}
|
||||
|
||||
func tmplDict(vals ...any) (map[string]any, error) {
|
||||
if len(vals)%2 != 0 {
|
||||
return nil, fmt.Errorf("invalid number of arguments: %d", len(vals))
|
||||
}
|
||||
|
||||
res := map[string]any{}
|
||||
|
||||
for i := 0; i < len(vals); i += 2 {
|
||||
key, ok := vals[i].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid key type: %T", vals[i])
|
||||
}
|
||||
|
||||
res[key] = vals[i+1]
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
59
pkg/machinery/config/encoder/markdown.tmpl
Normal file
59
pkg/machinery/config/encoder/markdown.tmpl
Normal file
@ -0,0 +1,59 @@
|
||||
{{ frontmatter .Root.Type .Root.Description }}
|
||||
|
||||
{{ block "struct" dict "Struct" .Root "Level" 1 "Name" .Root.Type "Path" .Root.Type "Types" .Types }}
|
||||
{{ if gt .Level 1 }}{{ repeat "#" .Level }} {{ .Name }} {#{{ .Path }}}{{ end }}
|
||||
|
||||
{{ if and .Struct.Description (gt .Level 1) -}}
|
||||
{{ .Struct.Description }}
|
||||
{{ end }}
|
||||
|
||||
{{ range $example := .Struct.Examples }}
|
||||
{{ yaml $example.GetValue $.Path }}
|
||||
{{ end }}
|
||||
|
||||
{{ if .Struct.Fields -}}
|
||||
| Field | Type | Description | Value(s) |
|
||||
|-------|------|-------------|----------|
|
||||
{{ range $field := $.Struct.Fields -}}
|
||||
{{ if $field.Name -}}
|
||||
|`{{ $field.Name }}` |
|
||||
{{- $type := index $.Types $field.Type -}}
|
||||
{{- if $type -}}
|
||||
<a href="#{{ $.Path }}.{{ $field.Name }}">{{ $field.Type }}</a>
|
||||
{{- else -}}
|
||||
{{- $type := index $.Types (trimPrefix $field.Type "[]") -}}
|
||||
{{- if $type -}}
|
||||
<a href="#{{ $.Path }}.{{ $field.Name }}.">{{ $field.Type }}</a>
|
||||
{{- else -}}
|
||||
{{- $type := index $.Types (trimPrefix $field.Type "map[string]") -}}
|
||||
{{- if $type -}}
|
||||
<a href="#{{ $.Path }}.{{ $field.Name }}.-">{{ $field.Type }}</a>
|
||||
{{- else -}}
|
||||
{{ $field.Type }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end }} |
|
||||
{{- fmtDesc $field.Description }} {{ with $field.Examples }}<details><summary>Show example(s)</summary>{{ range . }}{{ yaml .GetValue (printf ".%s" $field.Name) }}{{ end }}</details>{{ end }} |
|
||||
{{- range $value := $field.Values }}`{{ $value }}`<br />{{ end }} |
|
||||
{{ end -}}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{ range $field := .Struct.Fields }}
|
||||
{{- $struct := index $.Types $field.Type -}}
|
||||
{{- if $struct -}}
|
||||
{{ template "struct" dict "Struct" $struct "Level" (add $.Level 1) "Name" $field.Name "Types" $.Types "Path" (printf "%s.%s" $.Path $field.Name) }}
|
||||
{{- else -}}
|
||||
{{- $struct := index $.Types (trimPrefix $field.Type "[]") -}}
|
||||
{{- if $struct -}}
|
||||
{{ template "struct" dict "Struct" $struct "Level" (add $.Level 1) "Name" (printf "%s[]" $field.Name) "Types" $.Types "Path" (printf "%s.%s." $.Path $field.Name) }}
|
||||
{{- else -}}
|
||||
{{- $struct := index $.Types (trimPrefix $field.Type "map[string]") -}}
|
||||
{{- if $struct -}}
|
||||
{{ template "struct" dict "Struct" $struct "Level" (add $.Level 1) "Name" (printf "%s.*" $field.Name) "Types" $.Types "Path" (printf "%s.%s.-" $.Path $field.Name) }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{ end }}
|
||||
|
||||
{{ end }}
|
@ -31,10 +31,18 @@ var (
|
||||
_ config.NetworkRuleConfigSignal = &DefaultActionConfigV1Alpha1{}
|
||||
)
|
||||
|
||||
// DefaultActionConfigV1Alpha1 is a event sink config document.
|
||||
// DefaultActionConfigV1Alpha1 is a ingress firewall default action configuration document.
|
||||
//
|
||||
// examples:
|
||||
// - value: exampleDefaultActionConfigV1Alpha1()
|
||||
// alias: NetworkDefaultActionConfig
|
||||
type DefaultActionConfigV1Alpha1 struct {
|
||||
meta.Meta `yaml:",inline"`
|
||||
|
||||
// description: |
|
||||
// Default action for all not explicitly configured ingress traffic: accept or block.
|
||||
// values:
|
||||
// - "accept"
|
||||
// - "block"
|
||||
Ingress nethelpers.DefaultAction `yaml:"ingress"`
|
||||
}
|
||||
|
||||
@ -48,6 +56,13 @@ func NewDefaultActionConfigV1Alpha1() *DefaultActionConfigV1Alpha1 {
|
||||
}
|
||||
}
|
||||
|
||||
func exampleDefaultActionConfigV1Alpha1() *DefaultActionConfigV1Alpha1 {
|
||||
cfg := NewDefaultActionConfigV1Alpha1()
|
||||
cfg.Ingress = nethelpers.DefaultActionAccept
|
||||
|
||||
return cfg
|
||||
}
|
||||
|
||||
// Clone implements config.Document interface.
|
||||
func (s *DefaultActionConfigV1Alpha1) Clone() config.Document {
|
||||
return s.DeepCopy()
|
||||
|
@ -27,7 +27,7 @@ func TestDefaultActionConfigMarshalStability(t *testing.T) {
|
||||
cfg := network.NewDefaultActionConfigV1Alpha1()
|
||||
cfg.Ingress = nethelpers.DefaultActionBlock
|
||||
|
||||
marshaled, err := encoder.NewEncoder(cfg).Encode()
|
||||
marshaled, err := encoder.NewEncoder(cfg, encoder.WithComments(encoder.CommentsDisabled)).Encode()
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Log(string(marshaled))
|
||||
|
@ -2,7 +2,9 @@
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// Package network provides Talos network config documents.
|
||||
// Package network provides network machine configuration documents.
|
||||
package network
|
||||
|
||||
//go:generate docgen -output network_doc.go network.go default_action_config.go port_range.go rule_config.go
|
||||
|
||||
//go:generate deep-copy -type DefaultActionConfigV1Alpha1 -type RuleConfigV1Alpha1 -pointer-receiver -header-file ../../../../../hack/boilerplate.txt -o deep_copy.generated.go .
|
||||
|
165
pkg/machinery/config/types/network/network_doc.go
Normal file
165
pkg/machinery/config/types/network/network_doc.go
Normal file
@ -0,0 +1,165 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// Code generated by hack/docgen tool. DO NOT EDIT.
|
||||
|
||||
package network
|
||||
|
||||
import (
|
||||
"net/netip"
|
||||
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/encoder"
|
||||
)
|
||||
|
||||
func (DefaultActionConfigV1Alpha1) Doc() *encoder.Doc {
|
||||
doc := &encoder.Doc{
|
||||
Type: "NetworkDefaultActionConfig",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "NetworkDefaultActionConfig is a ingress firewall default action configuration document." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
Description: "NetworkDefaultActionConfig is a ingress firewall default action configuration document.",
|
||||
Fields: []encoder.Doc{
|
||||
{}, {
|
||||
Name: "ingress",
|
||||
Type: "DefaultAction",
|
||||
Note: "",
|
||||
Description: "Default action for all not explicitly configured ingress traffic: accept or block.",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "Default action for all not explicitly configured ingress traffic: accept or block." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
Values: []string{
|
||||
"accept",
|
||||
"block",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
doc.AddExample("", exampleDefaultActionConfigV1Alpha1())
|
||||
|
||||
return doc
|
||||
}
|
||||
|
||||
func (RuleConfigV1Alpha1) Doc() *encoder.Doc {
|
||||
doc := &encoder.Doc{
|
||||
Type: "NetworkRuleConfig",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "NetworkRuleConfig is a network firewall rule config document." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
Description: "NetworkRuleConfig is a network firewall rule config document.",
|
||||
Fields: []encoder.Doc{
|
||||
{},
|
||||
{
|
||||
Name: "name",
|
||||
Type: "string",
|
||||
Note: "",
|
||||
Description: "Name of the config document.",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "Name of the config document." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
},
|
||||
{
|
||||
Name: "portSelector",
|
||||
Type: "RulePortSelector",
|
||||
Note: "",
|
||||
Description: "Port selector defines which ports and protocols on the host are affected by the rule.",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "Port selector defines which ports and protocols on the host are affected by the rule." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
},
|
||||
{
|
||||
Name: "ingress",
|
||||
Type: "[]IngressRule",
|
||||
Note: "",
|
||||
Description: "Ingress defines which source subnets are allowed to access the host ports/protocols defined by the `portSelector`.",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "Ingress defines which source subnets are allowed to access the host ports/protocols defined by the `portSelector`." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
doc.AddExample("", exampleRuleConfigV1Alpha1())
|
||||
|
||||
return doc
|
||||
}
|
||||
|
||||
func (RulePortSelector) Doc() *encoder.Doc {
|
||||
doc := &encoder.Doc{
|
||||
Type: "RulePortSelector",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "RulePortSelector is a port selector for the network rule." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
Description: "RulePortSelector is a port selector for the network rule.",
|
||||
AppearsIn: []encoder.Appearance{
|
||||
{
|
||||
TypeName: "RuleConfigV1Alpha1",
|
||||
FieldName: "portSelector",
|
||||
},
|
||||
},
|
||||
Fields: []encoder.Doc{
|
||||
{
|
||||
Name: "ports",
|
||||
Type: "PortRanges",
|
||||
Note: "",
|
||||
Description: "Ports defines a list of port ranges or single ports.\nThe port ranges are inclusive, and should not overlap.",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "Ports defines a list of port ranges or single ports." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
},
|
||||
{
|
||||
Name: "protocol",
|
||||
Type: "Protocol",
|
||||
Note: "",
|
||||
Description: "Protocol defines traffic protocol (e.g. TCP or UDP).",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "Protocol defines traffic protocol (e.g. TCP or UDP)." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
Values: []string{
|
||||
"tcp",
|
||||
"udp",
|
||||
"icmp",
|
||||
"icmpv6",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
doc.Fields[0].AddExample("", examplePortRanges1())
|
||||
doc.Fields[0].AddExample("", examplePortRanges2())
|
||||
|
||||
return doc
|
||||
}
|
||||
|
||||
func (IngressRule) Doc() *encoder.Doc {
|
||||
doc := &encoder.Doc{
|
||||
Type: "IngressRule",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "IngressRule is a ingress rule." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
Description: "IngressRule is a ingress rule.",
|
||||
AppearsIn: []encoder.Appearance{
|
||||
{
|
||||
TypeName: "RuleConfigV1Alpha1",
|
||||
FieldName: "ingress",
|
||||
},
|
||||
},
|
||||
Fields: []encoder.Doc{
|
||||
{
|
||||
Name: "subnet",
|
||||
Type: "Prefix",
|
||||
Note: "",
|
||||
Description: "Subnet defines a source subnet.",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "Subnet defines a source subnet." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
},
|
||||
{
|
||||
Name: "except",
|
||||
Type: "Prefix",
|
||||
Note: "",
|
||||
Description: "Except defines a source subnet to exclude from the rule, it gets excluded from the `subnet`.",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "Except defines a source subnet to exclude from the rule, it gets excluded from the `subnet`." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
doc.Fields[0].AddExample("", netip.MustParsePrefix("10.3.4.0/24"))
|
||||
doc.Fields[0].AddExample("", netip.MustParsePrefix("2001:db8::/32"))
|
||||
doc.Fields[0].AddExample("", netip.MustParsePrefix("1.3.4.5/32"))
|
||||
|
||||
return doc
|
||||
}
|
||||
|
||||
// GetFileDoc returns documentation for the file network_doc.go.
|
||||
func GetFileDoc() *encoder.FileDoc {
|
||||
return &encoder.FileDoc{
|
||||
Name: "network",
|
||||
Description: "Package network provides network machine configuration documents.\n",
|
||||
Structs: []*encoder.Doc{
|
||||
DefaultActionConfigV1Alpha1{}.Doc(),
|
||||
RuleConfigV1Alpha1{}.Doc(),
|
||||
RulePortSelector{}.Doc(),
|
||||
IngressRule{}.Doc(),
|
||||
},
|
||||
}
|
||||
}
|
@ -2,7 +2,6 @@
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// Package network provides Talos network config documents.
|
||||
package network
|
||||
|
||||
import (
|
||||
@ -14,6 +13,8 @@ import (
|
||||
)
|
||||
|
||||
// PortRange is a port range.
|
||||
//
|
||||
//docgen:nodoc
|
||||
type PortRange struct {
|
||||
Lo uint16
|
||||
Hi uint16
|
||||
@ -71,6 +72,8 @@ func (pr PortRange) String() string {
|
||||
}
|
||||
|
||||
// PortRanges is a slice of port ranges.
|
||||
//
|
||||
//docgen:nodoc
|
||||
type PortRanges []PortRange
|
||||
|
||||
// Validate the port ranges.
|
||||
@ -100,3 +103,17 @@ func (prs PortRanges) Validate() error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func examplePortRanges1() PortRanges {
|
||||
return PortRanges{
|
||||
{Lo: 80, Hi: 80},
|
||||
{Lo: 443, Hi: 443},
|
||||
}
|
||||
}
|
||||
|
||||
func examplePortRanges2() PortRanges {
|
||||
return PortRanges{
|
||||
{Lo: 1200, Hi: 1299},
|
||||
{Lo: 8080, Hi: 8080},
|
||||
}
|
||||
}
|
||||
|
@ -41,27 +41,78 @@ var (
|
||||
)
|
||||
|
||||
// RuleConfigV1Alpha1 is a network firewall rule config document.
|
||||
//
|
||||
// examples:
|
||||
// - value: exampleRuleConfigV1Alpha1()
|
||||
// alias: NetworkRuleConfig
|
||||
type RuleConfigV1Alpha1 struct {
|
||||
meta.Meta `yaml:",inline"`
|
||||
MetaName string `yaml:"name"`
|
||||
|
||||
// description: |
|
||||
// Name of the config document.
|
||||
MetaName string `yaml:"name"`
|
||||
// description: |
|
||||
// Port selector defines which ports and protocols on the host are affected by the rule.
|
||||
PortSelector RulePortSelector `yaml:"portSelector"`
|
||||
Ingress IngressConfig `yaml:"ingress"`
|
||||
// description: |
|
||||
// Ingress defines which source subnets are allowed to access the host ports/protocols defined by the `portSelector`.
|
||||
Ingress IngressConfig `yaml:"ingress"`
|
||||
}
|
||||
|
||||
// RulePortSelector is a port selector for the network rule.
|
||||
type RulePortSelector struct {
|
||||
Ports PortRanges `yaml:"ports"`
|
||||
// description: |
|
||||
// Ports defines a list of port ranges or single ports.
|
||||
// The port ranges are inclusive, and should not overlap.
|
||||
// examples:
|
||||
// - value: >
|
||||
// examplePortRanges1()
|
||||
// - value: >
|
||||
// examplePortRanges2()
|
||||
Ports PortRanges `yaml:"ports"`
|
||||
// description: |
|
||||
// Protocol defines traffic protocol (e.g. TCP or UDP).
|
||||
// values:
|
||||
// - "tcp"
|
||||
// - "udp"
|
||||
// - "icmp"
|
||||
// - "icmpv6"
|
||||
Protocol nethelpers.Protocol `yaml:"protocol"`
|
||||
}
|
||||
|
||||
// IngressConfig is a ingress config.
|
||||
//
|
||||
//docgen:alias
|
||||
type IngressConfig []IngressRule
|
||||
|
||||
// IngressRule is a ingress rule.
|
||||
type IngressRule struct {
|
||||
// description: |
|
||||
// Subnet defines a source subnet.
|
||||
// examples:
|
||||
// - value: >
|
||||
// netip.MustParsePrefix("10.3.4.0/24")
|
||||
// - value: >
|
||||
// netip.MustParsePrefix("2001:db8::/32")
|
||||
// - value: >
|
||||
// netip.MustParsePrefix("1.3.4.5/32")
|
||||
Subnet netip.Prefix `yaml:"subnet"`
|
||||
Except netip.Prefix `yaml:"except,omitempty"`
|
||||
// description: |
|
||||
// Except defines a source subnet to exclude from the rule, it gets excluded from the `subnet`.
|
||||
Except Prefix `yaml:"except,omitempty"`
|
||||
}
|
||||
|
||||
// Prefix is a wrapper for netip.Prefix.
|
||||
//
|
||||
// It implements IsZero() so that yaml.Marshal correctly skips empty values.
|
||||
//
|
||||
//docgen:nodoc
|
||||
type Prefix struct {
|
||||
netip.Prefix
|
||||
}
|
||||
|
||||
// IsZero implements yaml.IsZeroer interface.
|
||||
func (n Prefix) IsZero() bool {
|
||||
return n.Prefix == netip.Prefix{}
|
||||
}
|
||||
|
||||
// NewRuleConfigV1Alpha1 creates a new RuleConfig config document.
|
||||
@ -74,6 +125,22 @@ func NewRuleConfigV1Alpha1() *RuleConfigV1Alpha1 {
|
||||
}
|
||||
}
|
||||
|
||||
func exampleRuleConfigV1Alpha1() *RuleConfigV1Alpha1 {
|
||||
cfg := NewRuleConfigV1Alpha1()
|
||||
cfg.MetaName = "ingress-apid"
|
||||
cfg.PortSelector.Protocol = nethelpers.ProtocolTCP
|
||||
cfg.PortSelector.Ports = PortRanges{
|
||||
{Lo: 50000, Hi: 50000},
|
||||
}
|
||||
cfg.Ingress = IngressConfig{
|
||||
{
|
||||
Subnet: netip.MustParsePrefix("192.168.0.0/16"),
|
||||
},
|
||||
}
|
||||
|
||||
return cfg
|
||||
}
|
||||
|
||||
// Name implements config.NamedDocument interface.
|
||||
func (s *RuleConfigV1Alpha1) Name() string {
|
||||
return s.MetaName
|
||||
@ -148,7 +215,7 @@ func (s *RuleConfigV1Alpha1) ExceptSubnets() []netip.Prefix {
|
||||
},
|
||||
),
|
||||
func(rule IngressRule) netip.Prefix {
|
||||
return rule.Except
|
||||
return rule.Except.Prefix
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -39,14 +39,14 @@ func TestRuleConfigMarshalStability(t *testing.T) {
|
||||
cfg.Ingress = network.IngressConfig{
|
||||
{
|
||||
Subnet: netip.MustParsePrefix("192.168.0.0/16"),
|
||||
Except: netip.MustParsePrefix("192.168.0.3/32"),
|
||||
Except: network.Prefix{netip.MustParsePrefix("192.168.0.3/32")},
|
||||
},
|
||||
{
|
||||
Subnet: netip.MustParsePrefix("2001::/16"),
|
||||
},
|
||||
}
|
||||
|
||||
marshaled, err := encoder.NewEncoder(cfg).Encode()
|
||||
marshaled, err := encoder.NewEncoder(cfg, encoder.WithComments(encoder.CommentsDisabled)).Encode()
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Log(string(marshaled))
|
||||
@ -79,7 +79,7 @@ func TestRuleConfigUnmarshal(t *testing.T) {
|
||||
Ingress: network.IngressConfig{
|
||||
{
|
||||
Subnet: netip.MustParsePrefix("192.168.0.0/16"),
|
||||
Except: netip.MustParsePrefix("192.168.0.3/32"),
|
||||
Except: network.Prefix{netip.MustParsePrefix("192.168.0.3/32")},
|
||||
},
|
||||
{
|
||||
Subnet: netip.MustParsePrefix("2001::/16"),
|
||||
@ -159,7 +159,7 @@ func TestRuleConfigValidate(t *testing.T) {
|
||||
cfg.Ingress = network.IngressConfig{
|
||||
{
|
||||
Subnet: netip.MustParsePrefix("192.168.0.0/16"),
|
||||
Except: netip.MustParsePrefix("192.168.3.0/24"),
|
||||
Except: network.Prefix{netip.MustParsePrefix("192.168.3.0/24")},
|
||||
},
|
||||
{
|
||||
Subnet: netip.MustParsePrefix("2001::/16"),
|
||||
|
@ -38,9 +38,18 @@ var (
|
||||
)
|
||||
|
||||
// EventSinkV1Alpha1 is a event sink config document.
|
||||
//
|
||||
// examples:
|
||||
// - value: exampleEventSinkV1Alpha1()
|
||||
// alias: EventSinkConfig
|
||||
type EventSinkV1Alpha1 struct {
|
||||
meta.Meta `yaml:",inline"`
|
||||
Endpoint string `yaml:"endpoint"`
|
||||
// description: |
|
||||
// The endpoint for the event sink as 'host:port'.
|
||||
// examples:
|
||||
// - value: >
|
||||
// "10.3.7.3:2810"
|
||||
Endpoint string `yaml:"endpoint"`
|
||||
}
|
||||
|
||||
// NewEventSinkV1Alpha1 creates a new eventsink config document.
|
||||
@ -53,6 +62,13 @@ func NewEventSinkV1Alpha1() *EventSinkV1Alpha1 {
|
||||
}
|
||||
}
|
||||
|
||||
func exampleEventSinkV1Alpha1() *EventSinkV1Alpha1 {
|
||||
cfg := NewEventSinkV1Alpha1()
|
||||
cfg.Endpoint = "192.168.10.3:3247"
|
||||
|
||||
return cfg
|
||||
}
|
||||
|
||||
// Clone implements config.Document interface.
|
||||
func (s *EventSinkV1Alpha1) Clone() config.Document {
|
||||
return s.DeepCopy()
|
||||
|
@ -22,7 +22,7 @@ func TestEventSinkMarshalStability(t *testing.T) {
|
||||
cfg := runtime.NewEventSinkV1Alpha1()
|
||||
cfg.Endpoint = "10.0.0.1:3333"
|
||||
|
||||
marshaled, err := encoder.NewEncoder(cfg).Encode()
|
||||
marshaled, err := encoder.NewEncoder(cfg, encoder.WithComments(encoder.CommentsDisabled)).Encode()
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Log(string(marshaled))
|
||||
|
@ -8,6 +8,8 @@ import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
"github.com/siderolabs/gen/ensure"
|
||||
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/config"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/internal/registry"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/types/meta"
|
||||
@ -36,9 +38,23 @@ var (
|
||||
)
|
||||
|
||||
// KmsgLogV1Alpha1 is a event sink config document.
|
||||
//
|
||||
// examples:
|
||||
// - value: exampleKmsgLogV1Alpha1()
|
||||
// alias: KmsgLogConfig
|
||||
type KmsgLogV1Alpha1 struct {
|
||||
meta.Meta `yaml:",inline"`
|
||||
MetaName string `yaml:"name"`
|
||||
meta.Meta `yaml:",inline"`
|
||||
// description: |
|
||||
// Name of the config document.
|
||||
MetaName string `yaml:"name"`
|
||||
// description: |
|
||||
// The URL encodes the log destination.
|
||||
// The scheme must be tcp:// or udp://.
|
||||
// The path must be empty.
|
||||
// The port is required.
|
||||
// examples:
|
||||
// - value: >
|
||||
// "udp://10.3.7.3:2810"
|
||||
KmsgLogURL meta.URL `yaml:"url"`
|
||||
}
|
||||
|
||||
@ -52,6 +68,14 @@ func NewKmsgLogV1Alpha1() *KmsgLogV1Alpha1 {
|
||||
}
|
||||
}
|
||||
|
||||
func exampleKmsgLogV1Alpha1() *KmsgLogV1Alpha1 {
|
||||
cfg := NewKmsgLogV1Alpha1()
|
||||
cfg.MetaName = "remote-log"
|
||||
cfg.KmsgLogURL.URL = ensure.Value(url.Parse("tcp://192.168.3.7:3478/"))
|
||||
|
||||
return cfg
|
||||
}
|
||||
|
||||
// Name implements config.NamedDocument interface.
|
||||
func (s *KmsgLogV1Alpha1) Name() string {
|
||||
return s.MetaName
|
||||
|
@ -25,7 +25,7 @@ func TestKmsgLogMarshalStability(t *testing.T) {
|
||||
cfg.MetaName = "apiSink"
|
||||
cfg.KmsgLogURL.URL = ensure.Value(url.Parse("https://kmsglog.api/logs"))
|
||||
|
||||
marshaled, err := encoder.NewEncoder(cfg).Encode()
|
||||
marshaled, err := encoder.NewEncoder(cfg, encoder.WithComments(encoder.CommentsDisabled)).Encode()
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Log(string(marshaled))
|
||||
|
@ -2,7 +2,9 @@
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// Package runtime provides Talos runtime config documents.
|
||||
// Package runtime provides runtime machine configuration documents.
|
||||
package runtime
|
||||
|
||||
//go:generate docgen -output runtime_doc.go runtime.go kmsg_log.go event_sink.go
|
||||
|
||||
//go:generate deep-copy -type EventSinkV1Alpha1 -type KmsgLogV1Alpha1 -pointer-receiver -header-file ../../../../../hack/boilerplate.txt -o deep_copy.generated.go .
|
||||
|
77
pkg/machinery/config/types/runtime/runtime_doc.go
Normal file
77
pkg/machinery/config/types/runtime/runtime_doc.go
Normal file
@ -0,0 +1,77 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// Code generated by hack/docgen tool. DO NOT EDIT.
|
||||
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/encoder"
|
||||
)
|
||||
|
||||
func (KmsgLogV1Alpha1) Doc() *encoder.Doc {
|
||||
doc := &encoder.Doc{
|
||||
Type: "KmsgLogConfig",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "KmsgLogConfig is a event sink config document." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
Description: "KmsgLogConfig is a event sink config document.",
|
||||
Fields: []encoder.Doc{
|
||||
{},
|
||||
{
|
||||
Name: "name",
|
||||
Type: "string",
|
||||
Note: "",
|
||||
Description: "Name of the config document.",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "Name of the config document." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
},
|
||||
{
|
||||
Name: "url",
|
||||
Type: "URL",
|
||||
Note: "",
|
||||
Description: "The URL encodes the log destination.\nThe scheme must be tcp:// or udp://.\nThe path must be empty.\nThe port is required.",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "The URL encodes the log destination." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
doc.AddExample("", exampleKmsgLogV1Alpha1())
|
||||
|
||||
doc.Fields[2].AddExample("", "udp://10.3.7.3:2810")
|
||||
|
||||
return doc
|
||||
}
|
||||
|
||||
func (EventSinkV1Alpha1) Doc() *encoder.Doc {
|
||||
doc := &encoder.Doc{
|
||||
Type: "EventSinkConfig",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "EventSinkConfig is a event sink config document." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
Description: "EventSinkConfig is a event sink config document.",
|
||||
Fields: []encoder.Doc{
|
||||
{}, {
|
||||
Name: "endpoint",
|
||||
Type: "string",
|
||||
Note: "",
|
||||
Description: "The endpoint for the event sink as 'host:port'.",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "The endpoint for the event sink as 'host:port'." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
doc.AddExample("", exampleEventSinkV1Alpha1())
|
||||
|
||||
doc.Fields[1].AddExample("", "10.3.7.3:2810")
|
||||
|
||||
return doc
|
||||
}
|
||||
|
||||
// GetFileDoc returns documentation for the file runtime_doc.go.
|
||||
func GetFileDoc() *encoder.FileDoc {
|
||||
return &encoder.FileDoc{
|
||||
Name: "runtime",
|
||||
Description: "Package runtime provides runtime machine configuration documents.\n",
|
||||
Structs: []*encoder.Doc{
|
||||
KmsgLogV1Alpha1{}.Doc(),
|
||||
EventSinkV1Alpha1{}.Doc(),
|
||||
},
|
||||
}
|
||||
}
|
@ -2,19 +2,23 @@
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// Package siderolink provides siderolink config documents.
|
||||
// Package siderolink provides SideroLink machine configuration documents.
|
||||
package siderolink
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
"github.com/siderolabs/gen/ensure"
|
||||
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/config"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/internal/registry"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/types/meta"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/validation"
|
||||
)
|
||||
|
||||
//go:generate docgen -output ./siderolink_doc.go ./siderolink.go
|
||||
|
||||
//go:generate deep-copy -type ConfigV1Alpha1 -pointer-receiver -header-file ../../../../../hack/boilerplate.txt -o deep_copy.generated.go .
|
||||
|
||||
// Kind is a siderolink config document kind.
|
||||
@ -38,9 +42,18 @@ var (
|
||||
_ config.Validator = &ConfigV1Alpha1{}
|
||||
)
|
||||
|
||||
// ConfigV1Alpha1 is a siderolink config document.
|
||||
// ConfigV1Alpha1 is a SideroLink connection machine configuration document.
|
||||
//
|
||||
// examples:
|
||||
// - value: exampleConfigV1Alpha1()
|
||||
// alias: SideroLinkConfig
|
||||
type ConfigV1Alpha1 struct {
|
||||
meta.Meta `yaml:",inline"`
|
||||
meta.Meta `yaml:",inline"`
|
||||
// description: |
|
||||
// SideroLink API URL to connect to.
|
||||
// examples:
|
||||
// - value: >
|
||||
// "https://siderolink.api/join?token=secret"
|
||||
APIUrlConfig meta.URL `yaml:"apiUrl"`
|
||||
}
|
||||
|
||||
@ -54,6 +67,13 @@ func NewConfigV1Alpha1() *ConfigV1Alpha1 {
|
||||
}
|
||||
}
|
||||
|
||||
func exampleConfigV1Alpha1() *ConfigV1Alpha1 {
|
||||
cfg := NewConfigV1Alpha1()
|
||||
cfg.APIUrlConfig.URL = ensure.Value(url.Parse("https://siderolink.api/join?token=secret"))
|
||||
|
||||
return cfg
|
||||
}
|
||||
|
||||
// Clone implements config.Document interface.
|
||||
func (s *ConfigV1Alpha1) Clone() config.Document {
|
||||
return s.DeepCopy()
|
||||
|
45
pkg/machinery/config/types/siderolink/siderolink_doc.go
Normal file
45
pkg/machinery/config/types/siderolink/siderolink_doc.go
Normal file
@ -0,0 +1,45 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// Code generated by hack/docgen tool. DO NOT EDIT.
|
||||
|
||||
package siderolink
|
||||
|
||||
import (
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/encoder"
|
||||
)
|
||||
|
||||
func (ConfigV1Alpha1) Doc() *encoder.Doc {
|
||||
doc := &encoder.Doc{
|
||||
Type: "SideroLinkConfig",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "SideroLinkConfig is a SideroLink connection machine configuration document." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
Description: "SideroLinkConfig is a SideroLink connection machine configuration document.",
|
||||
Fields: []encoder.Doc{
|
||||
{}, {
|
||||
Name: "apiUrl",
|
||||
Type: "URL",
|
||||
Note: "",
|
||||
Description: "SideroLink API URL to connect to.",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "SideroLink API URL to connect to." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
doc.AddExample("", exampleConfigV1Alpha1())
|
||||
|
||||
doc.Fields[1].AddExample("", "https://siderolink.api/join?token=secret")
|
||||
|
||||
return doc
|
||||
}
|
||||
|
||||
// GetFileDoc returns documentation for the file ./siderolink_doc.go.
|
||||
func GetFileDoc() *encoder.FileDoc {
|
||||
return &encoder.FileDoc{
|
||||
Name: "siderolink",
|
||||
Description: "Package siderolink provides SideroLink machine configuration documents.\n",
|
||||
Structs: []*encoder.Doc{
|
||||
ConfigV1Alpha1{}.Doc(),
|
||||
},
|
||||
}
|
||||
}
|
@ -39,7 +39,7 @@ func TestMarshalStability(t *testing.T) {
|
||||
cfg := siderolink.NewConfigV1Alpha1()
|
||||
cfg.APIUrlConfig.URL = ensure.Value(url.Parse("https://siderolink.api/join?jointoken=secret&user=alice"))
|
||||
|
||||
marshaled, err := encoder.NewEncoder(cfg).Encode()
|
||||
marshaled, err := encoder.NewEncoder(cfg, encoder.WithComments(encoder.CommentsDisabled)).Encode()
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, expectedDocument, marshaled)
|
||||
|
@ -701,12 +701,6 @@
|
||||
"markdownDescription": "Enable verbose logging to the console.\nAll system containers logs will flow into serial console.\n\n**Note:** To avoid breaking Talos bootstrap flow enable this option only if serial console can handle high message throughput.",
|
||||
"x-intellij-html-description": "\u003cp\u003eEnable verbose logging to the console.\nAll system containers logs will flow into serial console.\u003c/p\u003e\n\n\u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e To avoid breaking Talos bootstrap flow enable this option only if serial console can handle high message throughput.\u003c/p\u003e\n"
|
||||
},
|
||||
"persist": {
|
||||
"type": "boolean",
|
||||
"title": "persist",
|
||||
"markdownDescription": "",
|
||||
"x-intellij-html-description": ""
|
||||
},
|
||||
"machine": {
|
||||
"$ref": "#/$defs/MachineConfig",
|
||||
"title": "machine",
|
||||
@ -2395,19 +2389,6 @@
|
||||
"additionalProperties": false,
|
||||
"type": "object"
|
||||
},
|
||||
"PodCheckpointer": {
|
||||
"properties": {
|
||||
"image": {
|
||||
"type": "string",
|
||||
"title": "image",
|
||||
"description": "The image field is an override to the default pod-checkpointer image.\n",
|
||||
"markdownDescription": "The `image` field is an override to the default pod-checkpointer image.",
|
||||
"x-intellij-html-description": "\u003cp\u003eThe \u003ccode\u003eimage\u003c/code\u003e field is an override to the default pod-checkpointer image.\u003c/p\u003e\n"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"type": "object"
|
||||
},
|
||||
"ProxyConfig": {
|
||||
"properties": {
|
||||
"disabled": {
|
||||
|
@ -30,12 +30,10 @@ func mustParseURL(uri string) *url.URL {
|
||||
func configExample() any {
|
||||
return struct {
|
||||
Version string `yaml:"version"`
|
||||
Persist bool
|
||||
Machine *yaml.Node
|
||||
Cluster *yaml.Node
|
||||
}{
|
||||
Version: "v1alpha1",
|
||||
Persist: true,
|
||||
Machine: &yaml.Node{Kind: yaml.ScalarNode, LineComment: "..."},
|
||||
Cluster: &yaml.Node{Kind: yaml.ScalarNode, LineComment: "..."},
|
||||
}
|
||||
|
@ -3,17 +3,17 @@
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
/*
|
||||
Package v1alpha1 configuration file contains all the options available for configuring a machine.
|
||||
Package v1alpha1 contains definition of the `v1alpha1` configuration document.
|
||||
|
||||
To generate a set of basic configuration files, run:
|
||||
Even though the machine configuration in Talos Linux is multi-document, at the moment
|
||||
this configuration document contains most of the configuration options.
|
||||
|
||||
talosctl gen config --version v1alpha1 <cluster name> <cluster endpoint>
|
||||
|
||||
This will generate a machine config for each node type, and a talosconfig for the CLI.
|
||||
It is expected that new configuration options will be added as new documents, and existing ones
|
||||
migrated to their own documents.
|
||||
*/
|
||||
package v1alpha1
|
||||
|
||||
//go:generate docgen ./v1alpha1_types.go ./v1alpha1_types_doc.go Configuration ./schemas/v1alpha1_config.schema.json ../../../gendata/data/tag
|
||||
//go:generate docgen -output ./v1alpha1_types_doc.go -json-schema-output ./schemas/v1alpha1_config.schema.json -version-tag-file ../../../gendata/data/tag ./v1alpha1_types.go
|
||||
|
||||
//go:generate deepcopy-gen --input-dirs ../v1alpha1/ --go-header-file ../../../../../hack/boilerplate.txt --bounding-dirs ../v1alpha1 -O zz_generated.deepcopy
|
||||
|
||||
@ -42,7 +42,7 @@ func init() {
|
||||
})
|
||||
}
|
||||
|
||||
// Config defines the v1alpha1 configuration file.
|
||||
// Config defines the v1alpha1.Config Talos machine configuration document.
|
||||
//
|
||||
// examples:
|
||||
// - value: configExample()
|
||||
@ -63,7 +63,9 @@ type Config struct {
|
||||
// - false
|
||||
// - no
|
||||
ConfigDebug *bool `yaml:"debug,omitempty"`
|
||||
//docgen:nodoc
|
||||
// docgen:nodoc
|
||||
//
|
||||
// Deprecated: Not supported anymore.
|
||||
ConfigPersist *bool `yaml:"persist,omitempty"`
|
||||
// description: |
|
||||
// Provides machine specific configuration options.
|
||||
@ -1002,6 +1004,8 @@ type RegistriesConfig struct {
|
||||
}
|
||||
|
||||
// PodCheckpointer represents the pod-checkpointer config values.
|
||||
//
|
||||
//docgen:nodoc
|
||||
type PodCheckpointer struct {
|
||||
// description: |
|
||||
// The `image` field is an override to the default pod-checkpointer image.
|
||||
@ -2181,6 +2185,8 @@ type VolumeMountConfig struct {
|
||||
}
|
||||
|
||||
// ClusterInlineManifests is a list of ClusterInlineManifest.
|
||||
//
|
||||
//docgen:alias
|
||||
type ClusterInlineManifests []ClusterInlineManifest
|
||||
|
||||
// UnmarshalYAML implements yaml.Unmarshaler.
|
||||
|
@ -16,8 +16,8 @@ import (
|
||||
func (Config) Doc() *encoder.Doc {
|
||||
doc := &encoder.Doc{
|
||||
Type: "Config",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "Config defines the v1alpha1 configuration file." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
Description: "Config defines the v1alpha1 configuration file.",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "Config defines the v1alpha1.Config Talos machine configuration document." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
Description: "Config defines the v1alpha1.Config Talos machine configuration document.",
|
||||
Fields: []encoder.Doc{
|
||||
{
|
||||
Name: "version",
|
||||
@ -42,13 +42,7 @@ func (Config) Doc() *encoder.Doc {
|
||||
"no",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "persist",
|
||||
Type: "bool",
|
||||
Note: "",
|
||||
Description: "",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "" /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
},
|
||||
{},
|
||||
{
|
||||
Name: "machine",
|
||||
Type: "MachineConfig",
|
||||
@ -491,7 +485,7 @@ func (ClusterConfig) Doc() *encoder.Doc {
|
||||
},
|
||||
{
|
||||
Name: "inlineManifests",
|
||||
Type: "ClusterInlineManifests",
|
||||
Type: "[]ClusterInlineManifest",
|
||||
Note: "",
|
||||
Description: "A list of inline Kubernetes manifests.\nThese will get automatically deployed as part of the bootstrap.",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "A list of inline Kubernetes manifests." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
@ -1256,25 +1250,6 @@ func (RegistriesConfig) Doc() *encoder.Doc {
|
||||
return doc
|
||||
}
|
||||
|
||||
func (PodCheckpointer) Doc() *encoder.Doc {
|
||||
doc := &encoder.Doc{
|
||||
Type: "PodCheckpointer",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "PodCheckpointer represents the pod-checkpointer config values." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
Description: "PodCheckpointer represents the pod-checkpointer config values.",
|
||||
Fields: []encoder.Doc{
|
||||
{
|
||||
Name: "image",
|
||||
Type: "string",
|
||||
Note: "",
|
||||
Description: "The `image` field is an override to the default pod-checkpointer image.",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "The `image` field is an override to the default pod-checkpointer image." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return doc
|
||||
}
|
||||
|
||||
func (CoreDNS) Doc() *encoder.Doc {
|
||||
doc := &encoder.Doc{
|
||||
Type: "CoreDNS",
|
||||
@ -1324,7 +1299,9 @@ func (Endpoint) Doc() *encoder.Doc {
|
||||
FieldName: "endpoint",
|
||||
},
|
||||
},
|
||||
Fields: []encoder.Doc{},
|
||||
Fields: []encoder.Doc{
|
||||
{},
|
||||
},
|
||||
}
|
||||
|
||||
doc.AddExample("", clusterEndpointExample1())
|
||||
@ -3516,6 +3493,12 @@ func (ClusterInlineManifest) Doc() *encoder.Doc {
|
||||
Type: "ClusterInlineManifest",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "ClusterInlineManifest struct describes inline bootstrap manifests for the user." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
Description: "ClusterInlineManifest struct describes inline bootstrap manifests for the user.",
|
||||
AppearsIn: []encoder.Appearance{
|
||||
{
|
||||
TypeName: "ClusterConfig",
|
||||
FieldName: "inlineManifests",
|
||||
},
|
||||
},
|
||||
Fields: []encoder.Doc{
|
||||
{
|
||||
Name: "name",
|
||||
@ -3534,6 +3517,8 @@ func (ClusterInlineManifest) Doc() *encoder.Doc {
|
||||
},
|
||||
}
|
||||
|
||||
doc.AddExample("", clusterInlineManifestsExample())
|
||||
|
||||
doc.Fields[0].AddExample("", "csi")
|
||||
doc.Fields[1].AddExample("", "/etc/kubernetes/auth")
|
||||
|
||||
@ -3954,11 +3939,11 @@ func (KernelModuleConfig) Doc() *encoder.Doc {
|
||||
return doc
|
||||
}
|
||||
|
||||
// GetConfigurationDoc returns documentation for the file ./v1alpha1_types_doc.go.
|
||||
func GetConfigurationDoc() *encoder.FileDoc {
|
||||
// GetFileDoc returns documentation for the file ./v1alpha1_types_doc.go.
|
||||
func GetFileDoc() *encoder.FileDoc {
|
||||
return &encoder.FileDoc{
|
||||
Name: "Configuration",
|
||||
Description: "Package v1alpha1 configuration file contains all the options available for configuring a machine.\n\nTo generate a set of basic configuration files, run:\n\n talosctl gen config --version v1alpha1 <cluster name> <cluster endpoint>\n\nThis will generate a machine config for each node type, and a talosconfig for the CLI.\n",
|
||||
Name: "v1alpha1",
|
||||
Description: "Package v1alpha1 contains definition of the `v1alpha1` configuration document.\n\nEven though the machine configuration in Talos Linux is multi-document, at the moment\nthis configuration document contains most of the configuration options.\n\nIt is expected that new configuration options will be added as new documents, and existing ones\nmigrated to their own documents.\n",
|
||||
Structs: []*encoder.Doc{
|
||||
Config{}.Doc(),
|
||||
MachineConfig{}.Doc(),
|
||||
@ -3977,7 +3962,6 @@ func GetConfigurationDoc() *encoder.FileDoc {
|
||||
InstallExtensionConfig{}.Doc(),
|
||||
TimeConfig{}.Doc(),
|
||||
RegistriesConfig{}.Doc(),
|
||||
PodCheckpointer{}.Doc(),
|
||||
CoreDNS{}.Doc(),
|
||||
Endpoint{}.Doc(),
|
||||
ControlPlaneConfig{}.Doc(),
|
||||
|
@ -68,6 +68,11 @@ style = "solarized-dark"
|
||||
# Uncomment if you want your chosen highlight style used for code blocks without a specified language
|
||||
# guessSyntax = "true"
|
||||
|
||||
[markup.tableOfContents]
|
||||
endLevel = 6
|
||||
ordered = false
|
||||
startLevel = 2
|
||||
|
||||
# Everything below this are Site Params
|
||||
|
||||
# Comment out if you don't want the "print entire section" link enabled.
|
||||
|
@ -1,6 +1,6 @@
|
||||
---
|
||||
description: Talosctl CLI tool reference.
|
||||
title: CLI
|
||||
desription: Talosctl CLI tool reference.
|
||||
---
|
||||
|
||||
<!-- markdownlint-disable -->
|
||||
|
28
website/content/v1.6/reference/configuration/_index.md
Normal file
28
website/content/v1.6/reference/configuration/_index.md
Normal file
@ -0,0 +1,28 @@
|
||||
---
|
||||
title: Configuration
|
||||
description: Talos Linux machine configuration reference.
|
||||
---
|
||||
|
||||
Talos Linux machine is fully configured via a single YAML file called *machine configuration*.
|
||||
|
||||
The file might contain one or more configuration documents separated by `---` (three dashes) lines.
|
||||
At the moment, majority of the configuration options are within the [v1alpha1]({{< relref "./v1alpha1" >}}) document, so
|
||||
this is the only mandatory document in the configuration file.
|
||||
|
||||
Configuration documents might be named (contain a `name:` field) or unnamed.
|
||||
Unnamed documents can be supplied to the machine configuration file only once, while named documents can be supplied multiple times with unique names.
|
||||
|
||||
The `v1alpha1` document has its own (legacy) structure, while every other document has the following set of fields:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1alpha1 # version of the document
|
||||
kind: NetworkRuleConfig # type of document
|
||||
name: rule1 # only for named documents
|
||||
```
|
||||
|
||||
This section contains the configuration reference, to learn more about Talos Linux machine configuration management, please see:
|
||||
|
||||
* [quick guide to configuration generation]({{< relref "../../introduction/getting-started#configure-talos-linux" >}})
|
||||
* [configuration management in production]({{< relref "../../introduction/prodnotes#configure-talos" >}})
|
||||
* [configuration patches]({{< relref "../../talos-guides/configuration/patching" >}})
|
||||
* [editing live machine configuration]({{< relref "../../talos-guides/configuration/editing-machine-configuration" >}})
|
@ -0,0 +1,8 @@
|
||||
---
|
||||
description: |
|
||||
Package network provides network machine configuration documents.
|
||||
title: network
|
||||
---
|
||||
|
||||
<!-- markdownlint-disable -->
|
||||
|
@ -0,0 +1,31 @@
|
||||
---
|
||||
description: NetworkDefaultActionConfig is a ingress firewall default action configuration document.
|
||||
title: NetworkDefaultActionConfig
|
||||
---
|
||||
|
||||
<!-- markdownlint-disable -->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{{< highlight yaml >}}
|
||||
apiVersion: v1alpha1
|
||||
kind: NetworkDefaultActionConfig
|
||||
ingress: accept # Default action for all not explicitly configured ingress traffic: accept or block.
|
||||
{{< /highlight >}}
|
||||
|
||||
|
||||
| Field | Type | Description | Value(s) |
|
||||
|-------|------|-------------|----------|
|
||||
|`ingress` |DefaultAction |Default action for all not explicitly configured ingress traffic: accept or block. |`accept`<br />`block`<br /> |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,90 @@
|
||||
---
|
||||
description: NetworkRuleConfig is a network firewall rule config document.
|
||||
title: NetworkRuleConfig
|
||||
---
|
||||
|
||||
<!-- markdownlint-disable -->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{{< highlight yaml >}}
|
||||
apiVersion: v1alpha1
|
||||
kind: NetworkRuleConfig
|
||||
name: ingress-apid # Name of the config document.
|
||||
# Port selector defines which ports and protocols on the host are affected by the rule.
|
||||
portSelector:
|
||||
# Ports defines a list of port ranges or single ports.
|
||||
ports:
|
||||
- 50000
|
||||
protocol: tcp # Protocol defines traffic protocol (e.g. TCP or UDP).
|
||||
# Ingress defines which source subnets are allowed to access the host ports/protocols defined by the `portSelector`.
|
||||
ingress:
|
||||
- subnet: 192.168.0.0/16 # Subnet defines a source subnet.
|
||||
{{< /highlight >}}
|
||||
|
||||
|
||||
| Field | Type | Description | Value(s) |
|
||||
|-------|------|-------------|----------|
|
||||
|`name` |string |Name of the config document. | |
|
||||
|`portSelector` |<a href="#NetworkRuleConfig.portSelector">RulePortSelector</a> |Port selector defines which ports and protocols on the host are affected by the rule. | |
|
||||
|`ingress` |<a href="#NetworkRuleConfig.ingress.">[]IngressRule</a> |Ingress defines which source subnets are allowed to access the host ports/protocols defined by the `portSelector`. | |
|
||||
|
||||
|
||||
|
||||
|
||||
## portSelector {#NetworkRuleConfig.portSelector}
|
||||
|
||||
RulePortSelector is a port selector for the network rule.
|
||||
|
||||
|
||||
|
||||
|
||||
| Field | Type | Description | Value(s) |
|
||||
|-------|------|-------------|----------|
|
||||
|`ports` |PortRanges |<details><summary>Ports defines a list of port ranges or single ports.</summary>The port ranges are inclusive, and should not overlap.</details> <details><summary>Show example(s)</summary>{{< highlight yaml >}}
|
||||
ports:
|
||||
- 80
|
||||
- 443
|
||||
{{< /highlight >}}{{< highlight yaml >}}
|
||||
ports:
|
||||
- 1200-1299
|
||||
- 8080
|
||||
{{< /highlight >}}</details> | |
|
||||
|`protocol` |Protocol |Protocol defines traffic protocol (e.g. TCP or UDP). |`tcp`<br />`udp`<br />`icmp`<br />`icmpv6`<br /> |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## ingress[] {#NetworkRuleConfig.ingress.}
|
||||
|
||||
IngressRule is a ingress rule.
|
||||
|
||||
|
||||
|
||||
|
||||
| Field | Type | Description | Value(s) |
|
||||
|-------|------|-------------|----------|
|
||||
|`subnet` |Prefix |Subnet defines a source subnet. <details><summary>Show example(s)</summary>{{< highlight yaml >}}
|
||||
subnet: 10.3.4.0/24
|
||||
{{< /highlight >}}{{< highlight yaml >}}
|
||||
subnet: 2001:db8::/32
|
||||
{{< /highlight >}}{{< highlight yaml >}}
|
||||
subnet: 1.3.4.5/32
|
||||
{{< /highlight >}}</details> | |
|
||||
|`except` |Prefix |Except defines a source subnet to exclude from the rule, it gets excluded from the `subnet`. | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,8 @@
|
||||
---
|
||||
description: |
|
||||
Package runtime provides runtime machine configuration documents.
|
||||
title: runtime
|
||||
---
|
||||
|
||||
<!-- markdownlint-disable -->
|
||||
|
@ -0,0 +1,33 @@
|
||||
---
|
||||
description: EventSinkConfig is a event sink config document.
|
||||
title: EventSinkConfig
|
||||
---
|
||||
|
||||
<!-- markdownlint-disable -->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{{< highlight yaml >}}
|
||||
apiVersion: v1alpha1
|
||||
kind: EventSinkConfig
|
||||
endpoint: 192.168.10.3:3247 # The endpoint for the event sink as 'host:port'.
|
||||
{{< /highlight >}}
|
||||
|
||||
|
||||
| Field | Type | Description | Value(s) |
|
||||
|-------|------|-------------|----------|
|
||||
|`endpoint` |string |The endpoint for the event sink as 'host:port'. <details><summary>Show example(s)</summary>{{< highlight yaml >}}
|
||||
endpoint: 10.3.7.3:2810
|
||||
{{< /highlight >}}</details> | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,35 @@
|
||||
---
|
||||
description: KmsgLogConfig is a event sink config document.
|
||||
title: KmsgLogConfig
|
||||
---
|
||||
|
||||
<!-- markdownlint-disable -->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{{< highlight yaml >}}
|
||||
apiVersion: v1alpha1
|
||||
kind: KmsgLogConfig
|
||||
name: remote-log # Name of the config document.
|
||||
url: tcp://192.168.3.7:3478/ # The URL encodes the log destination.
|
||||
{{< /highlight >}}
|
||||
|
||||
|
||||
| Field | Type | Description | Value(s) |
|
||||
|-------|------|-------------|----------|
|
||||
|`name` |string |Name of the config document. | |
|
||||
|`url` |URL |<details><summary>The URL encodes the log destination.</summary>The scheme must be tcp:// or udp://.<br />The path must be empty.<br />The port is required.</details> <details><summary>Show example(s)</summary>{{< highlight yaml >}}
|
||||
url: udp://10.3.7.3:2810
|
||||
{{< /highlight >}}</details> | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,8 @@
|
||||
---
|
||||
description: |
|
||||
Package siderolink provides SideroLink machine configuration documents.
|
||||
title: siderolink
|
||||
---
|
||||
|
||||
<!-- markdownlint-disable -->
|
||||
|
@ -0,0 +1,33 @@
|
||||
---
|
||||
description: SideroLinkConfig is a SideroLink connection machine configuration document.
|
||||
title: SideroLinkConfig
|
||||
---
|
||||
|
||||
<!-- markdownlint-disable -->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{{< highlight yaml >}}
|
||||
apiVersion: v1alpha1
|
||||
kind: SideroLinkConfig
|
||||
apiUrl: https://siderolink.api/join?token=secret # SideroLink API URL to connect to.
|
||||
{{< /highlight >}}
|
||||
|
||||
|
||||
| Field | Type | Description | Value(s) |
|
||||
|-------|------|-------------|----------|
|
||||
|`apiUrl` |URL |SideroLink API URL to connect to. <details><summary>Show example(s)</summary>{{< highlight yaml >}}
|
||||
apiUrl: https://siderolink.api/join?token=secret
|
||||
{{< /highlight >}}</details> | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,14 @@
|
||||
---
|
||||
description: |
|
||||
Package v1alpha1 contains definition of the `v1alpha1` configuration document.
|
||||
|
||||
Even though the machine configuration in Talos Linux is multi-document, at the moment
|
||||
this configuration document contains most of the configuration options.
|
||||
|
||||
It is expected that new configuration options will be added as new documents, and existing ones
|
||||
migrated to their own documents.
|
||||
title: v1alpha1
|
||||
---
|
||||
|
||||
<!-- markdownlint-disable -->
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -701,12 +701,6 @@
|
||||
"markdownDescription": "Enable verbose logging to the console.\nAll system containers logs will flow into serial console.\n\n**Note:** To avoid breaking Talos bootstrap flow enable this option only if serial console can handle high message throughput.",
|
||||
"x-intellij-html-description": "\u003cp\u003eEnable verbose logging to the console.\nAll system containers logs will flow into serial console.\u003c/p\u003e\n\n\u003cp\u003e\u003cstrong\u003eNote:\u003c/strong\u003e To avoid breaking Talos bootstrap flow enable this option only if serial console can handle high message throughput.\u003c/p\u003e\n"
|
||||
},
|
||||
"persist": {
|
||||
"type": "boolean",
|
||||
"title": "persist",
|
||||
"markdownDescription": "",
|
||||
"x-intellij-html-description": ""
|
||||
},
|
||||
"machine": {
|
||||
"$ref": "#/$defs/MachineConfig",
|
||||
"title": "machine",
|
||||
@ -2395,19 +2389,6 @@
|
||||
"additionalProperties": false,
|
||||
"type": "object"
|
||||
},
|
||||
"PodCheckpointer": {
|
||||
"properties": {
|
||||
"image": {
|
||||
"type": "string",
|
||||
"title": "image",
|
||||
"description": "The image field is an override to the default pod-checkpointer image.\n",
|
||||
"markdownDescription": "The `image` field is an override to the default pod-checkpointer image.",
|
||||
"x-intellij-html-description": "\u003cp\u003eThe \u003ccode\u003eimage\u003c/code\u003e field is an override to the default pod-checkpointer image.\u003c/p\u003e\n"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"type": "object"
|
||||
},
|
||||
"ProxyConfig": {
|
||||
"properties": {
|
||||
"disabled": {
|
||||
|
@ -53,9 +53,11 @@ There are some special rules:
|
||||
|
||||
When patching a multi-document machine configuration, following rules apply:
|
||||
|
||||
- for each document in the patch, the document is merged with the respective document in the machine configuration (matching by `kind`, `apiVersion` and `name` for named documentes)
|
||||
- for each document in the patch, the document is merged with the respective document in the machine configuration (matching by `kind`, `apiVersion` and `name` for named documents)
|
||||
- if the patch document doesn't exist in the machine configuration, it is appended to the machine configuration
|
||||
|
||||
The strategic merge patch itself might be a multi-document YAML, and each document will be applied as a patch to the base machine configuration.
|
||||
|
||||
### RFC6902 (JSON Patches)
|
||||
|
||||
[JSON patches](https://jsonpatch.com/) can be written either in JSON or YAML format.
|
||||
|
@ -9,7 +9,8 @@ Talos Linux Ingress Firewall doesn't affect the traffic between the Kubernetes p
|
||||
|
||||
## Configuration
|
||||
|
||||
Ingress rules are configured as extra documents in the Talos machine configuration:
|
||||
Ingress rules are configured as extra documents [NetwokDefaultActionConfig]({{< relref "../../reference/configuration/network/networkdefaultactionconfig.md" >}}) and
|
||||
[NetworkRuleConfig]({{< relref "../../reference/configuration/network/networkruleconfig.md" >}}) in the Talos machine configuration:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1alpha1
|
||||
|
Loading…
x
Reference in New Issue
Block a user