diff --git a/.github/workflows/go-test.yaml b/.github/workflows/go-test.yaml
index 4b43eed..dc99fbf 100644
--- a/.github/workflows/go-test.yaml
+++ b/.github/workflows/go-test.yaml
@@ -2,12 +2,15 @@ name: Go-Tests
on:
pull_request:
+ types: [opened, synchronize, reopened]
branches:
- develop
push:
branches:
- master
+ - main
- develop
+ - 'releases/**'
jobs:
tests:
runs-on: ubuntu-latest
@@ -16,12 +19,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
- go-version: 1.23
- - name: Install Helm
- run: |
- curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3
- chmod 700 get_helm.sh
- ./get_helm.sh
+ go-version: 1.24
- name: Launch Test
run: |
go mod tidy
@@ -33,15 +31,18 @@ jobs:
coverprofile.out
gotest.json
sonar:
+ permissions:
+ contents: read
+ pull-requests: read
runs-on: ubuntu-latest
needs: tests
steps:
- - uses: actions/checkout@v4
- - uses: actions/download-artifact@v4
- with:
- name: tests-results
- - name: SonarCloud Scan
- uses: SonarSource/sonarcloud-github-action@master
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
+ - uses: actions/checkout@v4
+ - uses: actions/download-artifact@v4
+ with:
+ name: tests-results
+ - name: SonarQube Scan
+ uses: SonarSource/sonarqube-scan-action@v5.2.0
+ env:
+ SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
+ SONAR_HOST_URL: ${{ vars.SONAR_HOST_URL }}
diff --git a/Makefile b/Makefile
index 104a800..2fe526b 100644
--- a/Makefile
+++ b/Makefile
@@ -242,3 +242,16 @@ __label_doc:
gomarkdoc --repository.default-branch $(shell git branch --show-current) -o doc/docs/packages/$$pack.md $$pack
sed -i '/^## Index/,/^##/ { /## Index/d; /^##/! d }' doc/docs/packages/$$pack.md
done
+
+
+# Scan the source code.
+# - we don't need detection of text/template as it's not a web application, and
+# - we don't need sha1 detection as it is not used for cryptographic purposes.
+# Note: metrics are actually not sent to anyone - it's a thing that is removed from the code in the future.
+sast:
+ opengrep \
+ --config auto \
+ --exclude-rule go.lang.security.audit.xss.import-text-template.import-text-template \
+ --exclude-rule go.lang.security.audit.crypto.use_of_weak_crypto.use-of-sha1 \
+ --metrics=on \
+ .
diff --git a/cmd/katenary/main.go b/cmd/katenary/main.go
index 3276d31..f2810aa 100644
--- a/cmd/katenary/main.go
+++ b/cmd/katenary/main.go
@@ -146,7 +146,7 @@ func generateConvertCommand() *cobra.Command {
Use: "convert",
Short: "Converts a docker-compose file to a Helm Chart",
RunE: func(cmd *cobra.Command, args []string) error {
- if givenAppVersion != "" {
+ if len(strings.TrimSpace(givenAppVersion)) > 0 {
appVersion = &givenAppVersion
}
return generator.Convert(generator.ConvertOptions{
diff --git a/doc/docs/packages/generator.md b/doc/docs/packages/generator.md
index a761861..9b029da 100644
--- a/doc/docs/packages/generator.md
+++ b/doc/docs/packages/generator.md
@@ -465,7 +465,7 @@ type HelmChart struct {
AppVersion string `yaml:"appVersion"`
Description string `yaml:"description"`
Helper string `yaml:"-"`
- Dependencies []labelStructs.Dependency `yaml:"dependencies,omitempty"`
+ Dependencies []labelstructs.Dependency `yaml:"dependencies,omitempty"`
// contains filtered or unexported fields
}
```
diff --git a/doc/docs/packages/generator/katenaryfile.md b/doc/docs/packages/generator/katenaryfile.md
index 3e1d02e..a2a1824 100644
--- a/doc/docs/packages/generator/katenaryfile.md
+++ b/doc/docs/packages/generator/katenaryfile.md
@@ -38,20 +38,20 @@ 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"`
+ 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"`
- ExchangeVolumes []*labelStructs.ExchangeVolume `json:"exchange-volumes,omitempty" jsonschema:"title=Exchange Volumes,description=Exchange volumes between services"`
- ValuesFrom *labelStructs.ValueFrom `json:"values-from,omitempty" jsonschema:"title=Values From,description=Inject values from another service (secret or configmap environment variables)"`
+ 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"`
+ ExchangeVolumes []*labelstructs.ExchangeVolume `json:"exchange-volumes,omitempty" jsonschema:"title=Exchange Volumes,description=Exchange volumes between services"`
+ ValuesFrom *labelstructs.ValueFrom `json:"values-from,omitempty" jsonschema:"title=Values From,description=Inject values from another service (secret or configmap environment variables)"`
}
```
diff --git a/doc/docs/packages/generator/labels.md b/doc/docs/packages/generator/labels.md
index c990ce8..9728333 100644
--- a/doc/docs/packages/generator/labels.md
+++ b/doc/docs/packages/generator/labels.md
@@ -6,6 +6,8 @@
import "katenary/generator/labels"
```
+Package labels provides functionality to parse and manipulate labels.
+
## Constants
@@ -21,7 +23,7 @@ const KatenaryLabelPrefix = "katenary.v3"
func GetLabelHelp(asMarkdown bool) string
```
-Generate the help for the labels.
+GetLabelHelp return the help for the labels.
## func [GetLabelHelpFor]()
diff --git a/doc/docs/packages/generator/labels/labelstructs.md b/doc/docs/packages/generator/labels/labelstructs.md
new file mode 100644
index 0000000..9170aa6
--- /dev/null
+++ b/doc/docs/packages/generator/labels/labelstructs.md
@@ -0,0 +1,246 @@
+
+
+# labelstructs
+
+```go
+import "katenary/generator/labels/labelstructs"
+```
+
+Package labelstructs is a package that contains the structs used to represent the labels in the yaml files.
+
+## type [ConfigMapFile]()
+
+
+
+```go
+type ConfigMapFile []string
+```
+
+
+### func [ConfigMapFileFrom]()
+
+```go
+func ConfigMapFileFrom(data string) (ConfigMapFile, error)
+```
+
+
+
+
+## type [CronJob]()
+
+
+
+```go
+type CronJob struct {
+ Image string `yaml:"image,omitempty" json:"image,omitempty"`
+ Command string `yaml:"command" json:"command,omitempty"`
+ Schedule string `yaml:"schedule" json:"schedule,omitempty"`
+ Rbac bool `yaml:"rbac" json:"rbac,omitempty"`
+}
+```
+
+
+### func [CronJobFrom]()
+
+```go
+func CronJobFrom(data string) (*CronJob, error)
+```
+
+
+
+
+## type [Dependency]()
+
+Dependency is a dependency of a chart to other charts.
+
+```go
+type Dependency struct {
+ Values map[string]any `yaml:"-" json:"values,omitempty"`
+ Name string `yaml:"name" json:"name"`
+ Version string `yaml:"version" json:"version"`
+ Repository string `yaml:"repository" json:"repository"`
+ Alias string `yaml:"alias,omitempty" json:"alias,omitempty"`
+}
+```
+
+
+### func [DependenciesFrom]()
+
+```go
+func DependenciesFrom(data string) ([]Dependency, error)
+```
+
+DependenciesFrom returns a slice of dependencies from the given string.
+
+
+## type [EnvFrom]()
+
+
+
+```go
+type EnvFrom []string
+```
+
+
+### func [EnvFromFrom]()
+
+```go
+func EnvFromFrom(data string) (EnvFrom, error)
+```
+
+EnvFromFrom returns a EnvFrom from the given string.
+
+
+## type [ExchangeVolume]()
+
+
+
+```go
+type ExchangeVolume struct {
+ Name string `yaml:"name" json:"name"`
+ MountPath string `yaml:"mountPath" json:"mountPath"`
+ Type string `yaml:"type,omitempty" json:"type,omitempty"`
+ Init string `yaml:"init,omitempty" json:"init,omitempty"`
+}
+```
+
+
+### func [NewExchangeVolumes]()
+
+```go
+func NewExchangeVolumes(data string) ([]*ExchangeVolume, error)
+```
+
+
+
+
+## type [HealthCheck]()
+
+
+
+```go
+type HealthCheck struct {
+ LivenessProbe *corev1.Probe `yaml:"livenessProbe,omitempty" json:"livenessProbe,omitempty"`
+ ReadinessProbe *corev1.Probe `yaml:"readinessProbe,omitempty" json:"readinessProbe,omitempty"`
+}
+```
+
+
+### func [ProbeFrom]()
+
+```go
+func ProbeFrom(data string) (*HealthCheck, error)
+```
+
+
+
+
+## type [Ingress]()
+
+
+
+```go
+type Ingress struct {
+ Port *int32 `yaml:"port,omitempty" json:"port,omitempty"`
+ Annotations map[string]string `yaml:"annotations,omitempty" jsonschema:"nullable" json:"annotations,omitempty"`
+ Hostname string `yaml:"hostname,omitempty" json:"hostname,omitempty"`
+ Path *string `yaml:"path,omitempty" json:"path,omitempty"`
+ Class *string `yaml:"class,omitempty" json:"class,omitempty" jsonschema:"default:-"`
+ Enabled bool `yaml:"enabled,omitempty" json:"enabled,omitempty"`
+ TLS *TLS `yaml:"tls,omitempty" json:"tls,omitempty"`
+}
+```
+
+
+### func [IngressFrom]()
+
+```go
+func IngressFrom(data string) (*Ingress, error)
+```
+
+IngressFrom creates a new Ingress from a compose service.
+
+
+## type [MapEnv]()
+
+
+
+```go
+type MapEnv map[string]string
+```
+
+
+### func [MapEnvFrom]()
+
+```go
+func MapEnvFrom(data string) (MapEnv, error)
+```
+
+MapEnvFrom returns a MapEnv from the given string.
+
+
+## type [Ports]()
+
+
+
+```go
+type Ports []uint32
+```
+
+
+### func [PortsFrom]()
+
+```go
+func PortsFrom(data string) (Ports, error)
+```
+
+PortsFrom returns a Ports from the given string.
+
+
+## type [Secrets]()
+
+
+
+```go
+type Secrets []string
+```
+
+
+### func [SecretsFrom]()
+
+```go
+func SecretsFrom(data string) (Secrets, error)
+```
+
+
+
+
+## type [TLS]()
+
+
+
+```go
+type TLS struct {
+ Enabled bool `yaml:"enabled" json:"enabled,omitempty"`
+}
+```
+
+
+## type [ValueFrom]()
+
+
+
+```go
+type ValueFrom map[string]string
+```
+
+
+### func [GetValueFrom]()
+
+```go
+func GetValueFrom(data string) (*ValueFrom, error)
+```
+
+
+
+Generated by [gomarkdoc]()
diff --git a/doc/docs/packages/utils.md b/doc/docs/packages/utils.md
index b512f96..78a6551 100644
--- a/doc/docs/packages/utils.md
+++ b/doc/docs/packages/utils.md
@@ -8,7 +8,16 @@ import "katenary/utils"
Package utils provides some utility functions used in katenary. It defines some constants and functions used in the whole project.
-## func [AsResourceName]()
+## Constants
+
+DirectoryPermission is the default values for permissions apply to created directories.
+
+```go
+const DirectoryPermission = 0o755
+```
+
+
+## func [AsResourceName]()
```go
func AsResourceName(name string) string
@@ -17,7 +26,7 @@ func AsResourceName(name string) string
AsResourceName returns a resource name with underscores to respect the kubernetes naming convention. It's the opposite of FixedResourceName.
-## func [Confirm]()
+## func [Confirm]()
```go
func Confirm(question string, icon ...Icon) bool
@@ -26,7 +35,7 @@ func Confirm(question string, icon ...Icon) bool
Confirm asks a question and returns true if the answer is y.
-## func [CountStartingSpaces]()
+## func [CountStartingSpaces]()
```go
func CountStartingSpaces(line string) int
@@ -35,7 +44,7 @@ func CountStartingSpaces(line string) int
CountStartingSpaces counts the number of spaces at the beginning of a string.
-## func [EncodeBasicYaml]()
+## func [EncodeBasicYaml]()
```go
func EncodeBasicYaml(data any) ([]byte, error)
@@ -44,7 +53,7 @@ func EncodeBasicYaml(data any) ([]byte, error)
EncodeBasicYaml encodes a basic yaml from an interface.
-## func [FixedResourceName]()
+## func [FixedResourceName]()
```go
func FixedResourceName(name string) string
@@ -53,7 +62,7 @@ func FixedResourceName(name string) string
FixedResourceName returns a resource name without underscores to respect the kubernetes naming convention.
-## func [GetContainerByName]()
+## func [GetContainerByName]()
```go
func GetContainerByName(name string, containers []corev1.Container) (*corev1.Container, int)
@@ -62,7 +71,7 @@ func GetContainerByName(name string, containers []corev1.Container) (*corev1.Con
GetContainerByName returns a container by name and its index in the array. It returns nil, \-1 if not found.
-## func [GetKind]()
+## func [GetKind]()
```go
func GetKind(path string) (kind string)
@@ -71,7 +80,7 @@ func GetKind(path string) (kind string)
GetKind returns the kind of the resource from the file path.
-## func [GetServiceNameByPort]()
+## func [GetServiceNameByPort]()
```go
func GetServiceNameByPort(port int) string
@@ -80,7 +89,7 @@ func GetServiceNameByPort(port int) string
GetServiceNameByPort returns the service name for a port. It the service name is not found, it returns an empty string.
-## func [GetValuesFromLabel]()
+## func [GetValuesFromLabel]()
```go
func GetValuesFromLabel(service types.ServiceConfig, LabelValues string) map[string]*EnvConfig
@@ -98,7 +107,7 @@ func HashComposefiles(files []string) (string, error)
HashComposefiles returns a hash of the compose files.
-## func [Int32Ptr]()
+## func [Int32Ptr]()
```go
func Int32Ptr(i int32) *int32
@@ -107,7 +116,7 @@ func Int32Ptr(i int32) *int32
Int32Ptr returns a pointer to an int32.
-## func [PathToName]()
+## func [PathToName]()
```go
func PathToName(path string) string
@@ -116,7 +125,7 @@ func PathToName(path string) string
PathToName converts a path to a kubernetes complient name.
-## func [StrPtr]()
+## func [StrPtr]()
```go
func StrPtr(s string) *string
@@ -125,7 +134,7 @@ func StrPtr(s string) *string
StrPtr returns a pointer to a string.
-## func [TplName]()
+## func [TplName]()
```go
func TplName(serviceName, appname string, suffix ...string) string
@@ -134,7 +143,7 @@ func TplName(serviceName, appname string, suffix ...string) string
TplName returns the name of the kubernetes resource as a template string. It is used in the templates and defined in \_helper.tpl file.
-## func [TplValue]()
+## func [TplValue]()
```go
func TplValue(serviceName, variable string, pipes ...string) string
@@ -152,7 +161,7 @@ func Warn(msg ...any)
Warn prints a warning message
-## func [WordWrap]()
+## func [WordWrap]()
```go
func WordWrap(text string, lineWidth int) string
@@ -161,7 +170,7 @@ func WordWrap(text string, lineWidth int) string
WordWrap wraps a string to a given line width. Warning: it may break the string. You need to check the result.
-## func [Wrap]()
+## func [Wrap]()
```go
func Wrap(src, above, below string) string
@@ -170,7 +179,7 @@ func Wrap(src, above, below string) string
Wrap wraps a string with a string above and below. It will respect the indentation of the src string.
-## type [EnvConfig]()
+## type [EnvConfig]()
EnvConfig is a struct to hold the description of an environment variable.
diff --git a/generator/chart.go b/generator/chart.go
index 45f3791..25c0f89 100644
--- a/generator/chart.go
+++ b/generator/chart.go
@@ -3,7 +3,7 @@ package generator
import (
"fmt"
"katenary/generator/labels"
- "katenary/generator/labels/labelStructs"
+ "katenary/generator/labels/labelstructs"
"katenary/utils"
"log"
"maps"
@@ -49,7 +49,7 @@ type HelmChart struct {
AppVersion string `yaml:"appVersion"`
Description string `yaml:"description"`
Helper string `yaml:"-"`
- Dependencies []labelStructs.Dependency `yaml:"dependencies,omitempty"`
+ Dependencies []labelstructs.Dependency `yaml:"dependencies,omitempty"`
}
// NewChart creates a new empty chart with the given name.
@@ -95,7 +95,7 @@ func (chart *HelmChart) SaveTemplates(templateDir string) {
}
servicename := template.Servicename
- if err := os.MkdirAll(filepath.Join(templateDir, servicename), 0o755); err != nil {
+ if err := os.MkdirAll(filepath.Join(templateDir, servicename), utils.DirectoryPermission); err != nil {
fmt.Println(utils.IconFailure, err)
os.Exit(1)
}
@@ -103,7 +103,7 @@ func (chart *HelmChart) SaveTemplates(templateDir string) {
// if the name is a path, create the directory
if strings.Contains(name, string(filepath.Separator)) {
name = filepath.Join(templateDir, name)
- err := os.MkdirAll(filepath.Dir(name), 0o755)
+ err := os.MkdirAll(filepath.Dir(name), utils.DirectoryPermission)
if err != nil {
fmt.Println(utils.IconFailure, err)
os.Exit(1)
@@ -141,7 +141,7 @@ func (chart *HelmChart) generateConfigMapsAndSecrets(project *types.Project) err
maps.Copy(originalEnv, s.Environment)
if v, ok := s.Labels[labels.LabelSecrets]; ok {
- list, err := labelStructs.SecretsFrom(v)
+ list, err := labelstructs.SecretsFrom(v)
if err != nil {
log.Fatal("error unmarshaling secrets label:", err)
}
@@ -214,7 +214,7 @@ func (chart *HelmChart) generateDeployment(service types.ServiceConfig, deployme
if exchange, ok := service.Labels[labels.LabelExchangeVolume]; ok {
// we need to add a volume and a mount point
- ex, err := labelStructs.NewExchangeVolumes(exchange)
+ ex, err := labelstructs.NewExchangeVolumes(exchange)
if err != nil {
return err
}
@@ -298,7 +298,7 @@ func (chart *HelmChart) setCronJob(service types.ServiceConfig, appName string)
func (chart *HelmChart) setDependencies(service types.ServiceConfig) (bool, error) {
// helm dependency
if v, ok := service.Labels[labels.LabelDependencies]; ok {
- d, err := labelStructs.DependenciesFrom(v)
+ d, err := labelstructs.DependenciesFrom(v)
if err != nil {
return false, err
}
@@ -326,7 +326,7 @@ func (chart *HelmChart) setSharedConf(service types.ServiceConfig, deployments m
if _, ok := service.Labels[labels.LabelEnvFrom]; !ok {
return
}
- fromservices, err := labelStructs.EnvFromFrom(service.Labels[labels.LabelEnvFrom])
+ fromservices, err := labelstructs.EnvFromFrom(service.Labels[labels.LabelEnvFrom])
if err != nil {
log.Fatal("error unmarshaling env-from label:", err)
}
@@ -351,7 +351,7 @@ func (chart *HelmChart) setEnvironmentValuesFrom(service types.ServiceConfig, de
if _, ok := service.Labels[labels.LabelValueFrom]; !ok {
return
}
- mapping, err := labelStructs.GetValueFrom(service.Labels[labels.LabelValueFrom])
+ mapping, err := labelstructs.GetValueFrom(service.Labels[labels.LabelValueFrom])
if err != nil {
log.Fatal("error unmarshaling values-from label:", err)
}
@@ -383,7 +383,7 @@ func (chart *HelmChart) setEnvironmentValuesFrom(service types.ServiceConfig, de
// is it a secret?
isSecret := false
- secrets, err := labelStructs.SecretsFrom(dep.service.Labels[labels.LabelSecrets])
+ secrets, err := labelstructs.SecretsFrom(dep.service.Labels[labels.LabelSecrets])
if err == nil {
if slices.Contains(secrets, depName[1]) {
isSecret = true
diff --git a/generator/configMap.go b/generator/configMap.go
index 585dee3..d7fedf5 100644
--- a/generator/configMap.go
+++ b/generator/configMap.go
@@ -3,7 +3,7 @@ package generator
import (
"fmt"
"katenary/generator/labels"
- "katenary/generator/labels/labelStructs"
+ "katenary/generator/labels/labelstructs"
"katenary/utils"
"log"
"os"
@@ -65,7 +65,7 @@ func NewConfigMap(service types.ServiceConfig, appName string, forFile bool) *Co
}
// get the secrets from the labels
- secrets, err := labelStructs.SecretsFrom(service.Labels[labels.LabelSecrets])
+ secrets, err := labelstructs.SecretsFrom(service.Labels[labels.LabelSecrets])
if err != nil {
log.Fatal(err)
}
@@ -91,7 +91,7 @@ func NewConfigMap(service types.ServiceConfig, appName string, forFile bool) *Co
// do not bind env variables to the configmap
// remove the variables that are already defined in the environment
if l, ok := service.Labels[labels.LabelMapEnv]; ok {
- envmap, err := labelStructs.MapEnvFrom(l)
+ envmap, err := labelstructs.MapEnvFrom(l)
if err != nil {
log.Fatal("Error parsing map-env", err)
}
diff --git a/generator/converter.go b/generator/converter.go
index 77ceb73..52f9451 100644
--- a/generator/converter.go
+++ b/generator/converter.go
@@ -7,7 +7,7 @@ import (
"katenary/generator/extrafiles"
"katenary/generator/katenaryfile"
"katenary/generator/labels"
- "katenary/generator/labels/labelStructs"
+ "katenary/generator/labels/labelstructs"
"katenary/parser"
"katenary/utils"
"log"
@@ -173,9 +173,8 @@ func Convert(config ConvertOptions, dockerComposeFile ...string) error {
os.RemoveAll(config.OutputDir)
// create the chart directory
- if err := os.MkdirAll(templateDir, 0o755); err != nil {
- fmt.Println(utils.IconFailure, err)
- os.Exit(1)
+ if err := os.MkdirAll(templateDir, utils.DirectoryPermission); err != nil {
+ return err
}
// add icon from the command line
@@ -259,7 +258,7 @@ func addCommentsToValues(values []byte) []byte {
return []byte(strings.Join(lines, "\n"))
}
-func addDependencyDescription(values []byte, dependencies []labelStructs.Dependency) []byte {
+func addDependencyDescription(values []byte, dependencies []labelstructs.Dependency) []byte {
for _, d := range dependencies {
name := d.Name
if d.Alias != "" {
@@ -522,16 +521,16 @@ func buildCharYamlFile(chart *HelmChart, project *types.Project, chartPath strin
os.Exit(1)
}
// concat chart adding a comment with hash of services on top
- yamlChart = append([]byte(fmt.Sprintf("# compose hash (sha1): %s\n", *chart.composeHash)), yamlChart...)
+ yamlChart = append(fmt.Appendf(nil, "# compose hash (sha1): %s\n", *chart.composeHash), yamlChart...)
// add the list of compose files
files := []string{}
for _, file := range project.ComposeFiles {
base := filepath.Base(file)
files = append(files, base)
}
- yamlChart = append([]byte(fmt.Sprintf("# compose files: %s\n", strings.Join(files, ", "))), yamlChart...)
+ yamlChart = append(fmt.Appendf(nil, "# compose files: %s\n", strings.Join(files, ", ")), yamlChart...)
// add generated date
- yamlChart = append([]byte(fmt.Sprintf("# generated at: %s\n", time.Now().Format(time.RFC3339))), yamlChart...)
+ yamlChart = append(fmt.Appendf(nil, "# generated at: %s\n", time.Now().Format(time.RFC3339)), yamlChart...)
// document Chart.yaml file
yamlChart = addChartDoc(yamlChart, project)
diff --git a/generator/cronJob.go b/generator/cronJob.go
index 9cdf498..0c33c9f 100644
--- a/generator/cronJob.go
+++ b/generator/cronJob.go
@@ -2,7 +2,7 @@ package generator
import (
"katenary/generator/labels"
- "katenary/generator/labels/labelStructs"
+ "katenary/generator/labels/labelstructs"
"katenary/utils"
"log"
"strings"
@@ -30,7 +30,7 @@ func NewCronJob(service types.ServiceConfig, chart *HelmChart, appName string) (
if !ok {
return nil, nil
}
- mapping, err := labelStructs.CronJobFrom(labels)
+ mapping, err := labelstructs.CronJobFrom(labels)
if err != nil {
log.Fatalf("Error parsing cronjob labels: %s", err)
return nil, nil
diff --git a/generator/deployment.go b/generator/deployment.go
index 16c6ebd..2345882 100644
--- a/generator/deployment.go
+++ b/generator/deployment.go
@@ -3,7 +3,7 @@ package generator
import (
"fmt"
"katenary/generator/labels"
- "katenary/generator/labels/labelStructs"
+ "katenary/generator/labels/labelstructs"
"katenary/utils"
"log"
"os"
@@ -39,7 +39,7 @@ type Deployment struct {
service *types.ServiceConfig `yaml:"-"`
defaultTag string `yaml:"-"`
isMainApp bool `yaml:"-"`
- exchangesVolumes map[string]*labelStructs.ExchangeVolume `yaml:"-"`
+ exchangesVolumes map[string]*labelstructs.ExchangeVolume `yaml:"-"`
boundEnvVar []string `yaml:"-"` // environement to remove
}
@@ -94,7 +94,7 @@ func NewDeployment(service types.ServiceConfig, chart *HelmChart) *Deployment {
},
configMaps: make(map[string]*ConfigMapMount),
volumeMap: make(map[string]string),
- exchangesVolumes: map[string]*labelStructs.ExchangeVolume{},
+ exchangesVolumes: map[string]*labelstructs.ExchangeVolume{},
boundEnvVar: []string{},
}
@@ -160,7 +160,7 @@ func (d *Deployment) AddContainer(service types.ServiceConfig) {
func (d *Deployment) AddHealthCheck(service types.ServiceConfig, container *corev1.Container) {
// get the label for healthcheck
if v, ok := service.Labels[labels.LabelHealthCheck]; ok {
- probes, err := labelStructs.ProbeFrom(v)
+ probes, err := labelstructs.ProbeFrom(v)
if err != nil {
log.Fatal(err)
}
@@ -195,7 +195,7 @@ func (d *Deployment) AddIngress(service types.ServiceConfig, appName string) *In
func (d *Deployment) AddVolumes(service types.ServiceConfig, appName string) {
tobind := map[string]bool{}
if v, ok := service.Labels[labels.LabelConfigMapFiles]; ok {
- binds, err := labelStructs.ConfigMapFileFrom(v)
+ binds, err := labelstructs.ConfigMapFileFrom(v)
if err != nil {
log.Fatal(err)
}
@@ -320,7 +320,7 @@ func (d *Deployment) SetEnvFrom(service types.ServiceConfig, appName string, sam
}()
// secrets from label
- labelSecrets, err := labelStructs.SecretsFrom(service.Labels[labels.LabelSecrets])
+ labelSecrets, err := labelstructs.SecretsFrom(service.Labels[labels.LabelSecrets])
if err != nil {
log.Fatal(err)
}
diff --git a/generator/generator.go b/generator/generator.go
index 21f8559..cbaa288 100644
--- a/generator/generator.go
+++ b/generator/generator.go
@@ -4,7 +4,7 @@ import (
"bytes"
"fmt"
"katenary/generator/labels"
- "katenary/generator/labels/labelStructs"
+ "katenary/generator/labels/labelstructs"
"katenary/utils"
"log"
"regexp"
@@ -227,7 +227,7 @@ func fixResourceNames(project *types.Project) error {
}
// also, the value-from label should be updated
if valuefrom, ok := s.Labels[labels.LabelValueFrom]; ok {
- vf, err := labelStructs.GetValueFrom(valuefrom)
+ vf, err := labelstructs.GetValueFrom(valuefrom)
if err != nil {
return err
}
diff --git a/generator/ingress.go b/generator/ingress.go
index 7e2d753..31d9ed9 100644
--- a/generator/ingress.go
+++ b/generator/ingress.go
@@ -2,7 +2,7 @@ package generator
import (
"katenary/generator/labels"
- "katenary/generator/labels/labelStructs"
+ "katenary/generator/labels/labelstructs"
"katenary/utils"
"log"
"strings"
@@ -33,7 +33,7 @@ func NewIngress(service types.ServiceConfig, Chart *HelmChart) *Ingress {
return nil
}
- mapping, err := labelStructs.IngressFrom(label)
+ mapping, err := labelstructs.IngressFrom(label)
if err != nil {
log.Fatalf("Failed to parse ingress label: %s\n", err)
}
diff --git a/generator/katenaryfile/main.go b/generator/katenaryfile/main.go
index b9b938d..47f4624 100644
--- a/generator/katenaryfile/main.go
+++ b/generator/katenaryfile/main.go
@@ -5,7 +5,7 @@ import (
"encoding/json"
"fmt"
"katenary/generator/labels"
- "katenary/generator/labels/labelStructs"
+ "katenary/generator/labels/labelstructs"
"katenary/utils"
"log"
"os"
@@ -27,20 +27,20 @@ type StringOrMap any
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"`
+ 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"`
- ExchangeVolumes []*labelStructs.ExchangeVolume `json:"exchange-volumes,omitempty" jsonschema:"title=Exchange Volumes,description=Exchange volumes between services"`
- ValuesFrom *labelStructs.ValueFrom `json:"values-from,omitempty" jsonschema:"title=Values From,description=Inject values from another service (secret or configmap environment variables)"`
+ 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"`
+ ExchangeVolumes []*labelstructs.ExchangeVolume `json:"exchange-volumes,omitempty" jsonschema:"title=Exchange Volumes,description=Exchange volumes between services"`
+ ValuesFrom *labelstructs.ValueFrom `json:"values-from,omitempty" jsonschema:"title=Values From,description=Inject values from another service (secret or configmap environment variables)"`
}
// OverrideWithConfig overrides the project with the katenary.yaml file. It
@@ -117,7 +117,7 @@ func getLabelContent(o any, service *types.ServiceConfig, labelName string) erro
val := strings.TrimSpace(string(c))
if labelName == labels.LabelIngress {
// special case, values must be set from some defaults
- ing, err := labelStructs.IngressFrom(val)
+ ing, err := labelstructs.IngressFrom(val)
if err != nil {
log.Fatal(err)
return err
diff --git a/generator/katenaryfile/main_test.go b/generator/katenaryfile/main_test.go
index 559f322..263c612 100644
--- a/generator/katenaryfile/main_test.go
+++ b/generator/katenaryfile/main_test.go
@@ -57,6 +57,9 @@ webapp:
cli.WithDefaultConfigPath,
)
project, err := cli.ProjectFromOptions(options)
+ if err != nil {
+ t.Fatalf("Failed to create project from options: %s", err.Error())
+ }
OverrideWithConfig(project)
w := project.Services[0].Labels
@@ -107,6 +110,9 @@ webapp:
cli.WithDefaultConfigPath,
)
project, err := cli.ProjectFromOptions(options)
+ if err != nil {
+ t.Fatalf("Failed to create project from options: %s", err.Error())
+ }
OverrideWithConfig(project)
w := project.Services[0].Labels
diff --git a/generator/labels/doc.go b/generator/labels/doc.go
new file mode 100644
index 0000000..f75a717
--- /dev/null
+++ b/generator/labels/doc.go
@@ -0,0 +1,2 @@
+// Package labels provides functionality to parse and manipulate labels.
+package labels
diff --git a/generator/labels/katenaryLabels.go b/generator/labels/katenaryLabels.go
index 5c2ea33..550520f 100644
--- a/generator/labels/katenaryLabels.go
+++ b/generator/labels/katenaryLabels.go
@@ -84,7 +84,7 @@ func init() {
}
}
-// Generate the help for the labels.
+// GetLabelHelp return the help for the labels.
func GetLabelHelp(asMarkdown bool) string {
names := GetLabelNames() // sorted
if !asMarkdown {
diff --git a/generator/labels/labelStructs/doc.go b/generator/labels/labelStructs/doc.go
deleted file mode 100644
index 5373fcf..0000000
--- a/generator/labels/labelStructs/doc.go
+++ /dev/null
@@ -1,2 +0,0 @@
-// labelStructs is a package that contains the structs used to represent the labels in the yaml files.
-package labelStructs
diff --git a/generator/labels/labelStructs/configMap.go b/generator/labels/labelstructs/configMap.go
similarity index 92%
rename from generator/labels/labelStructs/configMap.go
rename to generator/labels/labelstructs/configMap.go
index 2b5112f..a771d7b 100644
--- a/generator/labels/labelStructs/configMap.go
+++ b/generator/labels/labelstructs/configMap.go
@@ -1,4 +1,4 @@
-package labelStructs
+package labelstructs
import "gopkg.in/yaml.v3"
diff --git a/generator/labels/labelstructs/configMap_test.go b/generator/labels/labelstructs/configMap_test.go
new file mode 100644
index 0000000..55f11f2
--- /dev/null
+++ b/generator/labels/labelstructs/configMap_test.go
@@ -0,0 +1,17 @@
+package labelstructs_test
+
+import (
+ "katenary/generator/labels/labelstructs"
+ "testing"
+)
+
+func TestConfigMapFileFrom(t *testing.T) {
+ ts := "- foo/bar"
+ tc2, _ := labelstructs.ConfigMapFileFrom(ts)
+ if len(tc2) != 1 {
+ t.Errorf("Expected ConfigMapFile to have 1 item, got %d", len(tc2))
+ }
+ if tc2[0] != "foo/bar" {
+ t.Errorf("Expected ConfigMapFile to contain 'foo/bar', got %s", tc2[0])
+ }
+}
diff --git a/generator/labels/labelStructs/cronJob.go b/generator/labels/labelstructs/cronJob.go
similarity index 95%
rename from generator/labels/labelStructs/cronJob.go
rename to generator/labels/labelstructs/cronJob.go
index 972e456..9c20ecb 100644
--- a/generator/labels/labelStructs/cronJob.go
+++ b/generator/labels/labelstructs/cronJob.go
@@ -1,4 +1,4 @@
-package labelStructs
+package labelstructs
import "gopkg.in/yaml.v3"
diff --git a/generator/labels/labelstructs/cronJob_test.go b/generator/labels/labelstructs/cronJob_test.go
new file mode 100644
index 0000000..85dfe75
--- /dev/null
+++ b/generator/labels/labelstructs/cronJob_test.go
@@ -0,0 +1,25 @@
+package labelstructs
+
+import "testing"
+
+func TestCronJobFrom(t *testing.T) {
+ ts := `
+image: fooimage
+command: thecommand
+schedule: "0/3 0 * * *"
+Rbac: false
+`
+ tc, _ := CronJobFrom(ts)
+ if tc.Image != "fooimage" {
+ t.Errorf("Expected CronJob image to be 'fooimage', got %s", tc.Image)
+ }
+ if tc.Command != "thecommand" {
+ t.Errorf("Expected CronJob command to be 'thecommand', got %s", tc.Command)
+ }
+ if tc.Schedule != "0/3 0 * * *" {
+ t.Errorf("Expected CronJob schedule to be '0/3 0 * * *', got %s", tc.Schedule)
+ }
+ if tc.Rbac != false {
+ t.Errorf("Expected CronJob rbac to be false, got %t", tc.Rbac)
+ }
+}
diff --git a/generator/labels/labelStructs/dependencies.go b/generator/labels/labelstructs/dependencies.go
similarity index 97%
rename from generator/labels/labelStructs/dependencies.go
rename to generator/labels/labelstructs/dependencies.go
index 90511fe..e82a585 100644
--- a/generator/labels/labelStructs/dependencies.go
+++ b/generator/labels/labelstructs/dependencies.go
@@ -1,4 +1,4 @@
-package labelStructs
+package labelstructs
import "gopkg.in/yaml.v3"
diff --git a/generator/labels/labelstructs/dependencies_test.go b/generator/labels/labelstructs/dependencies_test.go
new file mode 100644
index 0000000..b6fdd6c
--- /dev/null
+++ b/generator/labels/labelstructs/dependencies_test.go
@@ -0,0 +1,14 @@
+package labelstructs
+
+import "testing"
+
+func TestDependenciesLabel(t *testing.T) {
+ ts := "- name: mongodb"
+ tc, _ := DependenciesFrom(ts)
+ if len(tc) != 1 {
+ t.Errorf("Expected DependenciesLabel to have 1 item, got %d", len(tc))
+ }
+ if tc[0].Name != "mongodb" {
+ t.Errorf("Expected DependenciesLabel to contain 'mongodb', got %s", tc[0].Name)
+ }
+}
diff --git a/generator/labels/labelstructs/doc.go b/generator/labels/labelstructs/doc.go
new file mode 100644
index 0000000..2b8d5fb
--- /dev/null
+++ b/generator/labels/labelstructs/doc.go
@@ -0,0 +1,2 @@
+// Package labelstructs is a package that contains the structs used to represent the labels in the yaml files.
+package labelstructs
diff --git a/generator/labels/labelStructs/envFrom.go b/generator/labels/labelstructs/envFrom.go
similarity index 93%
rename from generator/labels/labelStructs/envFrom.go
rename to generator/labels/labelstructs/envFrom.go
index f2c8f2f..cbc4151 100644
--- a/generator/labels/labelStructs/envFrom.go
+++ b/generator/labels/labelstructs/envFrom.go
@@ -1,4 +1,4 @@
-package labelStructs
+package labelstructs
import "gopkg.in/yaml.v3"
diff --git a/generator/labels/labelstructs/envFrom_test.go b/generator/labels/labelstructs/envFrom_test.go
new file mode 100644
index 0000000..0f35d46
--- /dev/null
+++ b/generator/labels/labelstructs/envFrom_test.go
@@ -0,0 +1,17 @@
+package labelstructs
+
+import "testing"
+
+func TestEnvFromLabel(t *testing.T) {
+ ts := "- foo\n- bar"
+ tc, _ := EnvFromFrom(ts)
+ if len(tc) != 2 {
+ t.Errorf("Expected EnvFrom to have 2 items, got %d", len(tc))
+ }
+ if tc[0] != "foo" {
+ t.Errorf("Expected EnvFrom to contain 'foo', got %s", tc[0])
+ }
+ if tc[1] != "bar" {
+ t.Errorf("Expected EnvFrom to contain 'bar', got %s", tc[1])
+ }
+}
diff --git a/generator/labels/labelStructs/exchangeVolume.go b/generator/labels/labelstructs/exchangeVolume.go
similarity index 95%
rename from generator/labels/labelStructs/exchangeVolume.go
rename to generator/labels/labelstructs/exchangeVolume.go
index 1faa997..2f32894 100644
--- a/generator/labels/labelStructs/exchangeVolume.go
+++ b/generator/labels/labelstructs/exchangeVolume.go
@@ -1,4 +1,4 @@
-package labelStructs
+package labelstructs
import "gopkg.in/yaml.v3"
diff --git a/generator/labels/labelstructs/exchangeVolume_test.go b/generator/labels/labelstructs/exchangeVolume_test.go
new file mode 100644
index 0000000..a3f380c
--- /dev/null
+++ b/generator/labels/labelstructs/exchangeVolume_test.go
@@ -0,0 +1,17 @@
+package labelstructs
+
+import "testing"
+
+func TestExchangeVolumeLabel(t *testing.T) {
+ ts := "- name: exchange-volume\n mountPath: /exchange\n readOnly: true"
+ tc, _ := NewExchangeVolumes(ts)
+ if len(tc) != 1 {
+ t.Errorf("Expected ExchangeVolumeLabel to have 1 item, got %d", len(tc))
+ }
+ if tc[0].Name != "exchange-volume" {
+ t.Errorf("Expected ExchangeVolumeLabel to contain 'exchange-volume', got %s", tc[0].Name)
+ }
+ if tc[0].MountPath != "/exchange" {
+ t.Errorf("Expected MountPath to be '/exchange', got %s", tc[0].MountPath)
+ }
+}
diff --git a/generator/labels/labelStructs/ingress.go b/generator/labels/labelstructs/ingress.go
similarity index 85%
rename from generator/labels/labelStructs/ingress.go
rename to generator/labels/labelstructs/ingress.go
index df40da3..b7285cb 100644
--- a/generator/labels/labelStructs/ingress.go
+++ b/generator/labels/labelstructs/ingress.go
@@ -1,4 +1,4 @@
-package labelStructs
+package labelstructs
import (
"fmt"
@@ -14,10 +14,10 @@ type TLS struct {
type Ingress struct {
Port *int32 `yaml:"port,omitempty" json:"port,omitempty"`
Annotations map[string]string `yaml:"annotations,omitempty" jsonschema:"nullable" json:"annotations,omitempty"`
- Hostname string `yaml:"hostname" json:"hostname,omitempty"`
+ Hostname string `yaml:"hostname,omitempty" json:"hostname,omitempty"`
Path *string `yaml:"path,omitempty" json:"path,omitempty"`
Class *string `yaml:"class,omitempty" json:"class,omitempty" jsonschema:"default:-"`
- Enabled bool `yaml:"enabled" json:"enabled,omitempty"`
+ Enabled bool `yaml:"enabled,omitempty" json:"enabled,omitempty"`
TLS *TLS `yaml:"tls,omitempty" json:"tls,omitempty"`
}
diff --git a/generator/labels/labelstructs/ingress_test.go b/generator/labels/labelstructs/ingress_test.go
new file mode 100644
index 0000000..d4fe8c1
--- /dev/null
+++ b/generator/labels/labelstructs/ingress_test.go
@@ -0,0 +1,31 @@
+package labelstructs
+
+import "testing"
+
+func TestIngressLabel(t *testing.T) {
+ ts := "\nhostname: example.com\npath: /\nenabled: true\nport: 8888"
+ tc, err := IngressFrom(ts)
+ if err != nil {
+ t.Errorf("Error parsing IngressLabel: %v", err)
+ }
+ if tc.Hostname != "example.com" {
+ t.Errorf("Expected IngressLabel to contain 'example.com', got %s", tc.Hostname)
+ }
+ if tc.Path == nil || *tc.Path != "/" {
+ t.Errorf("Expected IngressLabel to contain '/', got %v", tc.Path)
+ }
+ if tc.Enabled != true {
+ t.Errorf("Expected IngressLabel to be enabled, got %v", tc.Enabled)
+ }
+ if tc.Port == nil || *tc.Port != 8888 {
+ t.Errorf("Expected IngressLabel to have port 8888, got %d", tc.Port)
+ }
+}
+
+func TestIngressLabelNoPort(t *testing.T) {
+ ts := "\nhostname: example.com\npath: /\nenabled: true"
+ _, err := IngressFrom(ts)
+ if err == nil {
+ t.Errorf("Expected error when parsing IngressLabel without port, got nil")
+ }
+}
diff --git a/generator/labels/labelStructs/mapenv.go b/generator/labels/labelstructs/mapenv.go
similarity index 93%
rename from generator/labels/labelStructs/mapenv.go
rename to generator/labels/labelstructs/mapenv.go
index 6b4cdfa..dfccf4f 100644
--- a/generator/labels/labelStructs/mapenv.go
+++ b/generator/labels/labelstructs/mapenv.go
@@ -1,4 +1,4 @@
-package labelStructs
+package labelstructs
import "gopkg.in/yaml.v3"
diff --git a/generator/labels/labelstructs/mapenv_test.go b/generator/labels/labelstructs/mapenv_test.go
new file mode 100644
index 0000000..67171c1
--- /dev/null
+++ b/generator/labels/labelstructs/mapenv_test.go
@@ -0,0 +1,11 @@
+package labelstructs
+
+import "testing"
+
+func TestConfigMapLabel(t *testing.T) {
+ ts := "foo: bar"
+ tc, _ := MapEnvFrom(ts)
+ if len(tc) != 1 {
+ t.Errorf("Expected ConfigMapFile to have 1 item, got %d", len(tc))
+ }
+}
diff --git a/generator/labels/labelStructs/ports.go b/generator/labels/labelstructs/ports.go
similarity index 92%
rename from generator/labels/labelStructs/ports.go
rename to generator/labels/labelstructs/ports.go
index 253a075..43253c8 100644
--- a/generator/labels/labelStructs/ports.go
+++ b/generator/labels/labelstructs/ports.go
@@ -1,4 +1,4 @@
-package labelStructs
+package labelstructs
import "gopkg.in/yaml.v3"
diff --git a/generator/labels/labelstructs/ports_test.go b/generator/labels/labelstructs/ports_test.go
new file mode 100644
index 0000000..032568b
--- /dev/null
+++ b/generator/labels/labelstructs/ports_test.go
@@ -0,0 +1,23 @@
+package labelstructs
+
+import "testing"
+
+func TestPortsFromLabel(t *testing.T) {
+ data := "- 8080\n- 9090\n"
+ expected := Ports{8080, 9090}
+
+ ports, err := PortsFrom(data)
+ if err != nil {
+ t.Fatalf("expected no error, got %v", err)
+ }
+
+ if len(ports) != len(expected) {
+ t.Fatalf("expected length %d, got %d", len(expected), len(ports))
+ }
+
+ for i, port := range ports {
+ if port != expected[i] {
+ t.Errorf("expected port %d at index %d, got %d", expected[i], i, port)
+ }
+ }
+}
diff --git a/generator/labels/labelStructs/probes.go b/generator/labels/labelstructs/probes.go
similarity index 98%
rename from generator/labels/labelStructs/probes.go
rename to generator/labels/labelstructs/probes.go
index bdd3813..1feeeb4 100644
--- a/generator/labels/labelStructs/probes.go
+++ b/generator/labels/labelstructs/probes.go
@@ -1,4 +1,4 @@
-package labelStructs
+package labelstructs
import (
"encoding/json"
diff --git a/generator/labels/labelstructs/probes_test.go b/generator/labels/labelstructs/probes_test.go
new file mode 100644
index 0000000..2ceaf4c
--- /dev/null
+++ b/generator/labels/labelstructs/probes_test.go
@@ -0,0 +1,16 @@
+package labelstructs
+
+import "testing"
+
+func TestProbesLabel(t *testing.T) {
+ readiness := "readinessProbe:\n httpGet:\n path: /healthz\n port: 8080\n initialDelaySeconds: 5\n periodSeconds: 10"
+ tc, err := ProbeFrom(readiness)
+ if err != nil {
+ t.Errorf("Error parsing ProbesLabel: %v %v", err, tc)
+ }
+ liveness := "livenessProbe:\n httpGet:\n path: /healthz\n port: 8080\n initialDelaySeconds: 5\n periodSeconds: 10"
+ tc2, err := ProbeFrom(liveness)
+ if err != nil {
+ t.Errorf("Error parsing ProbesLabel: %v %v", err, tc2)
+ }
+}
diff --git a/generator/labels/labelStructs/secrets.go b/generator/labels/labelstructs/secrets.go
similarity index 91%
rename from generator/labels/labelStructs/secrets.go
rename to generator/labels/labelstructs/secrets.go
index e5cfb36..2ac8d59 100644
--- a/generator/labels/labelStructs/secrets.go
+++ b/generator/labels/labelstructs/secrets.go
@@ -1,4 +1,4 @@
-package labelStructs
+package labelstructs
import "gopkg.in/yaml.v3"
diff --git a/generator/labels/labelstructs/secrets_test.go b/generator/labels/labelstructs/secrets_test.go
new file mode 100644
index 0000000..5e34b08
--- /dev/null
+++ b/generator/labels/labelstructs/secrets_test.go
@@ -0,0 +1,17 @@
+package labelstructs
+
+import "testing"
+
+func TestSecretLabel(t *testing.T) {
+ data := "- foo\n- bar"
+ tc, err := SecretsFrom(data)
+ if err != nil {
+ t.Errorf("Error parsing SecretLabel: %v %v", err, tc)
+ }
+ items := []string{"foo", "bar"}
+ for i, item := range tc {
+ if item != items[i] {
+ t.Errorf("Expected SecretLabel to contain '%s', got '%s'", items[i], item)
+ }
+ }
+}
diff --git a/generator/labels/labelStructs/valueFrom.go b/generator/labels/labelstructs/valueFrom.go
similarity index 91%
rename from generator/labels/labelStructs/valueFrom.go
rename to generator/labels/labelstructs/valueFrom.go
index 9ad5712..5d86176 100644
--- a/generator/labels/labelStructs/valueFrom.go
+++ b/generator/labels/labelstructs/valueFrom.go
@@ -1,4 +1,4 @@
-package labelStructs
+package labelstructs
import "gopkg.in/yaml.v3"
diff --git a/generator/labels/labelstructs/valueFrom_test.go b/generator/labels/labelstructs/valueFrom_test.go
new file mode 100644
index 0000000..5eb1f15
--- /dev/null
+++ b/generator/labels/labelstructs/valueFrom_test.go
@@ -0,0 +1,25 @@
+package labelstructs
+
+import (
+ "testing"
+)
+
+func TestValueFromLabel(t *testing.T) {
+ data := "data: foo\ndata2: bar"
+ tc, err := GetValueFrom(data)
+ if err != nil {
+ t.Fatalf("expected no error, got %v", err)
+ }
+ if tc == nil {
+ t.Fatalf("expected non-nil map, got nil")
+ }
+ if len(*tc) != 2 {
+ t.Errorf("expected 2 items, got %d", len(*tc))
+ }
+ if (*tc)["data"] != "foo" {
+ t.Errorf("expected 'data' to be 'foo', got %s", (*tc)["data"])
+ }
+ if (*tc)["data2"] != "bar" {
+ t.Errorf("expected 'data2' to be 'bar', got %s", (*tc)["data2"])
+ }
+}
diff --git a/generator/secret_test.go b/generator/secret_test.go
index fdefdaf..62dae1f 100644
--- a/generator/secret_test.go
+++ b/generator/secret_test.go
@@ -82,7 +82,9 @@ services:
AppVersion: appVersion,
ChartVersion: chartVersion,
}
- Convert(convertOptions, "compose.yml")
+ if err := Convert(convertOptions, "compose.yml"); err != nil {
+ t.Fatalf("Failed to convert compose file: %s", err)
+ }
c, err := os.ReadFile("chart/values.yaml")
if err != nil {
t.Fatal(err)
diff --git a/generator/utils.go b/generator/utils.go
index f931e73..51feb08 100644
--- a/generator/utils.go
+++ b/generator/utils.go
@@ -2,7 +2,7 @@ package generator
import (
"katenary/generator/labels"
- "katenary/generator/labels/labelStructs"
+ "katenary/generator/labels/labelstructs"
"katenary/utils"
"regexp"
"strconv"
@@ -50,7 +50,7 @@ func fixPorts(service *types.ServiceConfig) error {
if portsLabel, ok = service.Labels[labels.LabelPorts]; !ok {
return nil
}
- ports, err := labelStructs.PortsFrom(portsLabel)
+ ports, err := labelstructs.PortsFrom(portsLabel)
if err != nil {
// maybe it's a string, comma separated
parts := strings.SplitSeq(portsLabel, ",")
diff --git a/generator/utils_test.go b/generator/utils_test.go
index b08b1fd..f6a92f6 100644
--- a/generator/utils_test.go
+++ b/generator/utils_test.go
@@ -3,6 +3,7 @@ package generator
import (
"fmt"
"katenary/generator/labels"
+ "katenary/utils"
"os"
"path/filepath"
"testing"
@@ -25,7 +26,7 @@ services:
}
composeFile := filepath.Join(tmpDir, "compose.yaml")
- os.MkdirAll(tmpDir, 0755)
+ os.MkdirAll(tmpDir, utils.DirectoryPermission)
if err := os.WriteFile(composeFile, []byte(composeFileContent), 0644); err != nil {
t.Log(err)
}
@@ -73,7 +74,7 @@ services:
}
composeFile := filepath.Join(tmpDir, "compose.yaml")
- os.MkdirAll(tmpDir, 0755)
+ os.MkdirAll(tmpDir, utils.DirectoryPermission)
if err := os.WriteFile(composeFile, []byte(composeFileContent), 0644); err != nil {
t.Log(err)
}
diff --git a/generator/volume_test.go b/generator/volume_test.go
index d838f56..8f0b78a 100644
--- a/generator/volume_test.go
+++ b/generator/volume_test.go
@@ -6,6 +6,7 @@ import (
"image/color"
"image/png"
"katenary/generator/labels"
+ "katenary/utils"
"log"
"os"
"path/filepath"
@@ -19,7 +20,7 @@ import (
const (
htmlContent = "Hello, World!
"
developementFile = "templates/web/deployment.yaml"
- indexHtmlFile = "index.html"
+ indexHMLFile = "index.html"
)
func TestGenerateWithBoundVolume(t *testing.T) {
@@ -68,7 +69,7 @@ services:
// create a static directory with an index.html file
staticDir := tmpDir + "/static"
- os.Mkdir(staticDir, 0o755)
+ os.Mkdir(staticDir, utils.DirectoryPermission)
indexFile, err := os.Create(staticDir + "/index.html")
if err != nil {
t.Errorf("Failed to create index.html: %s", err)
@@ -106,8 +107,8 @@ services:
if len(data) != 1 {
t.Errorf("Expected 1 data, got %d", len(data))
}
- if data[indexHtmlFile] != htmlContent {
- t.Errorf("Expected index.html to be "+htmlContent+", got %s", data[indexHtmlFile])
+ if data[indexHMLFile] != htmlContent {
+ t.Errorf("Expected index.html to be "+htmlContent+", got %s", data[indexHMLFile])
}
}
@@ -128,7 +129,7 @@ services:
// create a static directory with an index.html file
staticDir := tmpDir + "/static"
- os.Mkdir(staticDir, 0o755)
+ os.Mkdir(staticDir, utils.DirectoryPermission)
indexFile, err := os.Create(staticDir + "/index.html")
if err != nil {
t.Errorf("Failed to create index.html: %s", err)
@@ -153,7 +154,7 @@ services:
}
// but this time, we need a subpath
subPath := dt.Spec.Template.Spec.Containers[0].VolumeMounts[0].SubPath
- if subPath != indexHtmlFile {
+ if subPath != indexHMLFile {
t.Errorf("Expected subpath to be index.html, got %s", subPath)
}
}
@@ -174,15 +175,15 @@ services:
log.Println(tmpDir)
defer teardown(tmpDir)
- os.Mkdir(filepath.Join(tmpDir, "images"), 0o755)
+ os.Mkdir(filepath.Join(tmpDir, "images"), utils.DirectoryPermission)
// create a png image
pngFile := tmpDir + "/images/foo.png"
w, h := 100, 100
img := image.NewRGBA(image.Rect(0, 0, w, h))
red := color.RGBA{255, 0, 0, 255}
- for y := 0; y < h; y++ {
- for x := 0; x < w; x++ {
+ for y := range h {
+ for x := range w {
img.Set(x, y, red)
}
}
@@ -244,15 +245,15 @@ services:
log.Println(tmpDir)
defer teardown(tmpDir)
- os.Mkdir(filepath.Join(tmpDir, "images"), 0o755)
+ os.Mkdir(filepath.Join(tmpDir, "images"), utils.DirectoryPermission)
// create a png image
pngFile := tmpDir + "/images/foo.png"
w, h := 100, 100
img := image.NewRGBA(image.Rect(0, 0, w, h))
red := color.RGBA{255, 0, 0, 255}
- for y := 0; y < h; y++ {
- for x := 0; x < w; x++ {
+ for y := range h {
+ for x := range w {
img.Set(x, y, red)
}
}
diff --git a/install.sh b/install.sh
index 15da7fa..03e5f86 100644
--- a/install.sh
+++ b/install.sh
@@ -18,28 +18,28 @@ COMON_INSTALL_PATHS="$HOME/.local/bin $HOME/.bin $HOME/bin"
INSTALL_PATH=""
for p in $COMON_INSTALL_PATHS; do
- if [ -d $p ]; then
- INSTALL_PATH=$p
- break
- fi
+ if [ -d $p ]; then
+ INSTALL_PATH=$p
+ break
+ fi
done
# check if the user has write access to the INSTALL_PATH
if [ -z "$INSTALL_PATH" ]; then
- INSTALL_PATH="/usr/local/bin"
- if [ ! -w $INSTALL_PATH ]; then
- echo "You don't have write access to $INSTALL_PATH"
- echo "Please, run with sudo or install locally"
- exit 1
- fi
+ INSTALL_PATH="/usr/local/bin"
+ if [ ! -w $INSTALL_PATH ]; then
+ echo "You don't have write access to $INSTALL_PATH"
+ echo "Please, run with sudo or install locally"
+ exit 1
+ fi
fi
# ensure that $INSTALL_PATH is in the PATH
-if ! echo $PATH | grep -q $INSTALL_PATH; then
- echo "Sorry, $INSTALL_PATH is not in the PATH"
- echo "Please, add it to your PATH in your shell configuration file"
- echo "then restart your shell and run this script again"
- exit 1
+if ! echo "$PATH" | grep -q "$INSTALL_PATH"; then
+ echo "Sorry, ${INSTALL_PATH} is not in the PATH"
+ echo "Please, add it to your PATH in your shell configuration file"
+ echo "then restart your shell and run this script again"
+ exit 1
fi
# Where to download the binary
@@ -47,7 +47,7 @@ BASE="https://github.com/metal3d/katenary/releases/latest/download/"
# for compatibility with older ARM versions
if [ $ARCH = "x86_64" ]; then
- ARCH="amd64"
+ ARCH="amd64"
fi
BIN_URL="$BASE/katenary-$OS-$ARCH"
@@ -58,8 +58,8 @@ echo "Downloading $BIN_URL"
T=$(mktemp -u)
curl -SL -# $BIN_URL -o $T || (echo "Failed to download katenary" && rm -f $T && exit 1)
-mv $T $INSTALL_PATH/katenary
-chmod +x $INSTALL_PATH/katenary
+mv "$T" "${INSTALL_PATH}/katenary"
+chmod +x "${INSTALL_PATH}/katenary"
echo
echo "Installed to $INSTALL_PATH/katenary"
echo "Installation complete! Run 'katenary help' to get started."
diff --git a/utils/utils.go b/utils/utils.go
index 6ebd5ab..78cca18 100644
--- a/utils/utils.go
+++ b/utils/utils.go
@@ -14,6 +14,9 @@ import (
corev1 "k8s.io/api/core/v1"
)
+// DirectoryPermission is the default values for permissions apply to created directories.
+const DirectoryPermission = 0o755
+
// TplName returns the name of the kubernetes resource as a template string.
// It is used in the templates and defined in _helper.tpl file.
func TplName(serviceName, appname string, suffix ...string) string {