Skip to content

Commit d7cb8ae

Browse files
committed
DOC/MEDIUM: annotations: move annotations to separate file
1 parent fdf9db7 commit d7cb8ae

File tree

7 files changed

+2004
-1958
lines changed

7 files changed

+2004
-1958
lines changed

documentation/README.md

Lines changed: 5 additions & 1796 deletions
Large diffs are not rendered by default.

documentation/annotations.md

Lines changed: 1803 additions & 0 deletions
Large diffs are not rendered by default.

documentation/gen/annotations.go

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"sort"
7+
"strings"
8+
9+
"github.com/google/renameio"
10+
)
11+
12+
var header = `
13+
This is autogenerated from [doc.yaml](doc.yaml). Description can be found in [generator readme](gen/README.md)
14+
15+
### Available annotations
16+
17+
> :information_source: Ingress and service annotations can have ` + "`ingress.kubernetes.io`, `haproxy.org` and `haproxy.com`" + ` prefixes
18+
>
19+
> Example: ` + "haproxy.com/ssl-redirect` and `haproxy.org/ssl-redirect`" + ` are same annotation
20+
21+
| Annotation | Type | Default | Dependencies | Config map | Ingress | Service |
22+
| - |:-:|:-:|:-:|:-:|:-:|:-:|
23+
`
24+
25+
var tableFooter = `
26+
> :information_source: Annotations have hierarchy: ` + "`default` <- `Configmap` <- `Ingress` <- `Service`" + `
27+
>
28+
> Service annotations have highest priority. If they are not defined, controller goes one level up until it finds value.
29+
>
30+
> This is useful if we want, for instance, to change default behaviour, but want to keep default for some service. etc.
31+
>
32+
> In general annotations follow the following rules:
33+
> - global annotations can only be used in Configmap
34+
> - ingress annotations can be used in Ingress and ConfigMap (to configure all ingress resources in use)
35+
> - service annotations can be used in Service, Ingress (to configure all services used in Ingress) and ConfigMap (to configure all services in use)
36+
37+
38+
### Options
39+
40+
#### Global Options
41+
42+
Global options are set via ConfigMap ([--configmap](controller.md)) annotations.
43+
Depending on the option, it can be in Global or Default HAProxy section.
44+
45+
`
46+
47+
var docFooter = `
48+
### Secrets
49+
50+
#### tls-secret
51+
52+
- define through pod arguments
53+
- ` + "`--default-ssl-certificate`=\\<namespace\\>/\\<secret\\>" + `
54+
- Annotation ` + "`ssl-certificate` in config map" + `
55+
- \<namespace\>/\<secret\>
56+
- this replaces default certificate
57+
- certificate can be defined in Ingress object: ` + "`spec.tls[].secretName`" + `
58+
- single certificate secret can contain two items:
59+
- tls.key
60+
- tls.crt
61+
- certificate secret with ` + "`rsa` and `ecdsa` certificates:" + `
62+
- :information_source: only one certificate is also acceptable setup
63+
- rsa.key
64+
- rsa.crt
65+
- ecdsa.key
66+
- ecdsa.crt
67+
68+
### Data types
69+
70+
#### Port
71+
72+
- value between <0, 65535]
73+
74+
#### Sample expression
75+
76+
- Sample expressions/fetches are used to retrieve data from request/response buffer.
77+
- Example:
78+
- headers: ` + "`hdr(header-name)`" + `
79+
- cookies: ` + "`cookie(cookie-name)`" + `
80+
- Name of the cipher used to offload SSL: ` + "`ssl_fc_cipher`" + `
81+
- Sample expressions are covered in depth in [HAProxy documentation](https://cbonte.github.io/haproxy-dconv/2.0/configuration.html#7.3), however many are out of the ingress controller's scope.
82+
83+
#### Time
84+
85+
- number + type
86+
- in milliseconds, "s" suffix denotes seconds
87+
- example: "1s"
88+
`
89+
90+
func (c *Conf) generateReadmeAnnotations() {
91+
var buff strings.Builder
92+
buff.WriteString(title)
93+
buff.WriteString(c.ActiveVersion.String())
94+
buff.WriteString(header)
95+
96+
groups := map[string]struct{}{}
97+
for _, ann := range c.Items {
98+
if !ann.VersionMax.LowerOrEqual(c.ActiveVersion) {
99+
continue
100+
}
101+
devVersion := !ann.VersionMin.LowerOrEqual(c.ActiveVersion)
102+
// log.Println(ann.Title, ann.VersionMin, ">", c.ActiveVersion, devVersion)
103+
if ann.Group == "" {
104+
ann.Group = ann.Title
105+
}
106+
annType := ann.Type
107+
if ann.Type == "bool" {
108+
annType = `[bool](#bool)`
109+
}
110+
defaultValue := ann.Default
111+
if annType != "number" && ann.Default != "" {
112+
defaultValue = `"` + ann.Default + `"`
113+
}
114+
dev := ""
115+
if devVersion {
116+
dev = " :construction:(dev)"
117+
}
118+
groupLink := strings.ReplaceAll(ann.Group, " ", "-")
119+
// log.Println(ann.Group, groupLink)
120+
// 3 can be a link to type maybe like for [IPs or CIDRs](#access-control)?
121+
buff.WriteString(fmt.Sprintf("| [%s](#%s)%s | %s | %s | %s |%s|%s|%s|\n",
122+
ann.Title, groupLink, dev, annType, defaultValue, ann.Dependencies,
123+
Contains(ann.AppliesTo, "configmap"), Contains(ann.AppliesTo, "ingress"), Contains(ann.AppliesTo, "service")))
124+
125+
// write group
126+
groups[ann.Group] = struct{}{}
127+
}
128+
129+
buff.WriteString(tableFooter)
130+
131+
sortedGroups := []string{}
132+
for group := range groups {
133+
sortedGroups = append(sortedGroups, group)
134+
}
135+
sort.Strings(sortedGroups)
136+
for _, group := range sortedGroups {
137+
buff.WriteString(fmt.Sprintf("#### %s\n\n", strings.ReplaceAll(strings.Title(group), "-", " ")))
138+
groupData, haveGroupData := c.Groups[group]
139+
if haveGroupData && groupData.Header != "" {
140+
buff.WriteString(fmt.Sprintf("%s\n\n", groupData.Header))
141+
}
142+
for _, ann := range c.Items {
143+
if ann.Group != group {
144+
continue
145+
}
146+
buff.WriteString(fmt.Sprintf("##### `%s`\n\n", ann.Title))
147+
if !ann.VersionMin.LowerOrEqual(c.ActiveVersion) {
148+
buff.WriteString("\n > :construction: this is only available from next version, currently available in dev build\n\n")
149+
}
150+
for _, desc := range ann.Description {
151+
buff.WriteString(fmt.Sprintf(" %s\n", desc))
152+
}
153+
buff.WriteString("\n Available on:")
154+
for _, app := range ann.AppliesTo {
155+
buff.WriteString(fmt.Sprintf(" `%s`", app))
156+
}
157+
buff.WriteString("\n")
158+
for _, tip := range ann.Tip {
159+
buff.WriteString(fmt.Sprintf("\n :information_source: %s\n", tip))
160+
}
161+
buff.WriteString("\nPossible values:\n\n")
162+
for _, value := range ann.Values {
163+
buff.WriteString(fmt.Sprintf("- %s\n", writeValue(value, ann.Default)))
164+
}
165+
buff.WriteString("\n")
166+
selectExamples(ann, &buff)
167+
}
168+
if haveGroupData && groupData.Footer != "" {
169+
buff.WriteString(fmt.Sprintf("%s\n\n", groupData.Footer))
170+
}
171+
buff.WriteString("<p align='right'><a href='#available-annotations'>:arrow_up_small: back to top</a></p>\n\n***\n\n")
172+
}
173+
174+
buff.WriteString(docFooter)
175+
176+
err := renameio.WriteFile("../annotations.md", []byte(buff.String()), 0o644)
177+
if err != nil {
178+
log.Println(err)
179+
}
180+
}

documentation/gen/go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@ module doc-gen
33
go 1.15
44

55
require (
6-
github.com/google/renameio v0.1.0
7-
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776
6+
github.com/google/renameio v1.0.1
7+
gopkg.in/yaml.v3 v3.0.0-20220512140231-539c8e751b99
88
)

documentation/gen/go.sum

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA=
2-
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
1+
github.com/google/renameio v1.0.1 h1:Lh/jXZmvZxb0BBeSY5VKEfidcbcbenKjZFzM/q0fSeU=
2+
github.com/google/renameio v1.0.1/go.mod h1:t/HQoYBZSsWSNK35C6CO/TpPLDVWvxOHboWUAweKUpk=
3+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
34
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
4-
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
5-
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
5+
gopkg.in/yaml.v3 v3.0.0-20220512140231-539c8e751b99 h1:dbuHpmKjkDzSOMKAWl10QNlgaZUd3V1q99xc81tt2Kc=
6+
gopkg.in/yaml.v3 v3.0.0-20220512140231-539c8e751b99/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

documentation/gen/main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ func main() {
55
cn.getConf()
66

77
cn.generateReadme()
8+
cn.generateReadmeAnnotations()
89
cn.generateReadmeController()
910
// cn.saveConf()
1011
// cn.saveDocConf()

documentation/gen/readme.go

Lines changed: 8 additions & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package main
33
import (
44
"fmt"
55
"log"
6-
"sort"
76
"strings"
87

98
"github.com/google/renameio"
@@ -14,173 +13,26 @@ var title = `
1413
1514
## HAProxy kubernetes ingress controller `
1615

17-
var header = `
18-
Options for starting controller can be found in [controller.md](controller.md)
16+
var headerREADME = `
1917
20-
This is autogenerated from [doc.yaml](doc.yaml). Description can be found in [generator readme](gen/README.md)
21-
22-
### Available annotations
23-
24-
> :information_source: Ingress and service annotations can have ` + "`ingress.kubernetes.io`, `haproxy.org` and `haproxy.com`" + ` prefixes
25-
>
26-
> Example: ` + "haproxy.com/ssl-redirect` and `haproxy.org/ssl-redirect`" + ` are same annotation
27-
28-
| Annotation | Type | Default | Dependencies | Config map | Ingress | Service |
29-
| - |:-:|:-:|:-:|:-:|:-:|:-:|
30-
`
31-
32-
var tableFooter = `
33-
> :information_source: Annotations have hierarchy: ` + "`default` <- `Configmap` <- `Ingress` <- `Service`" + `
34-
>
35-
> Service annotations have highest priority. If they are not defined, controller goes one level up until it finds value.
36-
>
37-
> This is useful if we want, for instance, to change default behaviour, but want to keep default for some service. etc.
38-
>
39-
> In general annotations follow the following rules:
40-
> - global annotations can only be used in Configmap
41-
> - ingress annotations can be used in Ingress and ConfigMap (to configure all ingress resources in use)
42-
> - service annotations can be used in Service, Ingress (to configure all services used in Ingress) and ConfigMap (to configure all services in use)
18+
### Documentation
4319
20+
- [Controller options](controller.md)
21+
- [Custom resource definitions](custom-resources.md)
22+
- [Annotations](annotations.md)
4423
45-
### Options
46-
47-
#### Global Options
48-
49-
Global options are set via ConfigMap ([--configmap](controller.md)) annotations.
50-
Depending on the option, it can be in Global or Default HAProxy section.
51-
52-
`
53-
54-
var docFooter = `
55-
### Secrets
5624
57-
#### tls-secret
58-
59-
- define through pod arguments
60-
- ` + "`--default-ssl-certificate`=\\<namespace\\>/\\<secret\\>" + `
61-
- Annotation ` + "`ssl-certificate` in config map" + `
62-
- \<namespace\>/\<secret\>
63-
- this replaces default certificate
64-
- certificate can be defined in Ingress object: ` + "`spec.tls[].secretName`" + `
65-
- single certificate secret can contain two items:
66-
- tls.key
67-
- tls.crt
68-
- certificate secret with ` + "`rsa` and `ecdsa` certificates:" + `
69-
- :information_source: only one certificate is also acceptable setup
70-
- rsa.key
71-
- rsa.crt
72-
- ecdsa.key
73-
- ecdsa.crt
74-
75-
### Data types
76-
77-
#### Port
78-
79-
- value between <0, 65535]
80-
81-
#### Sample expression
82-
83-
- Sample expressions/fetches are used to retrieve data from request/response buffer.
84-
- Example:
85-
- headers: ` + "`hdr(header-name)`" + `
86-
- cookies: ` + "`cookie(cookie-name)`" + `
87-
- Name of the cipher used to offload SSL: ` + "`ssl_fc_cipher`" + `
88-
- Sample expressions are covered in depth in [HAProxy documentation](https://cbonte.github.io/haproxy-dconv/2.0/configuration.html#7.3), however many are out of the ingress controller's scope.
89-
90-
#### Time
25+
This is autogenerated from [doc.yaml](doc.yaml). Description can be found in [generator readme](gen/README.md)
9126
92-
- number + type
93-
- in milliseconds, "s" suffix denotes seconds
94-
- example: "1s"
9527
`
9628

9729
func (c *Conf) generateReadme() {
9830
var buff strings.Builder
9931
buff.WriteString(title)
10032
buff.WriteString(c.ActiveVersion.String())
101-
buff.WriteString(header)
102-
103-
groups := map[string]struct{}{}
104-
for _, ann := range c.Items {
105-
if !ann.VersionMax.LowerOrEqual(c.ActiveVersion) {
106-
continue
107-
}
108-
devVersion := !ann.VersionMin.LowerOrEqual(c.ActiveVersion)
109-
// log.Println(ann.Title, ann.VersionMin, ">", c.ActiveVersion, devVersion)
110-
if ann.Group == "" {
111-
ann.Group = ann.Title
112-
}
113-
annType := ann.Type
114-
if ann.Type == "bool" {
115-
annType = `[bool](#bool)`
116-
}
117-
defaultValue := ann.Default
118-
if annType != "number" && ann.Default != "" {
119-
defaultValue = `"` + ann.Default + `"`
120-
}
121-
dev := ""
122-
if devVersion {
123-
dev = " :construction:(dev)"
124-
}
125-
groupLink := strings.ReplaceAll(ann.Group, " ", "-")
126-
// log.Println(ann.Group, groupLink)
127-
// 3 can be a link to type maybe like for [IPs or CIDRs](#access-control)?
128-
buff.WriteString(fmt.Sprintf("| [%s](#%s)%s | %s | %s | %s |%s|%s|%s|\n",
129-
ann.Title, groupLink, dev, annType, defaultValue, ann.Dependencies,
130-
Contains(ann.AppliesTo, "configmap"), Contains(ann.AppliesTo, "ingress"), Contains(ann.AppliesTo, "service")))
131-
132-
// write group
133-
groups[ann.Group] = struct{}{}
134-
}
135-
136-
buff.WriteString(tableFooter)
137-
138-
sortedGroups := []string{}
139-
for group := range groups {
140-
sortedGroups = append(sortedGroups, group)
141-
}
142-
sort.Strings(sortedGroups)
143-
for _, group := range sortedGroups {
144-
buff.WriteString(fmt.Sprintf("#### %s\n\n", strings.ReplaceAll(strings.Title(group), "-", " ")))
145-
groupData, haveGroupData := c.Groups[group]
146-
if haveGroupData && groupData.Header != "" {
147-
buff.WriteString(fmt.Sprintf("%s\n\n", groupData.Header))
148-
}
149-
for _, ann := range c.Items {
150-
if ann.Group != group {
151-
continue
152-
}
153-
buff.WriteString(fmt.Sprintf("##### `%s`\n\n", ann.Title))
154-
if !ann.VersionMin.LowerOrEqual(c.ActiveVersion) {
155-
buff.WriteString("\n > :construction: this is only available from next version, currently available in dev build\n\n")
156-
}
157-
for _, desc := range ann.Description {
158-
buff.WriteString(fmt.Sprintf(" %s\n", desc))
159-
}
160-
buff.WriteString("\n Available on:")
161-
for _, app := range ann.AppliesTo {
162-
buff.WriteString(fmt.Sprintf(" `%s`", app))
163-
}
164-
buff.WriteString("\n")
165-
for _, tip := range ann.Tip {
166-
buff.WriteString(fmt.Sprintf("\n :information_source: %s\n", tip))
167-
}
168-
buff.WriteString("\nPossible values:\n\n")
169-
for _, value := range ann.Values {
170-
buff.WriteString(fmt.Sprintf("- %s\n", writeValue(value, ann.Default)))
171-
}
172-
buff.WriteString("\n")
173-
selectExamples(ann, &buff)
174-
}
175-
if haveGroupData && groupData.Footer != "" {
176-
buff.WriteString(fmt.Sprintf("%s\n\n", groupData.Footer))
177-
}
178-
buff.WriteString("<p align='right'><a href='#available-annotations'>:arrow_up_small: back to top</a></p>\n\n***\n\n")
179-
}
180-
181-
buff.WriteString(docFooter)
33+
buff.WriteString(headerREADME)
18234

183-
err := renameio.WriteFile("../README.md", []byte(buff.String()), 0644)
35+
err := renameio.WriteFile("../README.md", []byte(buff.String()), 0o644)
18436
if err != nil {
18537
log.Println(err)
18638
}

0 commit comments

Comments
 (0)