Skip to content

Commit 909519f

Browse files
authored
Merge pull request #4983 from gofogo/chore-4260
chore(docs): docs/flags.md generation
2 parents a769df6 + 0633349 commit 909519f

File tree

6 files changed

+394
-6
lines changed

6 files changed

+394
-6
lines changed

Makefile

+5
Original file line numberDiff line numberDiff line change
@@ -160,3 +160,8 @@ release.prod: test
160160
.PHONY: ko
161161
ko:
162162
scripts/install-ko.sh
163+
164+
# generate-flags-documentation: Generate documentation (docs/flags.md)
165+
.PHONE: generate-flags-documentation
166+
generate-flags-documentation:
167+
go run internal/gen/docs/flags/main.go

docs/flags.md

+169
Large diffs are not rendered by default.

internal/gen/docs/flags/main.go

+115
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/*
2+
Copyright 2017 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package main
18+
19+
import (
20+
"bytes"
21+
"fmt"
22+
"os"
23+
"strings"
24+
"text/template"
25+
26+
cfg "sigs.k8s.io/external-dns/pkg/apis/externaldns"
27+
)
28+
29+
type Flag struct {
30+
Name string
31+
Description string
32+
}
33+
type Flags []Flag
34+
35+
// AddFlag adds a new flag to the Flags struct
36+
func (f *Flags) addFlag(name, description string) {
37+
*f = append(*f, Flag{Name: name, Description: description})
38+
}
39+
40+
const markdownTemplate = `# Flags
41+
42+
<!-- THIS FILE MUST NOT BE EDITED BY HAND -->
43+
<!-- ON NEW FLAG ADDED PLEASE RUN 'make generate-flags-documentation' -->
44+
45+
| Flag | Description |
46+
| :------ | :----------- |
47+
{{- range . }}
48+
| {{ .Name }} | {{ .Description }} | {{- end -}}
49+
`
50+
51+
// It generates a markdown file
52+
// with the supported flags and writes it to the 'docs/flags.md' file.
53+
// to re-generate `docs/flags.md` execute 'go run internal/gen/main.go'
54+
func main() {
55+
testPath, _ := os.Getwd()
56+
path := fmt.Sprintf("%s/docs/flags.md", testPath)
57+
fmt.Printf("generate file '%s' with supported flags\n", path)
58+
59+
flags := computeFlags()
60+
content, err := flags.generateMarkdownTable()
61+
if err != nil {
62+
_ = fmt.Errorf("failed to generate markdown file '%s': %v\n", path, err.Error())
63+
}
64+
_ = writeToFile(path, content)
65+
}
66+
67+
func computeFlags() Flags {
68+
app := cfg.App(&cfg.Config{})
69+
modelFlags := app.Model().Flags
70+
71+
flags := Flags{}
72+
73+
for _, flag := range modelFlags {
74+
// do not include helpers and completion flags
75+
if strings.Contains(flag.Name, "help") || strings.Contains(flag.Name, "completion-") {
76+
continue
77+
}
78+
flagString := ""
79+
flagName := flag.Name
80+
if flag.IsBoolFlag() {
81+
flagName = "[no-]" + flagName
82+
}
83+
flagString += fmt.Sprintf("--%s", flagName)
84+
85+
if !flag.IsBoolFlag() {
86+
flagString += fmt.Sprintf("=%s", flag.FormatPlaceHolder())
87+
}
88+
flags.addFlag(fmt.Sprintf("`%s`", flagString), flag.HelpWithEnvar())
89+
}
90+
return flags
91+
}
92+
93+
func (f *Flags) generateMarkdownTable() (string, error) {
94+
tmpl := template.Must(template.New("flags.md.tpl").Parse(markdownTemplate))
95+
96+
var b bytes.Buffer
97+
err := tmpl.Execute(&b, f)
98+
if err != nil {
99+
return "", err
100+
}
101+
return b.String(), nil
102+
}
103+
104+
func writeToFile(filename string, content string) error {
105+
file, fileErr := os.Create(filename)
106+
if fileErr != nil {
107+
_ = fmt.Errorf("failed to create file: %v", fileErr)
108+
}
109+
defer file.Close()
110+
_, writeErr := file.WriteString(content)
111+
if writeErr != nil {
112+
_ = fmt.Errorf("failed to write to file: %s", filename)
113+
}
114+
return nil
115+
}

internal/gen/docs/flags/main_test.go

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
Copyright 2017 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package main
18+
19+
import (
20+
"fmt"
21+
"io/fs"
22+
"os"
23+
"strings"
24+
"testing"
25+
26+
"github.com/stretchr/testify/assert"
27+
)
28+
29+
const pathToDocs = "%s/../../../../docs"
30+
31+
func TestComputeFlags(t *testing.T) {
32+
flags := computeFlags()
33+
34+
if len(flags) == 0 {
35+
t.Errorf("Expected non-zero flags, got %d", len(flags))
36+
}
37+
38+
for _, flag := range flags {
39+
if strings.Contains(flag.Name, "help") || strings.Contains(flag.Name, "completion-") {
40+
t.Errorf("Unexpected flag: %s", flag.Name)
41+
}
42+
}
43+
}
44+
45+
func TestGenerateMarkdownTableRenderer(t *testing.T) {
46+
flags := Flags{
47+
{Name: "flag1", Description: "description1"},
48+
}
49+
50+
got, err := flags.generateMarkdownTable()
51+
assert.NoError(t, err)
52+
53+
assert.Contains(t, got, "<!-- THIS FILE MUST NOT BE EDITED BY HAND -->")
54+
assert.Contains(t, got, "| flag1 | description1 |")
55+
}
56+
57+
func TestFlagsMdExists(t *testing.T) {
58+
testPath, _ := os.Getwd()
59+
fsys := os.DirFS(fmt.Sprintf(pathToDocs, testPath))
60+
fileName := "flags.md"
61+
st, err := fs.Stat(fsys, fileName)
62+
assert.NoError(t, err, "expected file %s to exist", fileName)
63+
assert.Equal(t, fileName, st.Name())
64+
}
65+
66+
func TestFlagsMdUpToDate(t *testing.T) {
67+
testPath, _ := os.Getwd()
68+
fsys := os.DirFS(fmt.Sprintf(pathToDocs, testPath))
69+
fileName := "flags.md"
70+
expected, err := fs.ReadFile(fsys, fileName)
71+
assert.NoError(t, err, "expected file %s to exist", fileName)
72+
73+
flags := computeFlags()
74+
actual, err := flags.generateMarkdownTable()
75+
assert.NoError(t, err)
76+
assert.True(t, len(expected) == len(actual), "expected file '%s' to be up to date. execute 'make generate-flags-documentation", fileName)
77+
}
78+
79+
func TestFlagsMdExtraFlagAdded(t *testing.T) {
80+
testPath, _ := os.Getwd()
81+
fsys := os.DirFS(fmt.Sprintf(pathToDocs, testPath))
82+
filePath := "flags.md"
83+
expected, err := fs.ReadFile(fsys, filePath)
84+
assert.NoError(t, err, "expected file %s to exist", filePath)
85+
86+
flags := computeFlags()
87+
flags.addFlag("new-flag", "description2")
88+
actual, err := flags.generateMarkdownTable()
89+
90+
assert.NoError(t, err)
91+
assert.NotEqual(t, string(expected), actual)
92+
}

mkdocs.yml

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ nav:
1212
- Changelog: charts/external-dns/CHANGELOG.md
1313
- About:
1414
- FAQ: docs/faq.md
15+
- Flags: docs/flags.md
1516
- Out of Incubator: docs/20190708-external-dns-incubator.md
1617
- Code of Conduct: code-of-conduct.md
1718
- License: LICENSE.md

pkg/apis/externaldns/types.go

+12-6
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,17 @@ func allLogLevelsAsStrings() []string {
400400

401401
// ParseFlags adds and parses flags from command line
402402
func (cfg *Config) ParseFlags(args []string) error {
403+
app := App(cfg)
404+
405+
_, err := app.Parse(args)
406+
if err != nil {
407+
return err
408+
}
409+
410+
return nil
411+
}
412+
413+
func App(cfg *Config) *kingpin.Application {
403414
app := kingpin.New("external-dns", "ExternalDNS synchronizes exposed Kubernetes Services and Ingresses with DNS providers.\n\nNote that all flags may be replaced with env vars - `--flag` -> `EXTERNAL_DNS_FLAG=1` or `--flag value` -> `EXTERNAL_DNS_FLAG=value`")
404415
app.Version(Version)
405416
app.DefaultEnvars()
@@ -603,10 +614,5 @@ func (cfg *Config) ParseFlags(args []string) error {
603614

604615
app.Flag("webhook-server", "When enabled, runs as a webhook server instead of a controller. (default: false).").BoolVar(&cfg.WebhookServer)
605616

606-
_, err := app.Parse(args)
607-
if err != nil {
608-
return err
609-
}
610-
611-
return nil
617+
return app
612618
}

0 commit comments

Comments
 (0)