chore(refacto): fix secret and use katenary schema
- add possibility to use a katenary.yaml file to setup values - fix secret generation
This commit is contained in:
27
.gitignore
vendored
27
.gitignore
vendored
@@ -1,25 +1,20 @@
|
|||||||
.venv
|
|
||||||
dist/*
|
dist/*
|
||||||
.cache/*
|
|
||||||
chart/*
|
|
||||||
*.yaml
|
|
||||||
*.yml
|
|
||||||
!.markdownlint.yaml
|
|
||||||
!generator/*.yaml
|
|
||||||
doc/venv/*
|
|
||||||
!doc/mkdocs.yaml
|
|
||||||
!.readthedocs.yaml
|
|
||||||
./katenary
|
|
||||||
*.env
|
*.env
|
||||||
docker-compose*
|
|
||||||
!examples/**/docker-compose*
|
|
||||||
.credentials
|
.credentials
|
||||||
release.id
|
release.id
|
||||||
configs/
|
|
||||||
cover*
|
cover*
|
||||||
.sq
|
.sq
|
||||||
./katenary
|
|
||||||
.aider*
|
.aider*
|
||||||
.python_history
|
.python_history
|
||||||
.bash_history
|
.bash_history
|
||||||
katenary
|
|
||||||
|
.cache/
|
||||||
|
.aider/
|
||||||
|
.config/
|
||||||
|
*/venv
|
||||||
|
|
||||||
|
# local binary
|
||||||
|
./katenary
|
||||||
|
|
||||||
|
# will be treated later
|
||||||
|
/examples/*
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
default: true
|
default: true
|
||||||
|
|
||||||
MD013: # Line length
|
MD013: # Line length
|
||||||
line_length: 240
|
line_length: 120
|
||||||
|
|
||||||
MD010: # Hard tabs
|
MD010: # Hard tabs
|
||||||
code_blocks: false
|
code_blocks: false
|
||||||
@@ -16,3 +16,6 @@ MD041: false
|
|||||||
# list indentation
|
# list indentation
|
||||||
MD007:
|
MD007:
|
||||||
indent: 4
|
indent: 4
|
||||||
|
|
||||||
|
# no problem using several code blocks styles
|
||||||
|
MD046: false
|
||||||
|
3
Makefile
3
Makefile
@@ -169,6 +169,9 @@ tests: test
|
|||||||
test:
|
test:
|
||||||
@echo -e "\033[1;33mTesting katenary $(VERSION)...\033[0m"
|
@echo -e "\033[1;33mTesting katenary $(VERSION)...\033[0m"
|
||||||
go test -coverprofile=cover.out ./...
|
go test -coverprofile=cover.out ./...
|
||||||
|
$(MAKE) cover
|
||||||
|
|
||||||
|
cover:
|
||||||
go tool cover -func=cover.out | grep "total:"
|
go tool cover -func=cover.out | grep "total:"
|
||||||
go tool cover -html=cover.out -o cover.html
|
go tool cover -html=cover.out -o cover.html
|
||||||
if [ "$(BROWSER)" = "xdg-open" ]; then
|
if [ "$(BROWSER)" = "xdg-open" ]; then
|
||||||
|
@@ -7,6 +7,8 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"katenary/generator"
|
"katenary/generator"
|
||||||
|
"katenary/generator/katenaryfile"
|
||||||
|
"katenary/generator/labels"
|
||||||
"katenary/utils"
|
"katenary/utils"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -43,6 +45,7 @@ func buildRootCmd() *cobra.Command {
|
|||||||
generateConvertCommand(),
|
generateConvertCommand(),
|
||||||
generateHashComposefilesCommand(),
|
generateHashComposefilesCommand(),
|
||||||
generateLabelHelpCommand(),
|
generateLabelHelpCommand(),
|
||||||
|
generateSchemaCommand(),
|
||||||
)
|
)
|
||||||
|
|
||||||
return rootCmd
|
return rootCmd
|
||||||
@@ -245,31 +248,31 @@ func generateLabelHelpCommand() *cobra.Command {
|
|||||||
If no label is specified, the help for all labels is printed.
|
If no label is specified, the help for all labels is printed.
|
||||||
If a label is specified, the help for this label is printed.
|
If a label is specified, the help for this label is printed.
|
||||||
|
|
||||||
The name of the label must be specified without the prefix ` + generator.Prefix() + `.
|
The name of the label must be specified without the prefix ` + labels.Prefix() + `.
|
||||||
|
|
||||||
e.g.
|
e.g.
|
||||||
kanetary help-labels
|
kanetary help-labels
|
||||||
katenary help-labels ingress
|
katenary help-labels ingress
|
||||||
katenary help-labels map-env
|
katenary help-labels map-env
|
||||||
`,
|
`,
|
||||||
ValidArgs: generator.GetLabelNames(),
|
ValidArgs: labels.GetLabelNames(),
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
fmt.Println(generator.GetLabelHelpFor(args[0], markdown))
|
fmt.Println(labels.GetLabelHelpFor(args[0], markdown))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if all {
|
if all {
|
||||||
// show the help for all labels
|
// show the help for all labels
|
||||||
l := len(generator.GetLabelNames())
|
l := len(labels.GetLabelNames())
|
||||||
for i, label := range generator.GetLabelNames() {
|
for i, label := range labels.GetLabelNames() {
|
||||||
fmt.Println(generator.GetLabelHelpFor(label, markdown))
|
fmt.Println(labels.GetLabelHelpFor(label, markdown))
|
||||||
if !markdown && i < l-1 {
|
if !markdown && i < l-1 {
|
||||||
fmt.Println(strings.Repeat("-", 80))
|
fmt.Println(strings.Repeat("-", 80))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
fmt.Println(generator.GetLabelHelp(markdown))
|
fmt.Println(labels.GetLabelHelp(markdown))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -298,3 +301,15 @@ If no composefile is specified, the hash of all composefiles is printed.`,
|
|||||||
}
|
}
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func generateSchemaCommand() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "schema",
|
||||||
|
Short: "Print the schema of the katenary file",
|
||||||
|
Long: "Generate a schama for katenary.yaml file that can be used to validate the file or to use with yaml LSP to complete and check your configuration.",
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
fmt.Println(katenaryfile.GenerateSchema())
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
@@ -10,7 +10,7 @@ func TestBuildCommand(t *testing.T) {
|
|||||||
if rootCmd.Use != "katenary" {
|
if rootCmd.Use != "katenary" {
|
||||||
t.Errorf("Expected rootCmd.Use to be katenary, got %s", rootCmd.Use)
|
t.Errorf("Expected rootCmd.Use to be katenary, got %s", rootCmd.Use)
|
||||||
}
|
}
|
||||||
numCommands := 5
|
numCommands := 6
|
||||||
if len(rootCmd.Commands()) != numCommands {
|
if len(rootCmd.Commands()) != numCommands {
|
||||||
t.Errorf("Expected %d command, got %d", numCommands, len(rootCmd.Commands()))
|
t.Errorf("Expected %d command, got %d", numCommands, len(rootCmd.Commands()))
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,8 @@ package generator
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"katenary/generator/labelStructs"
|
"katenary/generator/labels"
|
||||||
|
"katenary/generator/labels/labelStructs"
|
||||||
"katenary/utils"
|
"katenary/utils"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
@@ -136,7 +137,7 @@ func (chart *HelmChart) generateConfigMapsAndSecrets(project *types.Project) err
|
|||||||
originalEnv[k] = v
|
originalEnv[k] = v
|
||||||
}
|
}
|
||||||
|
|
||||||
if v, ok := s.Labels[LabelSecrets]; ok {
|
if v, ok := s.Labels[labels.LabelSecrets]; ok {
|
||||||
list, err := labelStructs.SecretsFrom(v)
|
list, err := labelStructs.SecretsFrom(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("error unmarshaling secrets label:", err)
|
log.Fatal("error unmarshaling secrets label:", err)
|
||||||
@@ -210,7 +211,8 @@ func (chart *HelmChart) generateDeployment(service types.ServiceConfig, deployme
|
|||||||
|
|
||||||
// get the same-pod label if exists, add it to the list.
|
// get the same-pod label if exists, add it to the list.
|
||||||
// We later will copy some parts to the target deployment and remove this one.
|
// We later will copy some parts to the target deployment and remove this one.
|
||||||
if samePod, ok := service.Labels[LabelSamePod]; ok && samePod != "" {
|
if samePod, ok := service.Labels[labels.LabelSamePod]; ok && samePod != "" {
|
||||||
|
log.Printf("Found same-pod label for %s", service.Name)
|
||||||
podToMerge[samePod] = &service
|
podToMerge[samePod] = &service
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,7 +249,7 @@ func (chart *HelmChart) setChartVersion(service types.ServiceConfig) {
|
|||||||
|
|
||||||
// setCronJob creates a cronjob from the service labels.
|
// setCronJob creates a cronjob from the service labels.
|
||||||
func (chart *HelmChart) setCronJob(service types.ServiceConfig, appName string) *CronJob {
|
func (chart *HelmChart) setCronJob(service types.ServiceConfig, appName string) *CronJob {
|
||||||
if _, ok := service.Labels[LabelCronJob]; !ok {
|
if _, ok := service.Labels[labels.LabelCronJob]; !ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
cronjob, rbac := NewCronJob(service, chart, appName)
|
cronjob, rbac := NewCronJob(service, chart, appName)
|
||||||
@@ -281,7 +283,7 @@ func (chart *HelmChart) setCronJob(service types.ServiceConfig, appName string)
|
|||||||
// setDependencies sets the dependencies from the service labels.
|
// setDependencies sets the dependencies from the service labels.
|
||||||
func (chart *HelmChart) setDependencies(service types.ServiceConfig) (bool, error) {
|
func (chart *HelmChart) setDependencies(service types.ServiceConfig) (bool, error) {
|
||||||
// helm dependency
|
// helm dependency
|
||||||
if v, ok := service.Labels[LabelDependencies]; ok {
|
if v, ok := service.Labels[labels.LabelDependencies]; ok {
|
||||||
d, err := labelStructs.DependenciesFrom(v)
|
d, err := labelStructs.DependenciesFrom(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@@ -307,10 +309,10 @@ func (chart *HelmChart) setDependencies(service types.ServiceConfig) (bool, erro
|
|||||||
func (chart *HelmChart) setSharedConf(service types.ServiceConfig, deployments map[string]*Deployment) {
|
func (chart *HelmChart) setSharedConf(service types.ServiceConfig, deployments map[string]*Deployment) {
|
||||||
// if the service has the "shared-conf" label, we need to add the configmap
|
// if the service has the "shared-conf" label, we need to add the configmap
|
||||||
// to the chart and add the env vars to the service
|
// to the chart and add the env vars to the service
|
||||||
if _, ok := service.Labels[LabelEnvFrom]; !ok {
|
if _, ok := service.Labels[labels.LabelEnvFrom]; !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
fromservices, err := labelStructs.EnvFromFrom(service.Labels[LabelEnvFrom])
|
fromservices, err := labelStructs.EnvFromFrom(service.Labels[labels.LabelEnvFrom])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("error unmarshaling env-from label:", err)
|
log.Fatal("error unmarshaling env-from label:", err)
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
package generator
|
package generator
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"katenary/generator/labelStructs"
|
"katenary/generator/labels"
|
||||||
|
"katenary/generator/labels/labelStructs"
|
||||||
"katenary/utils"
|
"katenary/utils"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
@@ -73,7 +74,7 @@ func NewConfigMap(service types.ServiceConfig, appName string, forFile bool) *Co
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get the secrets from the labels
|
// get the secrets from the labels
|
||||||
secrets, err := labelStructs.SecretsFrom(service.Labels[LabelSecrets])
|
secrets, err := labelStructs.SecretsFrom(service.Labels[labels.LabelSecrets])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -82,7 +83,7 @@ func NewConfigMap(service types.ServiceConfig, appName string, forFile bool) *Co
|
|||||||
drop[secret] = true
|
drop[secret] = true
|
||||||
}
|
}
|
||||||
// get the label values from the labels
|
// get the label values from the labels
|
||||||
varDescriptons := utils.GetValuesFromLabel(service, LabelValues)
|
varDescriptons := utils.GetValuesFromLabel(service, labels.LabelValues)
|
||||||
for value := range varDescriptons {
|
for value := range varDescriptons {
|
||||||
labelValues = append(labelValues, value)
|
labelValues = append(labelValues, value)
|
||||||
}
|
}
|
||||||
@@ -98,7 +99,7 @@ func NewConfigMap(service types.ServiceConfig, appName string, forFile bool) *Co
|
|||||||
if !forFile {
|
if !forFile {
|
||||||
// do not bind env variables to the configmap
|
// do not bind env variables to the configmap
|
||||||
// remove the variables that are already defined in the environment
|
// remove the variables that are already defined in the environment
|
||||||
if l, ok := service.Labels[LabelMapEnv]; ok {
|
if l, ok := service.Labels[labels.LabelMapEnv]; ok {
|
||||||
envmap, err := labelStructs.MapEnvFrom(l)
|
envmap, err := labelStructs.MapEnvFrom(l)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("Error parsing map-env", err)
|
log.Fatal("Error parsing map-env", err)
|
||||||
|
@@ -5,7 +5,9 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"katenary/generator/extrafiles"
|
"katenary/generator/extrafiles"
|
||||||
"katenary/generator/labelStructs"
|
"katenary/generator/katenaryfile"
|
||||||
|
"katenary/generator/labels"
|
||||||
|
"katenary/generator/labels/labelStructs"
|
||||||
"katenary/parser"
|
"katenary/parser"
|
||||||
"katenary/utils"
|
"katenary/utils"
|
||||||
"log"
|
"log"
|
||||||
@@ -125,6 +127,9 @@ func Convert(config ConvertOptions, dockerComposeFile ...string) {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: use katenary.yaml file here to set the labels
|
||||||
|
katenaryfile.OverrideWithConfig(project)
|
||||||
|
|
||||||
if !config.Force {
|
if !config.Force {
|
||||||
// check if the chart directory exists
|
// check if the chart directory exists
|
||||||
// if yes, prevent the user from overwriting it and ask for confirmation
|
// if yes, prevent the user from overwriting it and ask for confirmation
|
||||||
@@ -264,7 +269,7 @@ func addDependencyDescription(values []byte, dependencies []labelStructs.Depende
|
|||||||
// of the service definition.
|
// of the service definition.
|
||||||
func addDescriptions(values []byte, project types.Project) []byte {
|
func addDescriptions(values []byte, project types.Project) []byte {
|
||||||
for _, service := range project.Services {
|
for _, service := range project.Services {
|
||||||
if description, ok := service.Labels[LabelDescription]; ok {
|
if description, ok := service.Labels[labels.LabelDescription]; ok {
|
||||||
// set it as comment
|
// set it as comment
|
||||||
description = "\n# " + strings.ReplaceAll(description, "\n", "\n# ")
|
description = "\n# " + strings.ReplaceAll(description, "\n", "\n# ")
|
||||||
|
|
||||||
@@ -288,7 +293,7 @@ func addDescriptions(values []byte, project types.Project) []byte {
|
|||||||
|
|
||||||
func addDocToVariable(service types.ServiceConfig, lines []string) []string {
|
func addDocToVariable(service types.ServiceConfig, lines []string) []string {
|
||||||
currentService := ""
|
currentService := ""
|
||||||
variables := utils.GetValuesFromLabel(service, LabelValues)
|
variables := utils.GetValuesFromLabel(service, labels.LabelValues)
|
||||||
for i, line := range lines {
|
for i, line := range lines {
|
||||||
// if the line is a service, it is a name followed by a colon
|
// if the line is a service, it is a name followed by a colon
|
||||||
if regexp.MustCompile(`(?m)^` + service.Name + `:`).MatchString(line) {
|
if regexp.MustCompile(`(?m)^` + service.Name + `:`).MatchString(line) {
|
||||||
@@ -378,7 +383,7 @@ func addMainTagAppDoc(values []byte, project *types.Project) []byte {
|
|||||||
|
|
||||||
for _, service := range project.Services {
|
for _, service := range project.Services {
|
||||||
// read the label LabelMainApp
|
// read the label LabelMainApp
|
||||||
if v, ok := service.Labels[LabelMainApp]; !ok {
|
if v, ok := service.Labels[labels.LabelMainApp]; !ok {
|
||||||
continue
|
continue
|
||||||
} else if v == "false" || v == "no" || v == "0" {
|
} else if v == "false" || v == "no" || v == "0" {
|
||||||
continue
|
continue
|
||||||
@@ -651,7 +656,7 @@ func checkOldLabels(project *types.Project) error {
|
|||||||
badServices := make([]string, 0)
|
badServices := make([]string, 0)
|
||||||
for _, service := range project.Services {
|
for _, service := range project.Services {
|
||||||
for label := range service.Labels {
|
for label := range service.Labels {
|
||||||
if strings.Contains(label, "katenary.") && !strings.Contains(label, katenaryLabelPrefix) {
|
if strings.Contains(label, "katenary.") && !strings.Contains(label, labels.KatenaryLabelPrefix) {
|
||||||
badServices = append(badServices, fmt.Sprintf("- %s: %s", service.Name, label))
|
badServices = append(badServices, fmt.Sprintf("- %s: %s", service.Name, label))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -667,7 +672,7 @@ func checkOldLabels(project *types.Project) error {
|
|||||||
Services to upgrade:
|
Services to upgrade:
|
||||||
%s`,
|
%s`,
|
||||||
project.Name,
|
project.Name,
|
||||||
katenaryLabelPrefix[0:len(katenaryLabelPrefix)-1],
|
labels.KatenaryLabelPrefix[0:len(labels.KatenaryLabelPrefix)-1],
|
||||||
strings.Join(badServices, "\n"),
|
strings.Join(badServices, "\n"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
package generator
|
package generator
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"katenary/generator/labelStructs"
|
"katenary/generator/labels"
|
||||||
|
"katenary/generator/labels/labelStructs"
|
||||||
"katenary/utils"
|
"katenary/utils"
|
||||||
"log"
|
"log"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -25,7 +26,7 @@ type CronJob struct {
|
|||||||
|
|
||||||
// NewCronJob creates a new CronJob from a compose service. The appName is the name of the application taken from the project name.
|
// NewCronJob creates a new CronJob from a compose service. The appName is the name of the application taken from the project name.
|
||||||
func NewCronJob(service types.ServiceConfig, chart *HelmChart, appName string) (*CronJob, *RBAC) {
|
func NewCronJob(service types.ServiceConfig, chart *HelmChart, appName string) (*CronJob, *RBAC) {
|
||||||
labels, ok := service.Labels[LabelCronJob]
|
labels, ok := service.Labels[labels.LabelCronJob]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,8 @@ package generator
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"katenary/generator/labelStructs"
|
"katenary/generator/labels"
|
||||||
|
"katenary/generator/labels/labelStructs"
|
||||||
"katenary/utils"
|
"katenary/utils"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
@@ -44,7 +45,7 @@ type Deployment struct {
|
|||||||
// It also creates the Values map that will be used to create the values.yaml file.
|
// It also creates the Values map that will be used to create the values.yaml file.
|
||||||
func NewDeployment(service types.ServiceConfig, chart *HelmChart) *Deployment {
|
func NewDeployment(service types.ServiceConfig, chart *HelmChart) *Deployment {
|
||||||
isMainApp := false
|
isMainApp := false
|
||||||
if mainLabel, ok := service.Labels[LabelMainApp]; ok {
|
if mainLabel, ok := service.Labels[labels.LabelMainApp]; ok {
|
||||||
main := strings.ToLower(mainLabel)
|
main := strings.ToLower(mainLabel)
|
||||||
isMainApp = main == "true" || main == "yes" || main == "1"
|
isMainApp = main == "true" || main == "yes" || main == "1"
|
||||||
}
|
}
|
||||||
@@ -83,7 +84,7 @@ func NewDeployment(service types.ServiceConfig, chart *HelmChart) *Deployment {
|
|||||||
},
|
},
|
||||||
Spec: corev1.PodSpec{
|
Spec: corev1.PodSpec{
|
||||||
NodeSelector: map[string]string{
|
NodeSelector: map[string]string{
|
||||||
labelName("node-selector"): "replace",
|
labels.LabelName("node-selector"): "replace",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -154,7 +155,7 @@ func (d *Deployment) AddContainer(service types.ServiceConfig) {
|
|||||||
|
|
||||||
func (d *Deployment) AddHealthCheck(service types.ServiceConfig, container *corev1.Container) {
|
func (d *Deployment) AddHealthCheck(service types.ServiceConfig, container *corev1.Container) {
|
||||||
// get the label for healthcheck
|
// get the label for healthcheck
|
||||||
if v, ok := service.Labels[LabelHealthCheck]; ok {
|
if v, ok := service.Labels[labels.LabelHealthCheck]; ok {
|
||||||
probes, err := labelStructs.ProbeFrom(v)
|
probes, err := labelStructs.ProbeFrom(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
@@ -189,7 +190,7 @@ func (d *Deployment) AddIngress(service types.ServiceConfig, appName string) *In
|
|||||||
// If the volume is a bind volume it will warn the user that it is not supported yet.
|
// If the volume is a bind volume it will warn the user that it is not supported yet.
|
||||||
func (d *Deployment) AddVolumes(service types.ServiceConfig, appName string) {
|
func (d *Deployment) AddVolumes(service types.ServiceConfig, appName string) {
|
||||||
tobind := map[string]bool{}
|
tobind := map[string]bool{}
|
||||||
if v, ok := service.Labels[LabelConfigMapFiles]; ok {
|
if v, ok := service.Labels[labels.LabelConfigMapFiles]; ok {
|
||||||
binds, err := labelStructs.ConfigMapFileFrom(v)
|
binds, err := labelStructs.ConfigMapFileFrom(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
@@ -200,7 +201,7 @@ func (d *Deployment) AddVolumes(service types.ServiceConfig, appName string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isSamePod := false
|
isSamePod := false
|
||||||
if v, ok := service.Labels[LabelSamePod]; !ok {
|
if v, ok := service.Labels[labels.LabelSamePod]; !ok {
|
||||||
isSamePod = false
|
isSamePod = false
|
||||||
} else {
|
} else {
|
||||||
isSamePod = v != ""
|
isSamePod = v != ""
|
||||||
@@ -245,7 +246,12 @@ func (d *Deployment) DependsOn(to *Deployment, servicename string) error {
|
|||||||
for _, container := range to.Spec.Template.Spec.Containers {
|
for _, container := range to.Spec.Template.Spec.Containers {
|
||||||
commands := []string{}
|
commands := []string{}
|
||||||
if len(container.Ports) == 0 {
|
if len(container.Ports) == 0 {
|
||||||
utils.Warn("No ports found for service ", servicename, ". You should declare a port in the service or use "+LabelPorts+" label.")
|
utils.Warn("No ports found for service ",
|
||||||
|
servicename,
|
||||||
|
". You should declare a port in the service or use "+
|
||||||
|
labels.LabelPorts+
|
||||||
|
" label.",
|
||||||
|
)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
for _, port := range container.Ports {
|
for _, port := range container.Ports {
|
||||||
@@ -279,13 +285,13 @@ func (d *Deployment) SetEnvFrom(service types.ServiceConfig, appName string) {
|
|||||||
secrets := []string{}
|
secrets := []string{}
|
||||||
|
|
||||||
// secrets from label
|
// secrets from label
|
||||||
labelSecrets, err := labelStructs.SecretsFrom(service.Labels[LabelSecrets])
|
labelSecrets, err := labelStructs.SecretsFrom(service.Labels[labels.LabelSecrets])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// values from label
|
// values from label
|
||||||
varDescriptons := utils.GetValuesFromLabel(service, LabelValues)
|
varDescriptons := utils.GetValuesFromLabel(service, labels.LabelValues)
|
||||||
labelValues := []string{}
|
labelValues := []string{}
|
||||||
for v := range varDescriptons {
|
for v := range varDescriptons {
|
||||||
labelValues = append(labelValues, v)
|
labelValues = append(labelValues, v)
|
||||||
@@ -506,7 +512,7 @@ func (d *Deployment) Yaml() ([]byte, error) {
|
|||||||
|
|
||||||
// find the katenary.v3/node-selector line, and remove it
|
// find the katenary.v3/node-selector line, and remove it
|
||||||
for i, line := range content {
|
for i, line := range content {
|
||||||
if strings.Contains(line, labelName("node-selector")) {
|
if strings.Contains(line, labels.LabelName("node-selector")) {
|
||||||
content = append(content[:i], content[i+1:]...)
|
content = append(content[:i], content[i+1:]...)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -582,7 +588,7 @@ func (d *Deployment) bindVolumes(volume types.ServiceVolumeConfig, isSamePod boo
|
|||||||
utils.Warn(
|
utils.Warn(
|
||||||
"Bind volumes are not supported yet, " +
|
"Bind volumes are not supported yet, " +
|
||||||
"excepting for those declared as " +
|
"excepting for those declared as " +
|
||||||
LabelConfigMapFiles +
|
labels.LabelConfigMapFiles +
|
||||||
", skipping volume " + volume.Source +
|
", skipping volume " + volume.Source +
|
||||||
" from service " + service.Name,
|
" from service " + service.Name,
|
||||||
)
|
)
|
||||||
@@ -612,7 +618,7 @@ func (d *Deployment) bindVolumes(volume types.ServiceVolumeConfig, isSamePod boo
|
|||||||
})
|
})
|
||||||
// Add volume to values.yaml only if it the service is not in the same pod that another service.
|
// Add volume to values.yaml only if it the service is not in the same pod that another service.
|
||||||
// If it is in the same pod, the volume will be added to the other service later
|
// If it is in the same pod, the volume will be added to the other service later
|
||||||
if _, ok := service.Labels[LabelSamePod]; !ok {
|
if _, ok := service.Labels[labels.LabelSamePod]; !ok {
|
||||||
d.chart.Values[service.Name].(*Value).AddPersistence(volume.Source)
|
d.chart.Values[service.Name].(*Value).AddPersistence(volume.Source)
|
||||||
}
|
}
|
||||||
// Add volume to deployment
|
// Add volume to deployment
|
||||||
|
@@ -2,6 +2,7 @@ package generator
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"katenary/generator/labels"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -159,7 +160,7 @@ services:
|
|||||||
version: 18.x.X
|
version: 18.x.X
|
||||||
|
|
||||||
`
|
`
|
||||||
composeFile = fmt.Sprintf(composeFile, Prefix())
|
composeFile = fmt.Sprintf(composeFile, labels.Prefix())
|
||||||
tmpDir := setup(composeFile)
|
tmpDir := setup(composeFile)
|
||||||
defer teardown(tmpDir)
|
defer teardown(tmpDir)
|
||||||
|
|
||||||
@@ -249,7 +250,7 @@ services:
|
|||||||
path: /ready
|
path: /ready
|
||||||
port: 80
|
port: 80
|
||||||
`
|
`
|
||||||
composeFile = fmt.Sprintf(composeFile, Prefix())
|
composeFile = fmt.Sprintf(composeFile, labels.Prefix())
|
||||||
tmpDir := setup(composeFile)
|
tmpDir := setup(composeFile)
|
||||||
defer teardown(tmpDir)
|
defer teardown(tmpDir)
|
||||||
|
|
||||||
@@ -295,7 +296,7 @@ services:
|
|||||||
- FOO
|
- FOO
|
||||||
`
|
`
|
||||||
|
|
||||||
composeFile = fmt.Sprintf(composeFile, Prefix())
|
composeFile = fmt.Sprintf(composeFile, labels.Prefix())
|
||||||
tmpDir := setup(composeFile)
|
tmpDir := setup(composeFile)
|
||||||
defer teardown(tmpDir)
|
defer teardown(tmpDir)
|
||||||
|
|
||||||
|
@@ -3,6 +3,7 @@ package generator
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"katenary/generator/labels"
|
||||||
"katenary/utils"
|
"katenary/utils"
|
||||||
"log"
|
"log"
|
||||||
"regexp"
|
"regexp"
|
||||||
@@ -39,7 +40,7 @@ func Generate(project *types.Project) (*HelmChart, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
Annotations[labelName("compose-hash")] = hash
|
Annotations[labels.LabelName("compose-hash")] = hash
|
||||||
chart.composeHash = &hash
|
chart.composeHash = &hash
|
||||||
|
|
||||||
// find the "main-app" label, and set chart.AppVersion to the tag if exists
|
// find the "main-app" label, and set chart.AppVersion to the tag if exists
|
||||||
@@ -81,14 +82,14 @@ func Generate(project *types.Project) (*HelmChart, error) {
|
|||||||
// drop all "same-pod" deployments because the containers and volumes are already
|
// drop all "same-pod" deployments because the containers and volumes are already
|
||||||
// in the target deployment
|
// in the target deployment
|
||||||
for _, service := range podToMerge {
|
for _, service := range podToMerge {
|
||||||
if samepod, ok := service.Labels[LabelSamePod]; ok && samepod != "" {
|
if samepod, ok := service.Labels[labels.LabelSamePod]; ok && samepod != "" {
|
||||||
// move this deployment volumes to the target deployment
|
// move this deployment volumes to the target deployment
|
||||||
if target, ok := deployments[samepod]; ok {
|
if target, ok := deployments[samepod]; ok {
|
||||||
target.AddContainer(*service)
|
target.AddContainer(*service)
|
||||||
target.BindFrom(*service, deployments[service.Name])
|
target.BindFrom(*service, deployments[service.Name])
|
||||||
delete(deployments, service.Name)
|
delete(deployments, service.Name)
|
||||||
} else {
|
} else {
|
||||||
log.Printf("service %[1]s is declared as %[2]s, but %[2]s is not defined", service.Name, LabelSamePod)
|
log.Printf("service %[1]s is declared as %[2]s, but %[2]s is not defined", service.Name, labels.LabelSamePod)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -163,7 +164,7 @@ func Generate(project *types.Project) (*HelmChart, error) {
|
|||||||
|
|
||||||
// serviceIsMain returns true if the service is the main app.
|
// serviceIsMain returns true if the service is the main app.
|
||||||
func serviceIsMain(service types.ServiceConfig) bool {
|
func serviceIsMain(service types.ServiceConfig) bool {
|
||||||
if main, ok := service.Labels[LabelMainApp]; ok {
|
if main, ok := service.Labels[labels.LabelMainApp]; ok {
|
||||||
return main == "true" || main == "yes" || main == "1"
|
return main == "true" || main == "yes" || main == "1"
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@@ -276,7 +277,7 @@ func buildVolumes(service types.ServiceConfig, chart *HelmChart, deployments map
|
|||||||
|
|
||||||
// if the service is integrated in another deployment, we need to add the volume
|
// if the service is integrated in another deployment, we need to add the volume
|
||||||
// to the target deployment
|
// to the target deployment
|
||||||
if override, ok := service.Labels[LabelSamePod]; ok {
|
if override, ok := service.Labels[labels.LabelSamePod]; ok {
|
||||||
pvc.nameOverride = override
|
pvc.nameOverride = override
|
||||||
pvc.Spec.StorageClassName = utils.StrPtr(`{{ .Values.` + override + `.persistence.` + v.Source + `.storageClass }}`)
|
pvc.Spec.StorageClassName = utils.StrPtr(`{{ .Values.` + override + `.persistence.` + v.Source + `.storageClass }}`)
|
||||||
chart.Values[override].(*Value).AddPersistence(v.Source)
|
chart.Values[override].(*Value).AddPersistence(v.Source)
|
||||||
@@ -308,7 +309,7 @@ func samePodVolume(service types.ServiceConfig, v types.ServiceVolumeConfig, dep
|
|||||||
}
|
}
|
||||||
|
|
||||||
targetDeployment := ""
|
targetDeployment := ""
|
||||||
if targetName, ok := service.Labels[LabelSamePod]; !ok {
|
if targetName, ok := service.Labels[labels.LabelSamePod]; !ok {
|
||||||
return false
|
return false
|
||||||
} else {
|
} else {
|
||||||
targetDeployment = targetName
|
targetDeployment = targetName
|
||||||
|
@@ -1,6 +1,9 @@
|
|||||||
package generator
|
package generator
|
||||||
|
|
||||||
import "regexp"
|
import (
|
||||||
|
"katenary/generator/labels"
|
||||||
|
"regexp"
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// find all labels starting by __replace_ and ending with ":"
|
// find all labels starting by __replace_ and ending with ":"
|
||||||
@@ -11,6 +14,6 @@ var (
|
|||||||
|
|
||||||
// Standard annotationss
|
// Standard annotationss
|
||||||
Annotations = map[string]string{
|
Annotations = map[string]string{
|
||||||
labelName("version"): Version,
|
labels.LabelName("version"): Version,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@@ -2,6 +2,7 @@ package generator
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
_ "embed"
|
_ "embed"
|
||||||
|
"katenary/generator/labels"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -13,7 +14,7 @@ var helmHelper string
|
|||||||
// Helper returns the _helpers.tpl file for a chart.
|
// Helper returns the _helpers.tpl file for a chart.
|
||||||
func Helper(name string) string {
|
func Helper(name string) string {
|
||||||
helmHelper := strings.ReplaceAll(helmHelper, "__APP__", name)
|
helmHelper := strings.ReplaceAll(helmHelper, "__APP__", name)
|
||||||
helmHelper = strings.ReplaceAll(helmHelper, "__PREFIX__", katenaryLabelPrefix)
|
helmHelper = strings.ReplaceAll(helmHelper, "__PREFIX__", labels.KatenaryLabelPrefix)
|
||||||
helmHelper = strings.ReplaceAll(helmHelper, "__VERSION__", "0.1.0")
|
helmHelper = strings.ReplaceAll(helmHelper, "__VERSION__", "0.1.0")
|
||||||
return helmHelper
|
return helmHelper
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
package generator
|
package generator
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"katenary/generator/labelStructs"
|
"katenary/generator/labels"
|
||||||
|
"katenary/generator/labels/labelStructs"
|
||||||
"katenary/utils"
|
"katenary/utils"
|
||||||
"log"
|
"log"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -27,7 +28,7 @@ func NewIngress(service types.ServiceConfig, Chart *HelmChart) *Ingress {
|
|||||||
}
|
}
|
||||||
var label string
|
var label string
|
||||||
var ok bool
|
var ok bool
|
||||||
if label, ok = service.Labels[LabelIngress]; !ok {
|
if label, ok = service.Labels[labels.LabelIngress]; !ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2,6 +2,7 @@ package generator
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"katenary/generator/labels"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -22,7 +23,7 @@ services:
|
|||||||
hostname: my.test.tld
|
hostname: my.test.tld
|
||||||
port: 80
|
port: 80
|
||||||
`
|
`
|
||||||
composeFile = fmt.Sprintf(composeFile, katenaryLabelPrefix)
|
composeFile = fmt.Sprintf(composeFile, labels.KatenaryLabelPrefix)
|
||||||
tmpDir := setup(composeFile)
|
tmpDir := setup(composeFile)
|
||||||
defer teardown(tmpDir)
|
defer teardown(tmpDir)
|
||||||
|
|
||||||
|
10
generator/katenaryfile/doc.go
Normal file
10
generator/katenaryfile/doc.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
/*
|
||||||
|
Package katenaryfile is a package for reading and writing katenary files.
|
||||||
|
|
||||||
|
A katenary file, named "katenary.yml" or "katenary.yaml", is a file where you can define the
|
||||||
|
configuration of the conversion avoiding the use of labels in the compose file.
|
||||||
|
|
||||||
|
Formely, the file describe the same structure as in labels, and so that can be validated and
|
||||||
|
completed by LSP. It also ease the use of katenary.
|
||||||
|
*/
|
||||||
|
package katenaryfile
|
142
generator/katenaryfile/main.go
Normal file
142
generator/katenaryfile/main.go
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
package katenaryfile
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"katenary/generator/labels"
|
||||||
|
"katenary/generator/labels/labelStructs"
|
||||||
|
"katenary/utils"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/compose-spec/compose-go/types"
|
||||||
|
"github.com/invopop/jsonschema"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
var allowedKatenaryYamlFileNames = []string{"katenary.yaml", "katenary.yml"}
|
||||||
|
|
||||||
|
// StringOrMap is a struct that can be either a string or a map of strings.
|
||||||
|
// It's a helper struct to unmarshal the katenary.yaml file and produce the schema
|
||||||
|
type StringOrMap any
|
||||||
|
|
||||||
|
// Service is a struct that contains the service configuration for katenary
|
||||||
|
type Service struct {
|
||||||
|
MainApp *bool `json:"main-app,omitempty" jsonschema:"title=Is this service the main application"`
|
||||||
|
Values []StringOrMap `json:"values,omitempty" jsonschema:"description=Environment variables to be set in values.yaml with or without a description"`
|
||||||
|
Secrets *labelStructs.Secrets `json:"secrets,omitempty" jsonschema:"title=Secrets,description=Environment variables to be set as secrets"`
|
||||||
|
Ports *labelStructs.Ports `json:"ports,omitempty" jsonschema:"title=Ports,description=Ports to be exposed in services"`
|
||||||
|
Ingress *labelStructs.Ingress `json:"ingress,omitempty" jsonschema:"title=Ingress,description=Ingress configuration"`
|
||||||
|
HealthCheck *labelStructs.HealthCheck `json:"health-check,omitempty" jsonschema:"title=Health Check,description=Health check configuration that respects the kubernetes api"`
|
||||||
|
SamePod *string `json:"same-pod,omitempty" jsonschema:"title=Same Pod,description=Service that should be in the same pod"`
|
||||||
|
Description *string `json:"description,omitempty" jsonschema:"title=Description,description=Description of the service that will be injected in the values.yaml file"`
|
||||||
|
Ignore *bool `json:"ignore,omitempty" jsonschema:"title=Ignore,description=Ignore the service in the conversion"`
|
||||||
|
Dependencies []labelStructs.Dependency `json:"dependencies,omitempty" jsonschema:"title=Dependencies,description=Services that should be injected in the Chart.yaml file"`
|
||||||
|
ConfigMapFile *labelStructs.ConfigMapFile `json:"configmap-files,omitempty" jsonschema:"title=ConfigMap Files,description=Files that should be injected as ConfigMap"`
|
||||||
|
MapEnv *labelStructs.MapEnv `json:"map-env,omitempty" jsonschema:"title=Map Env,description=Map environment variables to another value"`
|
||||||
|
CronJob *labelStructs.CronJob `json:"cron-job,omitempty" jsonschema:"title=Cron Job,description=Cron Job configuration"`
|
||||||
|
EnvFrom *labelStructs.EnvFrom `json:"env-from,omitempty" jsonschema:"title=Env From,description=Inject environment variables from another service"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// OverrideWithConfig overrides the project with the katenary.yaml file. It
|
||||||
|
// will set the labels of the services with the values from the katenary.yaml file.
|
||||||
|
// It work in memory, so it will not modify the original project.
|
||||||
|
func OverrideWithConfig(project *types.Project) {
|
||||||
|
var yamlFile string
|
||||||
|
var err error
|
||||||
|
for _, yamlFile = range allowedKatenaryYamlFileNames {
|
||||||
|
_, err = os.Stat(yamlFile)
|
||||||
|
if err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
// no katenary file found
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Println(utils.IconInfo, "Using katenary file", yamlFile)
|
||||||
|
|
||||||
|
services := make(map[string]Service)
|
||||||
|
fp, err := os.Open(yamlFile)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := yaml.NewDecoder(fp).Decode(&services); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for i, p := range project.Services {
|
||||||
|
name := p.Name
|
||||||
|
if project.Services[i].Labels == nil {
|
||||||
|
project.Services[i].Labels = make(map[string]string)
|
||||||
|
}
|
||||||
|
|
||||||
|
if s, ok := services[name]; ok {
|
||||||
|
getLabelContent(s.MainApp, &project.Services[i], labels.LabelMainApp)
|
||||||
|
getLabelContent(s.Values, &project.Services[i], labels.LabelValues)
|
||||||
|
getLabelContent(s.Secrets, &project.Services[i], labels.LabelSecrets)
|
||||||
|
getLabelContent(s.Ports, &project.Services[i], labels.LabelPorts)
|
||||||
|
getLabelContent(s.Ingress, &project.Services[i], labels.LabelIngress)
|
||||||
|
getLabelContent(s.HealthCheck, &project.Services[i], labels.LabelHealthCheck)
|
||||||
|
getLabelContent(s.SamePod, &project.Services[i], labels.LabelSamePod)
|
||||||
|
getLabelContent(s.Description, &project.Services[i], labels.LabelDescription)
|
||||||
|
getLabelContent(s.Ignore, &project.Services[i], labels.LabelIgnore)
|
||||||
|
getLabelContent(s.Dependencies, &project.Services[i], labels.LabelDependencies)
|
||||||
|
getLabelContent(s.ConfigMapFile, &project.Services[i], labels.LabelConfigMapFiles)
|
||||||
|
getLabelContent(s.MapEnv, &project.Services[i], labels.LabelMapEnv)
|
||||||
|
getLabelContent(s.CronJob, &project.Services[i], labels.LabelCronJob)
|
||||||
|
getLabelContent(s.EnvFrom, &project.Services[i], labels.LabelEnvFrom)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println(utils.IconInfo, "Katenary file loaded successfully, the services are now configured.")
|
||||||
|
}
|
||||||
|
|
||||||
|
func getLabelContent(o any, service *types.ServiceConfig, labelName string) error {
|
||||||
|
if reflect.ValueOf(o).IsZero() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := yaml.Marshal(o)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
val := strings.TrimSpace(string(c))
|
||||||
|
|
||||||
|
service.Labels[labelName] = val
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenerateSchema generates the schema for the katenary.yaml file.
|
||||||
|
func GenerateSchema() string {
|
||||||
|
s := jsonschema.Reflect(map[string]Service{})
|
||||||
|
|
||||||
|
// redefine the IntOrString type from k8s
|
||||||
|
s.Definitions["IntOrString"] = &jsonschema.Schema{
|
||||||
|
OneOf: []*jsonschema.Schema{
|
||||||
|
{Type: "integer"},
|
||||||
|
{Type: "string"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// same for the StringOrMap type, that can be either a string or a map of string:string
|
||||||
|
s.Definitions["StringOrMap"] = &jsonschema.Schema{
|
||||||
|
OneOf: []*jsonschema.Schema{
|
||||||
|
{Type: "string"},
|
||||||
|
{Type: "object", AdditionalProperties: &jsonschema.Schema{Type: "string"}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
c, _ := s.MarshalJSON()
|
||||||
|
// indent the json
|
||||||
|
var out bytes.Buffer
|
||||||
|
err := json.Indent(&out, c, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(out.Bytes())
|
||||||
|
}
|
@@ -1,33 +0,0 @@
|
|||||||
package labelStructs
|
|
||||||
|
|
||||||
import "gopkg.in/yaml.v3"
|
|
||||||
|
|
||||||
type TLS struct {
|
|
||||||
Enabled bool `yaml:"enabled"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Ingress struct {
|
|
||||||
Port *int32 `yaml:"port,omitempty"`
|
|
||||||
Annotations map[string]string `yaml:"annotations,omitempty"`
|
|
||||||
Hostname string `yaml:"hostname"`
|
|
||||||
Path string `yaml:"path"`
|
|
||||||
Class string `yaml:"class"`
|
|
||||||
Enabled bool `yaml:"enabled"`
|
|
||||||
TLS TLS `yaml:"tls"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// IngressFrom creates a new Ingress from a compose service.
|
|
||||||
func IngressFrom(data string) (*Ingress, error) {
|
|
||||||
mapping := Ingress{
|
|
||||||
Hostname: "",
|
|
||||||
Path: "/",
|
|
||||||
Enabled: false,
|
|
||||||
Class: "-",
|
|
||||||
Port: nil,
|
|
||||||
TLS: TLS{Enabled: true},
|
|
||||||
}
|
|
||||||
if err := yaml.Unmarshal([]byte(data), &mapping); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &mapping, nil
|
|
||||||
}
|
|
@@ -2,9 +2,10 @@ package generator
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"katenary/generator/labels"
|
||||||
)
|
)
|
||||||
|
|
||||||
var componentLabel = labelName("component")
|
var componentLabel = labels.LabelName("component")
|
||||||
|
|
||||||
// GetLabels returns the labels for a service. It uses the appName to replace the __replace__ in the labels.
|
// GetLabels returns the labels for a service. It uses the appName to replace the __replace__ in the labels.
|
||||||
// This is used to generate the labels in the templates.
|
// This is used to generate the labels in the templates.
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
package generator
|
package labels
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@@ -14,24 +14,24 @@ import (
|
|||||||
"sigs.k8s.io/yaml"
|
"sigs.k8s.io/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
const katenaryLabelPrefix = "katenary.v3"
|
const KatenaryLabelPrefix = "katenary.v3"
|
||||||
|
|
||||||
// Known labels.
|
// Known labels.
|
||||||
const (
|
const (
|
||||||
LabelMainApp Label = katenaryLabelPrefix + "/main-app"
|
LabelMainApp Label = KatenaryLabelPrefix + "/main-app"
|
||||||
LabelValues Label = katenaryLabelPrefix + "/values"
|
LabelValues Label = KatenaryLabelPrefix + "/values"
|
||||||
LabelSecrets Label = katenaryLabelPrefix + "/secrets"
|
LabelSecrets Label = KatenaryLabelPrefix + "/secrets"
|
||||||
LabelPorts Label = katenaryLabelPrefix + "/ports"
|
LabelPorts Label = KatenaryLabelPrefix + "/ports"
|
||||||
LabelIngress Label = katenaryLabelPrefix + "/ingress"
|
LabelIngress Label = KatenaryLabelPrefix + "/ingress"
|
||||||
LabelMapEnv Label = katenaryLabelPrefix + "/map-env"
|
LabelMapEnv Label = KatenaryLabelPrefix + "/map-env"
|
||||||
LabelHealthCheck Label = katenaryLabelPrefix + "/health-check"
|
LabelHealthCheck Label = KatenaryLabelPrefix + "/health-check"
|
||||||
LabelSamePod Label = katenaryLabelPrefix + "/same-pod"
|
LabelSamePod Label = KatenaryLabelPrefix + "/same-pod"
|
||||||
LabelDescription Label = katenaryLabelPrefix + "/description"
|
LabelDescription Label = KatenaryLabelPrefix + "/description"
|
||||||
LabelIgnore Label = katenaryLabelPrefix + "/ignore"
|
LabelIgnore Label = KatenaryLabelPrefix + "/ignore"
|
||||||
LabelDependencies Label = katenaryLabelPrefix + "/dependencies"
|
LabelDependencies Label = KatenaryLabelPrefix + "/dependencies"
|
||||||
LabelConfigMapFiles Label = katenaryLabelPrefix + "/configmap-files"
|
LabelConfigMapFiles Label = KatenaryLabelPrefix + "/configmap-files"
|
||||||
LabelCronJob Label = katenaryLabelPrefix + "/cronjob"
|
LabelCronJob Label = KatenaryLabelPrefix + "/cronjob"
|
||||||
LabelEnvFrom Label = katenaryLabelPrefix + "/env-from"
|
LabelEnvFrom Label = KatenaryLabelPrefix + "/env-from"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -47,8 +47,8 @@ var (
|
|||||||
// Label is a katenary label to find in compose files.
|
// Label is a katenary label to find in compose files.
|
||||||
type Label = string
|
type Label = string
|
||||||
|
|
||||||
func labelName(name string) Label {
|
func LabelName(name string) Label {
|
||||||
return Label(katenaryLabelPrefix + "/" + name)
|
return Label(KatenaryLabelPrefix + "/" + name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Help is the documentation of a label.
|
// Help is the documentation of a label.
|
||||||
@@ -114,7 +114,7 @@ func GetLabelHelpFor(labelname string, asMarkdown bool) string {
|
|||||||
template.Must(template.New("shorthelp").Parse(help.Long)).Execute(&buf, struct {
|
template.Must(template.New("shorthelp").Parse(help.Long)).Execute(&buf, struct {
|
||||||
KatenaryPrefix string
|
KatenaryPrefix string
|
||||||
}{
|
}{
|
||||||
KatenaryPrefix: katenaryLabelPrefix,
|
KatenaryPrefix: KatenaryLabelPrefix,
|
||||||
})
|
})
|
||||||
help.Long = buf.String()
|
help.Long = buf.String()
|
||||||
buf.Reset()
|
buf.Reset()
|
||||||
@@ -122,7 +122,7 @@ func GetLabelHelpFor(labelname string, asMarkdown bool) string {
|
|||||||
template.Must(template.New("example").Parse(help.Example)).Execute(&buf, struct {
|
template.Must(template.New("example").Parse(help.Example)).Execute(&buf, struct {
|
||||||
KatenaryPrefix string
|
KatenaryPrefix string
|
||||||
}{
|
}{
|
||||||
KatenaryPrefix: katenaryLabelPrefix,
|
KatenaryPrefix: KatenaryLabelPrefix,
|
||||||
})
|
})
|
||||||
help.Example = buf.String()
|
help.Example = buf.String()
|
||||||
buf.Reset()
|
buf.Reset()
|
||||||
@@ -134,7 +134,7 @@ func GetLabelHelpFor(labelname string, asMarkdown bool) string {
|
|||||||
}{
|
}{
|
||||||
Name: labelname,
|
Name: labelname,
|
||||||
Help: help,
|
Help: help,
|
||||||
KatenaryPrefix: katenaryLabelPrefix,
|
KatenaryPrefix: KatenaryLabelPrefix,
|
||||||
})
|
})
|
||||||
|
|
||||||
return buf.String()
|
return buf.String()
|
||||||
@@ -152,7 +152,7 @@ func generateMarkdownHelp(names []string) string {
|
|||||||
}
|
}
|
||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
help := labelFullHelp[name]
|
help := labelFullHelp[name]
|
||||||
maxNameLength = max(maxNameLength, len(name)+2+len(katenaryLabelPrefix))
|
maxNameLength = max(maxNameLength, len(name)+2+len(KatenaryLabelPrefix))
|
||||||
maxDescriptionLength = max(maxDescriptionLength, len(help.Short))
|
maxDescriptionLength = max(maxDescriptionLength, len(help.Short))
|
||||||
maxTypeLength = max(maxTypeLength, len(help.Type))
|
maxTypeLength = max(maxTypeLength, len(help.Type))
|
||||||
}
|
}
|
||||||
@@ -163,7 +163,7 @@ func generateMarkdownHelp(names []string) string {
|
|||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
help := labelFullHelp[name]
|
help := labelFullHelp[name]
|
||||||
fmt.Fprintf(&builder, "| %-*s | %-*s | %-*s |\n",
|
fmt.Fprintf(&builder, "| %-*s | %-*s | %-*s |\n",
|
||||||
maxNameLength, "`"+labelName(name)+"`", // enclose in backticks
|
maxNameLength, "`"+LabelName(name)+"`", // enclose in backticks
|
||||||
maxDescriptionLength, help.Short,
|
maxDescriptionLength, help.Short,
|
||||||
maxTypeLength, help.Type,
|
maxTypeLength, help.Type,
|
||||||
)
|
)
|
||||||
@@ -176,7 +176,7 @@ func generatePlainHelp(names []string) string {
|
|||||||
var builder strings.Builder
|
var builder strings.Builder
|
||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
help := labelFullHelp[name]
|
help := labelFullHelp[name]
|
||||||
fmt.Fprintf(&builder, "%s:\t%s\t%s\n", labelName(name), help.Type, help.Short)
|
fmt.Fprintf(&builder, "%s:\t%s\t%s\n", LabelName(name), help.Type, help.Short)
|
||||||
}
|
}
|
||||||
|
|
||||||
// use tabwriter to align the help text
|
// use tabwriter to align the help text
|
||||||
@@ -231,5 +231,5 @@ Example:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Prefix() string {
|
func Prefix() string {
|
||||||
return katenaryLabelPrefix
|
return KatenaryLabelPrefix
|
||||||
}
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
package generator
|
package labels
|
||||||
|
|
||||||
import (
|
import (
|
||||||
_ "embed"
|
_ "embed"
|
||||||
@@ -48,7 +48,7 @@ func TestLabelName(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
if got := labelName(tt.args.name); !reflect.DeepEqual(got, tt.want) {
|
if got := LabelName(tt.args.name); !reflect.DeepEqual(got, tt.want) {
|
||||||
t.Errorf("labelName() = %v, want %v", got, tt.want)
|
t.Errorf("labelName() = %v, want %v", got, tt.want)
|
||||||
}
|
}
|
||||||
})
|
})
|
@@ -3,10 +3,10 @@ package labelStructs
|
|||||||
import "gopkg.in/yaml.v3"
|
import "gopkg.in/yaml.v3"
|
||||||
|
|
||||||
type CronJob struct {
|
type CronJob struct {
|
||||||
Image string `yaml:"image,omitempty"`
|
Image string `yaml:"image,omitempty" json:"image,omitempty"`
|
||||||
Command string `yaml:"command"`
|
Command string `yaml:"command" json:"command,omitempty"`
|
||||||
Schedule string `yaml:"schedule"`
|
Schedule string `yaml:"schedule" json:"schedule,omitempty"`
|
||||||
Rbac bool `yaml:"rbac"`
|
Rbac bool `yaml:"rbac" json:"rbac,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func CronJobFrom(data string) (*CronJob, error) {
|
func CronJobFrom(data string) (*CronJob, error) {
|
@@ -4,11 +4,11 @@ import "gopkg.in/yaml.v3"
|
|||||||
|
|
||||||
// Dependency is a dependency of a chart to other charts.
|
// Dependency is a dependency of a chart to other charts.
|
||||||
type Dependency struct {
|
type Dependency struct {
|
||||||
Values map[string]any `yaml:"-"`
|
Values map[string]any `yaml:"-" json:"values,omitempty"`
|
||||||
Name string `yaml:"name"`
|
Name string `yaml:"name" json:"name"`
|
||||||
Version string `yaml:"version"`
|
Version string `yaml:"version" json:"version"`
|
||||||
Repository string `yaml:"repository"`
|
Repository string `yaml:"repository" json:"repository"`
|
||||||
Alias string `yaml:"alias,omitempty"`
|
Alias string `yaml:"alias,omitempty" json:"alias,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// DependenciesFrom returns a slice of dependencies from the given string.
|
// DependenciesFrom returns a slice of dependencies from the given string.
|
33
generator/labels/labelStructs/ingress.go
Normal file
33
generator/labels/labelStructs/ingress.go
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package labelStructs
|
||||||
|
|
||||||
|
import "gopkg.in/yaml.v3"
|
||||||
|
|
||||||
|
type TLS struct {
|
||||||
|
Enabled bool `yaml:"enabled" json:"enabled,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Ingress struct {
|
||||||
|
Port *int32 `yaml:"port,omitempty" jsonschema:"nullable" json:"port,omitempty"`
|
||||||
|
Annotations map[string]string `yaml:"annotations,omitempty" jsonschema:"nullable" json:"annotations,omitempty"`
|
||||||
|
Hostname string `yaml:"hostname" json:"hostname,omitempty"`
|
||||||
|
Path string `yaml:"path" json:"path,omitempty"`
|
||||||
|
Class string `yaml:"class" json:"class,omitempty" jsonschema:"default:-"`
|
||||||
|
Enabled bool `yaml:"enabled" json:"enabled,omitempty"`
|
||||||
|
TLS *TLS `yaml:"tls,omitempty" json:"tls,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// IngressFrom creates a new Ingress from a compose service.
|
||||||
|
func IngressFrom(data string) (*Ingress, error) {
|
||||||
|
mapping := Ingress{
|
||||||
|
Hostname: "",
|
||||||
|
Path: "/",
|
||||||
|
Enabled: false,
|
||||||
|
Class: "-",
|
||||||
|
Port: nil,
|
||||||
|
TLS: &TLS{Enabled: true},
|
||||||
|
}
|
||||||
|
if err := yaml.Unmarshal([]byte(data), &mapping); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &mapping, nil
|
||||||
|
}
|
@@ -8,13 +8,13 @@ import (
|
|||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Probe struct {
|
type HealthCheck struct {
|
||||||
LivenessProbe *corev1.Probe `yaml:"livenessProbe,omitempty"`
|
LivenessProbe *corev1.Probe `yaml:"livenessProbe,omitempty" json:"livenessProbe,omitempty"`
|
||||||
ReadinessProbe *corev1.Probe `yaml:"readinessProbe,omitempty"`
|
ReadinessProbe *corev1.Probe `yaml:"readinessProbe,omitempty" json:"readinessProbe,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func ProbeFrom(data string) (*Probe, error) {
|
func ProbeFrom(data string) (*HealthCheck, error) {
|
||||||
mapping := Probe{}
|
mapping := HealthCheck{}
|
||||||
tmp := map[string]any{}
|
tmp := map[string]any{}
|
||||||
err := yaml.Unmarshal([]byte(data), &tmp)
|
err := yaml.Unmarshal([]byte(data), &tmp)
|
||||||
if err != nil {
|
if err != nil {
|
@@ -3,6 +3,7 @@ package generator
|
|||||||
import (
|
import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"katenary/generator/labels"
|
||||||
"katenary/utils"
|
"katenary/utils"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -44,7 +45,7 @@ func NewSecret(service types.ServiceConfig, appName string) *Secret {
|
|||||||
|
|
||||||
// check if the value should be in values.yaml
|
// check if the value should be in values.yaml
|
||||||
valueList := []string{}
|
valueList := []string{}
|
||||||
varDescriptons := utils.GetValuesFromLabel(service, LabelValues)
|
varDescriptons := utils.GetValuesFromLabel(service, labels.LabelValues)
|
||||||
for value := range varDescriptons {
|
for value := range varDescriptons {
|
||||||
valueList = append(valueList, value)
|
valueList = append(valueList, value)
|
||||||
}
|
}
|
||||||
@@ -79,7 +80,15 @@ func (s *Secret) AddData(key, value string) {
|
|||||||
if value == "" {
|
if value == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.Data[key] = []byte(`{{ tpl ` + value + ` $ | b64enc }}`)
|
valuesLabels := utils.GetValuesFromLabel(s.service, labels.LabelValues)
|
||||||
|
if _, ok := valuesLabels[key]; ok {
|
||||||
|
// the value should be in values.yaml
|
||||||
|
s.Data[key] = []byte(`{{ tpl .Values.` + s.service.Name + `.environment.` + key + ` $ | b64enc }}`)
|
||||||
|
} else {
|
||||||
|
encoded := base64.StdEncoding.EncodeToString([]byte(value))
|
||||||
|
s.Data[key] = []byte(encoded)
|
||||||
|
}
|
||||||
|
// s.Data[key] = []byte(`{{ tpl ` + value + ` $ | b64enc }}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filename returns the filename of the secret.
|
// Filename returns the filename of the secret.
|
||||||
|
@@ -2,6 +2,7 @@ package generator
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"katenary/generator/labels"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -21,7 +22,7 @@ services:
|
|||||||
%s/secrets: |-
|
%s/secrets: |-
|
||||||
- BAR
|
- BAR
|
||||||
`
|
`
|
||||||
composeFile = fmt.Sprintf(composeFile, katenaryLabelPrefix)
|
composeFile = fmt.Sprintf(composeFile, labels.KatenaryLabelPrefix)
|
||||||
tmpDir := setup(composeFile)
|
tmpDir := setup(composeFile)
|
||||||
defer teardown(tmpDir)
|
defer teardown(tmpDir)
|
||||||
|
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
package generator
|
package generator
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"katenary/generator/labelStructs"
|
"katenary/generator/labels"
|
||||||
|
"katenary/generator/labels/labelStructs"
|
||||||
"katenary/utils"
|
"katenary/utils"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -46,7 +47,7 @@ func fixPorts(service *types.ServiceConfig) error {
|
|||||||
// check the "ports" label from container and add it to the service
|
// check the "ports" label from container and add it to the service
|
||||||
portsLabel := ""
|
portsLabel := ""
|
||||||
ok := false
|
ok := false
|
||||||
if portsLabel, ok = service.Labels[LabelPorts]; !ok {
|
if portsLabel, ok = service.Labels[labels.LabelPorts]; !ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
ports, err := labelStructs.PortsFrom(portsLabel)
|
ports, err := labelStructs.PortsFrom(portsLabel)
|
||||||
@@ -75,7 +76,7 @@ func fixPorts(service *types.ServiceConfig) error {
|
|||||||
|
|
||||||
// isIgnored returns true if the service is ignored.
|
// isIgnored returns true if the service is ignored.
|
||||||
func isIgnored(service types.ServiceConfig) bool {
|
func isIgnored(service types.ServiceConfig) bool {
|
||||||
if v, ok := service.Labels[LabelIgnore]; ok {
|
if v, ok := service.Labels[labels.LabelIgnore]; ok {
|
||||||
return v == "true" || v == "yes" || v == "1"
|
return v == "true" || v == "yes" || v == "1"
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
@@ -2,6 +2,7 @@ package generator
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"katenary/generator/labels"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -52,7 +53,7 @@ services:
|
|||||||
%s/configmap-files: |-
|
%s/configmap-files: |-
|
||||||
- ./static
|
- ./static
|
||||||
`
|
`
|
||||||
composeFile = fmt.Sprintf(composeFile, katenaryLabelPrefix)
|
composeFile = fmt.Sprintf(composeFile, labels.KatenaryLabelPrefix)
|
||||||
tmpDir := setup(composeFile)
|
tmpDir := setup(composeFile)
|
||||||
defer teardown(tmpDir)
|
defer teardown(tmpDir)
|
||||||
|
|
||||||
@@ -112,7 +113,7 @@ services:
|
|||||||
%s/configmap-files: |-
|
%s/configmap-files: |-
|
||||||
- ./static/index.html
|
- ./static/index.html
|
||||||
`
|
`
|
||||||
composeFile = fmt.Sprintf(composeFile, katenaryLabelPrefix)
|
composeFile = fmt.Sprintf(composeFile, labels.KatenaryLabelPrefix)
|
||||||
tmpDir := setup(composeFile)
|
tmpDir := setup(composeFile)
|
||||||
defer teardown(tmpDir)
|
defer teardown(tmpDir)
|
||||||
|
|
||||||
@@ -169,7 +170,7 @@ volumes:
|
|||||||
data:
|
data:
|
||||||
`
|
`
|
||||||
|
|
||||||
composeFile = fmt.Sprintf(composeFile, katenaryLabelPrefix)
|
composeFile = fmt.Sprintf(composeFile, labels.KatenaryLabelPrefix)
|
||||||
tmpDir := setup(composeFile)
|
tmpDir := setup(composeFile)
|
||||||
defer teardown(tmpDir)
|
defer teardown(tmpDir)
|
||||||
|
|
||||||
|
5
go.mod
5
go.mod
@@ -6,6 +6,7 @@ toolchain go1.23.2
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/compose-spec/compose-go v1.20.2
|
github.com/compose-spec/compose-go v1.20.2
|
||||||
|
github.com/invopop/jsonschema v0.12.0
|
||||||
github.com/mitchellh/go-wordwrap v1.0.1
|
github.com/mitchellh/go-wordwrap v1.0.1
|
||||||
github.com/spf13/cobra v1.8.1
|
github.com/spf13/cobra v1.8.1
|
||||||
github.com/thediveo/netdb v1.1.2
|
github.com/thediveo/netdb v1.1.2
|
||||||
@@ -17,6 +18,8 @@ require (
|
|||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/bahlo/generic-list-go v0.2.0 // indirect
|
||||||
|
github.com/buger/jsonparser v1.1.1 // indirect
|
||||||
github.com/distribution/reference v0.6.0 // indirect
|
github.com/distribution/reference v0.6.0 // indirect
|
||||||
github.com/docker/go-connections v0.5.0 // indirect
|
github.com/docker/go-connections v0.5.0 // indirect
|
||||||
github.com/docker/go-units v0.5.0 // indirect
|
github.com/docker/go-units v0.5.0 // indirect
|
||||||
@@ -27,6 +30,7 @@ require (
|
|||||||
github.com/imdario/mergo v0.3.16 // indirect
|
github.com/imdario/mergo v0.3.16 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
|
github.com/mailru/easyjson v0.7.7 // indirect
|
||||||
github.com/mattn/go-shellwords v1.0.12 // indirect
|
github.com/mattn/go-shellwords v1.0.12 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
@@ -35,6 +39,7 @@ require (
|
|||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
|
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
|
||||||
github.com/x448/float16 v0.8.4 // indirect
|
github.com/x448/float16 v0.8.4 // indirect
|
||||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||||
|
11
go.sum
11
go.sum
@@ -1,3 +1,7 @@
|
|||||||
|
github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
|
||||||
|
github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
|
||||||
|
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
|
||||||
|
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
|
||||||
github.com/compose-spec/compose-go v1.20.2 h1:u/yfZHn4EaHGdidrZycWpxXgFffjYULlTbRfJ51ykjQ=
|
github.com/compose-spec/compose-go v1.20.2 h1:u/yfZHn4EaHGdidrZycWpxXgFffjYULlTbRfJ51ykjQ=
|
||||||
github.com/compose-spec/compose-go v1.20.2/go.mod h1:+MdqXV4RA7wdFsahh/Kb8U0pAJqkg7mr4PM9tFKU8RM=
|
github.com/compose-spec/compose-go v1.20.2/go.mod h1:+MdqXV4RA7wdFsahh/Kb8U0pAJqkg7mr4PM9tFKU8RM=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
@@ -32,6 +36,9 @@ github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
|
|||||||
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
|
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
|
github.com/invopop/jsonschema v0.12.0 h1:6ovsNSuvn9wEQVOyc72aycBMVQFKz7cPdMJn10CvzRI=
|
||||||
|
github.com/invopop/jsonschema v0.12.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0=
|
||||||
|
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||||
@@ -40,6 +47,8 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
|||||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
|
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||||
|
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||||
github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk=
|
github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk=
|
||||||
github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
|
github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
|
||||||
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
|
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
|
||||||
@@ -78,6 +87,8 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT
|
|||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/thediveo/netdb v1.1.2 h1:XdLx/YJPutxrSkPYtmCAIY5sgAvxtkS1Tz+Z0UX2I+U=
|
github.com/thediveo/netdb v1.1.2 h1:XdLx/YJPutxrSkPYtmCAIY5sgAvxtkS1Tz+Z0UX2I+U=
|
||||||
github.com/thediveo/netdb v1.1.2/go.mod h1:KJczM//7VIIiovQO1qDooHvM8+0pt6RdRt3rVDZxEGM=
|
github.com/thediveo/netdb v1.1.2/go.mod h1:KJczM//7VIIiovQO1qDooHvM8+0pt6RdRt3rVDZxEGM=
|
||||||
|
github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc=
|
||||||
|
github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw=
|
||||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||||
|
Reference in New Issue
Block a user