feat(refacto): move everything in internal package
This allows to install katenary with `go install` and to clean up the project folder.
This commit is contained in:
2
internal/generator/extrafiles/doc.go
Normal file
2
internal/generator/extrafiles/doc.go
Normal file
@@ -0,0 +1,2 @@
|
||||
/* Package extrafiles provides function to generate the Chart files that are not objects. Like README.md and notes.txt... */
|
||||
package extrafiles
|
31
internal/generator/extrafiles/notes.go
Normal file
31
internal/generator/extrafiles/notes.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package extrafiles
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
//go:embed notes.tpl
|
||||
var notesTemplate string
|
||||
|
||||
// NotesFile returns the content of the note.txt file.
|
||||
func NotesFile(services []string) string {
|
||||
// build a list of ingress URLs if there are any
|
||||
ingresses := make([]string, len(services))
|
||||
for i, service := range services {
|
||||
condition := fmt.Sprintf(`{{- if and .Values.%[1]s.ingress .Values.%[1]s.ingress.enabled }}`, service)
|
||||
line := fmt.Sprintf(`{{- $count = add1 $count -}}{{- $listOfURL = printf "%%s\n- http://%%s" $listOfURL (tpl .Values.%s.ingress.host .) -}}`, service)
|
||||
ingresses[i] = fmt.Sprintf("%s\n%s\n{{- end }}", condition, line)
|
||||
}
|
||||
|
||||
// inject the list of ingress URLs into the notes template
|
||||
notes := strings.Split(notesTemplate, "\n")
|
||||
for i, line := range notes {
|
||||
if strings.Contains(line, "ingress_list") {
|
||||
notes[i] = strings.Join(ingresses, "\n")
|
||||
}
|
||||
}
|
||||
|
||||
return strings.Join(notes, "\n")
|
||||
}
|
39
internal/generator/extrafiles/notes.tpl
Normal file
39
internal/generator/extrafiles/notes.tpl
Normal file
@@ -0,0 +1,39 @@
|
||||
Thanks to have installed {{ .Chart.Name }} {{ .Chart.Version }} as {{ .Release.Name }} ({{.Chart.AppVersion }}).
|
||||
|
||||
# Get release information
|
||||
|
||||
To learn more about the release, try:
|
||||
|
||||
$ helm -n {{ .Release.Namespace }} status {{ .Release.Name }}
|
||||
$ helm -n {{ .Release.Namespace }} get values {{ .Release.Name }}
|
||||
$ helm -n {{ .Release.Namespace }} get all {{ .Release.Name }}
|
||||
|
||||
# To delete the release
|
||||
|
||||
Use helm uninstall command to delete the release.
|
||||
|
||||
$ helm -n {{ .Release.Namespace }} uninstall {{ .Release.Name }}
|
||||
|
||||
Note that some resources may still be in use after a release is deleted. For exemple, PersistentVolumeClaims are not deleted by default for some storage classes or if some annotations are set.
|
||||
|
||||
# More information
|
||||
|
||||
You can see this notes again by running:
|
||||
|
||||
$ helm -n {{ .Release.Namespace }} get notes {{ .Release.Name }}
|
||||
|
||||
{{- $count := 0 -}}
|
||||
{{- $listOfURL := "" -}}
|
||||
{{* DO NOT REMOVE, replaced by notes.go: ingress_list *}}
|
||||
{{- if gt $count 0 }}
|
||||
|
||||
# List of activated ingresses URL:
|
||||
{{ $listOfURL }}
|
||||
|
||||
You can get these urls with kubectl:
|
||||
|
||||
kubeclt get ingress -n {{ .Release.Namespace }}
|
||||
|
||||
{{- end }}
|
||||
|
||||
Thanks for using Helm!
|
40
internal/generator/extrafiles/notes_test.go
Normal file
40
internal/generator/extrafiles/notes_test.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package extrafiles
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// override the embedded template for testing
|
||||
var testTemplate = `
|
||||
Some header
|
||||
{{ ingress_list }}
|
||||
Some footer
|
||||
`
|
||||
|
||||
func init() {
|
||||
notesTemplate = testTemplate
|
||||
}
|
||||
|
||||
func TestNotesFile_NoServices(t *testing.T) {
|
||||
result := NotesFile([]string{})
|
||||
if !strings.Contains(result, "Some header") || !strings.Contains(result, "Some footer") {
|
||||
t.Errorf("Expected template header/footer in output, got: %s", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNotesFile_WithServices(t *testing.T) {
|
||||
services := []string{"svc1", "svc2"}
|
||||
result := NotesFile(services)
|
||||
|
||||
for _, svc := range services {
|
||||
cond := "{{- if and .Values." + svc + ".ingress .Values." + svc + ".ingress.enabled }}"
|
||||
line := "{{- $count = add1 $count -}}{{- $listOfURL = printf \"%s\\n- http://%s\" $listOfURL (tpl .Values." + svc + ".ingress.host .) -}}"
|
||||
if !strings.Contains(result, cond) {
|
||||
t.Errorf("Expected condition for service %s in output", svc)
|
||||
}
|
||||
if !strings.Contains(result, line) {
|
||||
t.Errorf("Expected line for service %s in output", svc)
|
||||
}
|
||||
}
|
||||
}
|
100
internal/generator/extrafiles/readme.go
Normal file
100
internal/generator/extrafiles/readme.go
Normal file
@@ -0,0 +1,100 @@
|
||||
package extrafiles
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"log"
|
||||
"sort"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
//go:embed readme.tpl
|
||||
var readmeTemplate string
|
||||
|
||||
type chart struct {
|
||||
Name string
|
||||
Description string
|
||||
Values []string
|
||||
}
|
||||
|
||||
func parseValues(prefix string, values map[string]any, result map[string]string) {
|
||||
for key, value := range values {
|
||||
path := key
|
||||
if prefix != "" {
|
||||
path = prefix + "." + key
|
||||
}
|
||||
|
||||
switch v := value.(type) {
|
||||
case []any:
|
||||
for i, u := range v {
|
||||
parseValues(fmt.Sprintf("%s[%d]", path, i), map[string]any{"value": u}, result)
|
||||
}
|
||||
case map[string]any:
|
||||
parseValues(path, v, result)
|
||||
default:
|
||||
strValue := fmt.Sprintf("`%v`", value)
|
||||
result["`"+path+"`"] = strValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ReadMeFile returns the content of the README.md file.
|
||||
func ReadMeFile(charname, description string, values map[string]any) string {
|
||||
// values is a yaml structure with keys and structured values...
|
||||
// we want to make list of dot separated keys and their values
|
||||
|
||||
vv := map[string]any{}
|
||||
out, _ := yaml.Marshal(values)
|
||||
if err := yaml.Unmarshal(out, &vv); err != nil {
|
||||
log.Printf("Error parsing values: %s", err)
|
||||
}
|
||||
|
||||
result := make(map[string]string)
|
||||
parseValues("", vv, result)
|
||||
|
||||
funcMap := template.FuncMap{
|
||||
"repeat": func(s string, count int) string {
|
||||
return strings.Repeat(s, count)
|
||||
},
|
||||
}
|
||||
tpl, err := template.New("readme").Funcs(funcMap).Parse(readmeTemplate)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
valuesLines := []string{}
|
||||
maxParamLen := 0
|
||||
maxDefaultLen := 0
|
||||
for key, value := range result {
|
||||
if len(key) > maxParamLen {
|
||||
maxParamLen = len(key)
|
||||
}
|
||||
if len(value) > maxDefaultLen {
|
||||
maxDefaultLen = len(value)
|
||||
}
|
||||
}
|
||||
for key, value := range result {
|
||||
valuesLines = append(valuesLines, fmt.Sprintf("| %-*s | %-*s |", maxParamLen, key, maxDefaultLen, value))
|
||||
}
|
||||
sort.Strings(valuesLines)
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
err = tpl.Execute(buf, map[string]any{
|
||||
"DescrptionPadding": maxParamLen,
|
||||
"DefaultPadding": maxDefaultLen,
|
||||
"Chart": chart{
|
||||
Name: charname,
|
||||
Description: description,
|
||||
Values: valuesLines,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return buf.String()
|
||||
}
|
32
internal/generator/extrafiles/readme.tpl
Normal file
32
internal/generator/extrafiles/readme.tpl
Normal file
@@ -0,0 +1,32 @@
|
||||
# {{ .Chart.Name }}
|
||||
|
||||
{{ .Chart.Description }}
|
||||
|
||||
## Installing the Chart
|
||||
|
||||
To install the chart with the release name `my-release`:
|
||||
|
||||
```bash
|
||||
# Standard Helm install
|
||||
$ helm install my-release {{ .Chart.Name }}
|
||||
|
||||
# To use a custom namespace and force the creation of the namespace
|
||||
$ helm install my-release --namespace my-namespace --create-namespace {{ .Chart.Name }}
|
||||
|
||||
# To use a custom values file
|
||||
$ helm install my-release -f my-values.yaml {{ .Chart.Name }}
|
||||
```
|
||||
|
||||
See the [Helm documentation](https://helm.sh/docs/intro/using_helm/) for more information on installing and managing the chart.
|
||||
|
||||
## Configuration
|
||||
|
||||
The following table lists the configurable parameters of the {{ .Chart.Name }} chart and their default values.
|
||||
|
||||
| {{ printf "%-*s" .DescrptionPadding "Parameter" }} | {{ printf "%-*s" .DefaultPadding "Default" }} |
|
||||
| {{ repeat "-" .DescrptionPadding }} | {{ repeat "-" .DefaultPadding }} |
|
||||
{{- range .Chart.Values }}
|
||||
{{ . }}
|
||||
{{- end }}
|
||||
|
||||
|
33
internal/generator/extrafiles/readme_test.go
Normal file
33
internal/generator/extrafiles/readme_test.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package extrafiles
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestReadMeFile_Basic(t *testing.T) {
|
||||
values := map[string]any{
|
||||
"replicas": 2,
|
||||
"image": map[string]any{
|
||||
"repository": "nginx",
|
||||
"tag": "latest",
|
||||
},
|
||||
}
|
||||
|
||||
result := ReadMeFile("testchart", "A test chart", values)
|
||||
t.Logf("Generated README content:\n%s", result)
|
||||
paramerRegExp := regexp.MustCompile(`\|\s+` + "`" + `(.*?)` + "`" + `\s+\|\s+` + "`" + `(.*?)` + "`" + `\s+\|`)
|
||||
matches := paramerRegExp.FindAllStringSubmatch(result, -1)
|
||||
if len(matches) != 3 {
|
||||
t.Errorf("Expected 5 lines in the table for headers and parameters, got %d", len(matches))
|
||||
}
|
||||
if matches[0][1] != "image.repository" || matches[0][2] != "nginx" {
|
||||
t.Errorf("Expected third line to be image.repository, got %s", matches[1])
|
||||
}
|
||||
if matches[1][1] != "image.tag" || matches[1][2] != "latest" {
|
||||
t.Errorf("Expected fourth line to be image.tag, got %s", matches[2])
|
||||
}
|
||||
if matches[2][1] != "replicas" || matches[2][2] != "2" {
|
||||
t.Errorf("Expected second line to be replicas, got %s", matches[0])
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user