2024-11-18 17:12:12 +01:00
|
|
|
package labels
|
2023-12-06 15:24:02 +01:00
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
_ "embed"
|
|
|
|
"fmt"
|
2024-10-17 17:08:42 +02:00
|
|
|
"katenary/utils"
|
2023-12-06 15:24:02 +01:00
|
|
|
"regexp"
|
|
|
|
"sort"
|
|
|
|
"strings"
|
|
|
|
"text/tabwriter"
|
|
|
|
"text/template"
|
|
|
|
|
|
|
|
"sigs.k8s.io/yaml"
|
2024-10-17 17:08:42 +02:00
|
|
|
)
|
2024-05-06 21:11:36 +02:00
|
|
|
|
2024-11-18 17:12:12 +01:00
|
|
|
const KatenaryLabelPrefix = "katenary.v3"
|
2024-10-17 17:08:42 +02:00
|
|
|
|
|
|
|
// Known labels.
|
|
|
|
const (
|
2024-11-18 17:12:12 +01:00
|
|
|
LabelMainApp Label = KatenaryLabelPrefix + "/main-app"
|
|
|
|
LabelValues Label = KatenaryLabelPrefix + "/values"
|
|
|
|
LabelSecrets Label = KatenaryLabelPrefix + "/secrets"
|
|
|
|
LabelPorts Label = KatenaryLabelPrefix + "/ports"
|
|
|
|
LabelIngress Label = KatenaryLabelPrefix + "/ingress"
|
|
|
|
LabelMapEnv Label = KatenaryLabelPrefix + "/map-env"
|
|
|
|
LabelHealthCheck Label = KatenaryLabelPrefix + "/health-check"
|
|
|
|
LabelSamePod Label = KatenaryLabelPrefix + "/same-pod"
|
|
|
|
LabelDescription Label = KatenaryLabelPrefix + "/description"
|
|
|
|
LabelIgnore Label = KatenaryLabelPrefix + "/ignore"
|
|
|
|
LabelDependencies Label = KatenaryLabelPrefix + "/dependencies"
|
|
|
|
LabelConfigMapFiles Label = KatenaryLabelPrefix + "/configmap-files"
|
|
|
|
LabelCronJob Label = KatenaryLabelPrefix + "/cronjob"
|
|
|
|
LabelEnvFrom Label = KatenaryLabelPrefix + "/env-from"
|
2024-11-22 14:54:36 +01:00
|
|
|
LabelExchangeVolume Label = KatenaryLabelPrefix + "/exchange-volumes"
|
2024-11-26 16:11:12 +01:00
|
|
|
LabelValueFrom Label = KatenaryLabelPrefix + "/values-from"
|
2023-12-06 15:24:02 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
// Set the documentation of labels here
|
|
|
|
//
|
|
|
|
//go:embed katenaryLabelsDoc.yaml
|
|
|
|
labelFullHelpYAML []byte
|
|
|
|
|
|
|
|
// parsed yaml
|
|
|
|
labelFullHelp map[string]Help
|
2024-11-21 11:08:55 +01:00
|
|
|
|
|
|
|
//go:embed help-template.tpl
|
|
|
|
helpTemplatePlain string
|
|
|
|
|
|
|
|
//go:embed help-template.md.tpl
|
|
|
|
helpTemplateMarkdown string
|
2023-12-06 15:24:02 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
// Label is a katenary label to find in compose files.
|
|
|
|
type Label = string
|
|
|
|
|
2024-11-18 17:12:12 +01:00
|
|
|
func LabelName(name string) Label {
|
|
|
|
return Label(KatenaryLabelPrefix + "/" + name)
|
2024-10-17 17:08:42 +02:00
|
|
|
}
|
|
|
|
|
2023-12-06 15:24:02 +01:00
|
|
|
// Help is the documentation of a label.
|
|
|
|
type Help struct {
|
|
|
|
Short string `yaml:"short"`
|
|
|
|
Long string `yaml:"long"`
|
|
|
|
Example string `yaml:"example"`
|
|
|
|
Type string `yaml:"type"`
|
|
|
|
}
|
|
|
|
|
2024-10-17 17:08:42 +02:00
|
|
|
// GetLabelNames returns a sorted list of all katenary label names.
|
|
|
|
func GetLabelNames() []string {
|
|
|
|
var names []string
|
|
|
|
for name := range labelFullHelp {
|
|
|
|
names = append(names, name)
|
|
|
|
}
|
|
|
|
sort.Strings(names)
|
|
|
|
return names
|
2024-04-24 13:59:21 +02:00
|
|
|
}
|
2023-12-06 15:24:02 +01:00
|
|
|
|
|
|
|
func init() {
|
|
|
|
if err := yaml.Unmarshal(labelFullHelpYAML, &labelFullHelp); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Generate the help for the labels.
|
|
|
|
func GetLabelHelp(asMarkdown bool) string {
|
|
|
|
names := GetLabelNames() // sorted
|
|
|
|
if !asMarkdown {
|
|
|
|
return generatePlainHelp(names)
|
|
|
|
}
|
|
|
|
return generateMarkdownHelp(names)
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetLabelHelpFor returns the help for a specific label.
|
|
|
|
func GetLabelHelpFor(labelname string, asMarkdown bool) string {
|
|
|
|
help, ok := labelFullHelp[labelname]
|
|
|
|
if !ok {
|
|
|
|
return "No help available for " + labelname + "."
|
|
|
|
}
|
|
|
|
|
|
|
|
help.Long = strings.TrimPrefix(help.Long, "\n")
|
|
|
|
help.Example = strings.TrimPrefix(help.Example, "\n")
|
|
|
|
help.Short = strings.TrimPrefix(help.Short, "\n")
|
|
|
|
|
|
|
|
if asMarkdown {
|
|
|
|
// enclose templates in backticks
|
|
|
|
help.Long = regexp.MustCompile(`\{\{(.*?)\}\}`).ReplaceAllString(help.Long, "`{{$1}}`")
|
|
|
|
help.Long = strings.ReplaceAll(help.Long, "__APP__", "`__APP__`")
|
|
|
|
} else {
|
|
|
|
help.Long = strings.ReplaceAll(help.Long, " \n", "\n")
|
|
|
|
help.Long = strings.ReplaceAll(help.Long, "`", "")
|
|
|
|
help.Long = strings.ReplaceAll(help.Long, "<code>", "")
|
|
|
|
help.Long = strings.ReplaceAll(help.Long, "</code>", "")
|
|
|
|
help.Long = utils.WordWrap(help.Long, 80)
|
|
|
|
}
|
|
|
|
|
2024-11-21 11:08:55 +01:00
|
|
|
// get help template
|
|
|
|
var helpTemplate string
|
|
|
|
switch asMarkdown {
|
|
|
|
case true:
|
|
|
|
helpTemplate = helpTemplateMarkdown
|
|
|
|
case false:
|
|
|
|
helpTemplate = helpTemplatePlain
|
|
|
|
}
|
|
|
|
|
2023-12-06 15:24:02 +01:00
|
|
|
var buf bytes.Buffer
|
|
|
|
template.Must(template.New("shorthelp").Parse(help.Long)).Execute(&buf, struct {
|
2024-04-24 13:59:21 +02:00
|
|
|
KatenaryPrefix string
|
2023-12-06 15:24:02 +01:00
|
|
|
}{
|
2024-11-18 17:12:12 +01:00
|
|
|
KatenaryPrefix: KatenaryLabelPrefix,
|
2023-12-06 15:24:02 +01:00
|
|
|
})
|
|
|
|
help.Long = buf.String()
|
|
|
|
buf.Reset()
|
|
|
|
|
|
|
|
template.Must(template.New("example").Parse(help.Example)).Execute(&buf, struct {
|
2024-04-24 13:59:21 +02:00
|
|
|
KatenaryPrefix string
|
2023-12-06 15:24:02 +01:00
|
|
|
}{
|
2024-11-18 17:12:12 +01:00
|
|
|
KatenaryPrefix: KatenaryLabelPrefix,
|
2023-12-06 15:24:02 +01:00
|
|
|
})
|
|
|
|
help.Example = buf.String()
|
|
|
|
buf.Reset()
|
|
|
|
|
|
|
|
template.Must(template.New("complete").Parse(helpTemplate)).Execute(&buf, struct {
|
2024-04-24 13:59:21 +02:00
|
|
|
Name string
|
|
|
|
Help Help
|
|
|
|
KatenaryPrefix string
|
2023-12-06 15:24:02 +01:00
|
|
|
}{
|
2024-04-24 13:59:21 +02:00
|
|
|
Name: labelname,
|
|
|
|
Help: help,
|
2024-11-18 17:12:12 +01:00
|
|
|
KatenaryPrefix: KatenaryLabelPrefix,
|
2023-12-06 15:24:02 +01:00
|
|
|
})
|
|
|
|
|
|
|
|
return buf.String()
|
|
|
|
}
|
|
|
|
|
2024-10-17 17:08:42 +02:00
|
|
|
func generateMarkdownHelp(names []string) string {
|
|
|
|
var builder strings.Builder
|
|
|
|
var maxNameLength, maxDescriptionLength, maxTypeLength int
|
|
|
|
|
|
|
|
max := func(a, b int) int {
|
|
|
|
if a > b {
|
|
|
|
return a
|
|
|
|
}
|
|
|
|
return b
|
2023-12-06 15:24:02 +01:00
|
|
|
}
|
2024-10-17 17:08:42 +02:00
|
|
|
for _, name := range names {
|
|
|
|
help := labelFullHelp[name]
|
2024-11-26 23:42:39 +01:00
|
|
|
maxNameLength = max(maxNameLength, len(name)+3+len(KatenaryLabelPrefix))
|
2024-10-17 17:08:42 +02:00
|
|
|
maxDescriptionLength = max(maxDescriptionLength, len(help.Short))
|
2024-11-26 23:42:39 +01:00
|
|
|
maxTypeLength = max(maxTypeLength, len(help.Type)+3)
|
2024-10-17 17:08:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Fprintf(&builder, "%s\n", generateTableHeader(maxNameLength, maxDescriptionLength, maxTypeLength))
|
|
|
|
fmt.Fprintf(&builder, "%s\n", generateTableHeaderSeparator(maxNameLength, maxDescriptionLength, maxTypeLength))
|
|
|
|
|
|
|
|
for _, name := range names {
|
|
|
|
help := labelFullHelp[name]
|
|
|
|
fmt.Fprintf(&builder, "| %-*s | %-*s | %-*s |\n",
|
2024-11-18 17:12:12 +01:00
|
|
|
maxNameLength, "`"+LabelName(name)+"`", // enclose in backticks
|
2024-10-17 17:08:42 +02:00
|
|
|
maxDescriptionLength, help.Short,
|
2024-11-26 23:42:39 +01:00
|
|
|
maxTypeLength, "`"+help.Type+"`",
|
2024-10-17 17:08:42 +02:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
return builder.String()
|
|
|
|
}
|
|
|
|
|
|
|
|
func generatePlainHelp(names []string) string {
|
|
|
|
var builder strings.Builder
|
|
|
|
for _, name := range names {
|
|
|
|
help := labelFullHelp[name]
|
2024-11-18 17:12:12 +01:00
|
|
|
fmt.Fprintf(&builder, "%s:\t%s\t%s\n", LabelName(name), help.Type, help.Short)
|
2024-10-17 17:08:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// use tabwriter to align the help text
|
|
|
|
buf := new(strings.Builder)
|
|
|
|
w := tabwriter.NewWriter(buf, 0, 8, 0, '\t', tabwriter.AlignRight)
|
|
|
|
fmt.Fprintln(w, builder.String())
|
|
|
|
w.Flush()
|
|
|
|
|
|
|
|
head := "To get more information about a label, use `katenary help-label <name_without_prefix>\ne.g. katenary help-label dependencies\n\n"
|
|
|
|
return head + buf.String()
|
|
|
|
}
|
|
|
|
|
|
|
|
func generateTableHeader(maxNameLength, maxDescriptionLength, maxTypeLength int) string {
|
|
|
|
return fmt.Sprintf(
|
|
|
|
"| %-*s | %-*s | %-*s |",
|
|
|
|
maxNameLength, "Label name",
|
|
|
|
maxDescriptionLength, "Description",
|
|
|
|
maxTypeLength, "Type",
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
func generateTableHeaderSeparator(maxNameLength, maxDescriptionLength, maxTypeLength int) string {
|
|
|
|
return fmt.Sprintf(
|
|
|
|
"| %s | %s | %s |",
|
|
|
|
strings.Repeat("-", maxNameLength),
|
|
|
|
strings.Repeat("-", maxDescriptionLength),
|
|
|
|
strings.Repeat("-", maxTypeLength),
|
|
|
|
)
|
2023-12-06 15:24:02 +01:00
|
|
|
}
|
|
|
|
|
2024-10-17 17:08:42 +02:00
|
|
|
func Prefix() string {
|
2024-11-18 17:12:12 +01:00
|
|
|
return KatenaryLabelPrefix
|
2024-10-17 17:08:42 +02:00
|
|
|
}
|