Skip to content

Commit 97d6111

Browse files
authored
Merge pull request #938 from DirectXMan12/docs/controller-gen-cli
Add controller-gen CLI options to book
2 parents cc2a4cb + efb4541 commit 97d6111

File tree

5 files changed

+125
-25
lines changed

5 files changed

+125
-25
lines changed

docs/book/src/SUMMARY.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@
6666
- [Object/DeepCopy](./reference/markers/object.md)
6767
- [RBAC](./reference/markers/rbac.md)
6868

69+
- [controller-gen CLI](./reference/controller-gen.md)
70+
6971
---
7072

7173
[Appendix: The TODO Landing Page](./TODO.md)
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# controller-gen CLI
2+
3+
KubeBuilder makes use of a tool called
4+
[controller-gen](https://sigs.k8s.io/controller-tools/cmd/controller-gen)
5+
for generating utility code and Kubernetes YAML. This code and config
6+
generation is controlled by the presence of special ["marker
7+
comments"](/reference/markers.md) in Go code.
8+
9+
controller-gen is built out of different "generators" (which specify what
10+
to generate) and "output rules" (which specify how and where to write the
11+
results).
12+
13+
Both are configured through command line options specified in [marker
14+
format](/reference/markers.md).
15+
16+
For instance,
17+
18+
```shell
19+
controller-gen paths=./... crd:trivialVersions=true rbac:roleName=controller-perms output:crd:artifacts:config=config/crd/bases
20+
```
21+
22+
generates CRDs and RBAC, and specifically stores the generated CRD YAML in
23+
`config/crd/bases`. For the RBAC, it uses the default output rules
24+
(`config/rbac`). It considers every package in the current directory tree
25+
(as per the normal rules of the go `...` wildcard).
26+
27+
## Generators
28+
29+
Each different generator is configured through a CLI option. Multiple
30+
generators may be used in a single invocation of `controller-gen`.
31+
32+
{{#markerdocs CLI: generators}}
33+
34+
## Output Rules
35+
36+
Output rules configure how a given generator outputs its results. There is
37+
always one global "fallback" output rule (specified as `output:<rule>`),
38+
plus per-generator overrides (specified as `output:<generator>:<rule>`).
39+
40+
<aside class="note">
41+
42+
<h1>Default Rules</h1>
43+
44+
When no fallback rule is specified manually, a set of default
45+
per-generator rules are used which result in YAML going to
46+
`config/<generator>`, and code staying where it belongs.
47+
48+
The default rules are equivalent to
49+
`output:<generator>:artifacts:config=config/<generator>` for each
50+
generator.
51+
52+
When a "fallback" rule is specified, that'll be used instead of the
53+
default rules.
54+
55+
For example, if you specify `crd rbac:roleName=controller-perms
56+
output:crd:stdout`, you'll get CRDs on standard out, and rbac in a file in
57+
`config/rbac`. If you were to add in a global rule instead, like `crd
58+
rbac:roleName=controller-perms output:crd:stdout output:none`, you'd get
59+
CRDs to standard out, and everything else to /dev/null, because we've
60+
explicitly specified a fallback.
61+
62+
</aside>
63+
64+
For brevity, the per-generator output rules (`output:<generator>:<rule>`)
65+
are omitted below. They are equivalent to the global fallback options
66+
listed here.
67+
68+
{{#markerdocs CLI: output rules (optionally as output:<generator>:...)}}
69+
70+
## Other Options
71+
72+
{{#markerdocs CLI: generic}}

docs/book/src/reference/markers.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Markers for Config/Code Generation
22

3-
KubeBuilder makes use of a tool called `controller-gen` (from
4-
[controller-tools](https://godoc.org/sigs.k8s.io/controller-tools)) for
3+
KubeBuilder makes use of a tool called
4+
[controller-gen](/reference/controller-gen.md) for
55
generating utility code and Kubernetes YAML. This code and config
66
generation is controlled by the presence of special "marker comments" in
77
Go code.

docs/book/theme/css/general.css

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -219,9 +219,6 @@ blockquote {
219219
.marker dl.args.summary dt::before {
220220
content: ',';
221221
}
222-
.marker dl.args.summary dt:first-of-type:last-of-type::before {
223-
content: '';
224-
}
225222
/* hide in non-summary view */
226223
.marker dd.args {
227224
display: none
@@ -309,25 +306,25 @@ blockquote {
309306
}
310307

311308
/* summary view */
312-
#markers-summarize:checked ~ dl > .marker dd.args {
309+
.markers-summarize:checked ~ dl > .marker dd.args {
313310
display: inline-block
314311
}
315-
#markers-summarize:checked ~ dl > .marker dd.description dl.args {
312+
.markers-summarize:checked ~ dl > .marker dd.description dl.args {
316313
display: none
317314
}
318-
#markers-summarize:checked ~ dl > .marker dd.description {
315+
.markers-summarize:checked ~ dl > .marker dd.description {
319316
margin-bottom: 0.25em;
320317
}
321318

322-
#markers-summarize {
319+
input.markers-summarize {
323320
display: none;
324321
}
325-
label[for="markers-summarize"]::before {
322+
label.markers-summarize::before {
326323
margin-right: 0.5em;
327324
content: '\25bc';
328325
display: inline-block;
329326
}
330-
#markers-summarize:checked ~ label[for="markers-summarize"]::before {
327+
input.markers-summarize:checked ~ label.markers-summarize::before {
331328
content: '\25b6';
332329
}
333330

docs/book/utils/markerdocs/main.go

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,11 @@ func markerTemplate(marker *MarkerDoc) toHTML {
114114
// will be added to locations marked `{{#markerdocs category name}}`.
115115
// This allows us to put additional documentation in each category.
116116
type MarkerDocs struct {
117-
// MarkerCategories contains the generators for which to query controller-tools.
118-
MarkerGenerators []string
117+
// Args contains the arguments to pass to controller-gen to get
118+
// marker help JSON output. Each key is a prefix to apply to
119+
// category names (for disambiguation), and each value is an invocation
120+
// of controller-gen.
121+
Args map[string][]string
119122
}
120123

121124
func (_ MarkerDocs) SupportsOutput(_ string) bool { return true }
@@ -128,6 +131,11 @@ func (p MarkerDocs) Process(input *plugin.Input) error {
128131
// first, find all categories...
129132
markersByCategory := make(map[string][]MarkerDoc)
130133
for _, cat := range markerDocs {
134+
if cat.Category == "" {
135+
// skip un-named categories, which are intended to be hidden
136+
// (e.g. all the per-generate idendical output rules)
137+
continue
138+
}
131139
markersByCategory[cat.Category] = cat.Markers
132140
}
133141

@@ -145,10 +153,15 @@ func (p MarkerDocs) Process(input *plugin.Input) error {
145153
return "", fmt.Errorf("unknown category %q", category)
146154
}
147155

156+
// HTML5 says that any characters are valid in ID except for space,
157+
// but may not be empty (which we prevent by skipping un-named categories):
158+
// https://www.w3.org/TR/html52/dom.html#element-attrdef-global-id
159+
categoryAlias := strings.ReplaceAll(category, " ", "-")
160+
148161
content := new(strings.Builder)
149162

150163
// NB(directxman12): wrap this in a div to prevent the markdown processor from inserting extra paragraphs
151-
fmt.Fprint(content, "<div><input checked type=\"checkbox\" id=\"markers-summarize\"></input><label for=\"markers-summarize\">Show Detailed Argument Help</label><dl class=\"markers\">")
164+
fmt.Fprintf(content, "<div><input checked type=\"checkbox\" class=\"markers-summarize\" id=\"markers-summarize-%[1]s\"></input><label class=\"markers-summarize\" for=\"markers-summarize-%[1]s\">Show Detailed Argument Help</label><dl class=\"markers\">", categoryAlias)
152165

153166
// write the markers
154167
for _, marker := range markers {
@@ -204,25 +217,41 @@ func wrapWithNewlines(src string) string {
204217

205218
// getMarkerDocs fetches marker documentation from controller-gen
206219
func (p MarkerDocs) getMarkerDocs() ([]CategoryDoc, error) {
207-
args := []string{"-wwww"} // wonderful-world-wide-web
208-
args = append(args, p.MarkerGenerators...)
209-
cmd := exec.Command("controller-gen", args...)
210-
outRaw, err := cmd.Output()
211-
if err != nil {
212-
return nil, err
213-
}
214-
215220
var res []CategoryDoc
216-
if err := json.Unmarshal(outRaw, &res); err != nil {
217-
return nil, err
221+
for categoryPrefix, args := range p.Args {
222+
cmd := exec.Command("controller-gen", args...)
223+
outRaw, err := cmd.Output()
224+
if err != nil {
225+
return nil, err
226+
}
227+
228+
var invocationRes []CategoryDoc
229+
if err := json.Unmarshal(outRaw, &invocationRes); err != nil {
230+
return nil, err
231+
}
232+
233+
for i, category := range invocationRes {
234+
// leave empty categories as-is, so that they're skipped
235+
if category.Category == "" {
236+
continue
237+
}
238+
invocationRes[i].Category = categoryPrefix + category.Category
239+
}
240+
241+
res = append(res, invocationRes...)
218242
}
219243

220244
return res, nil
221245
}
222246

223247
func main() {
224248
if err := plugin.Run(MarkerDocs{
225-
MarkerGenerators: []string{"crd", "webhook", "rbac:roleName=cheddar" /* role name doesn't mean anything here */, "object"},
249+
Args: map[string][]string{
250+
// marker args
251+
"": []string{"-wwww", "crd", "webhook", "rbac:roleName=cheddar" /* role name doesn't mean anything here */, "object"},
252+
// cli options args
253+
"CLI: ": []string{"-hhhh"},
254+
},
226255
}, os.Stdin, os.Stdout, os.Args[1:]...); err != nil {
227256
log.Fatal(err.Error())
228257
}

0 commit comments

Comments
 (0)