Merge pull request #129 from metal3d/develop

Many fixes on code quality and CI
This commit is contained in:
2025-07-06 15:37:08 +02:00
committed by GitHub
49 changed files with 641 additions and 143 deletions

View File

@@ -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 }}

View File

@@ -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 \
.

View File

@@ -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{

View File

@@ -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
}
```

View File

@@ -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)"`
}
```

View File

@@ -6,6 +6,8 @@
import "katenary/generator/labels"
```
Package labels provides functionality to parse and manipulate labels.
## Constants
<a name="KatenaryLabelPrefix"></a>
@@ -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.
<a name="GetLabelHelpFor"></a>
## func [GetLabelHelpFor](<https://github.com/metal3d/katenary/blob/develop/generator/labels/katenaryLabels.go#L97>)

View File

@@ -0,0 +1,246 @@
<!-- Code generated by gomarkdoc. DO NOT EDIT -->
# 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](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelstructs/configMap.go#L5>)
```go
type ConfigMapFile []string
```
<a name="ConfigMapFileFrom"></a>
### func [ConfigMapFileFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelstructs/configMap.go#L7>)
```go
func ConfigMapFileFrom(data string) (ConfigMapFile, error)
```
<a name="CronJob"></a>
## type [CronJob](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelstructs/cronJob.go#L5-L10>)
```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"`
}
```
<a name="CronJobFrom"></a>
### func [CronJobFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelstructs/cronJob.go#L12>)
```go
func CronJobFrom(data string) (*CronJob, error)
```
<a name="Dependency"></a>
## type [Dependency](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelstructs/dependencies.go#L6-L12>)
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"`
}
```
<a name="DependenciesFrom"></a>
### func [DependenciesFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelstructs/dependencies.go#L15>)
```go
func DependenciesFrom(data string) ([]Dependency, error)
```
DependenciesFrom returns a slice of dependencies from the given string.
<a name="EnvFrom"></a>
## type [EnvFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelstructs/envFrom.go#L5>)
```go
type EnvFrom []string
```
<a name="EnvFromFrom"></a>
### func [EnvFromFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelstructs/envFrom.go#L8>)
```go
func EnvFromFrom(data string) (EnvFrom, error)
```
EnvFromFrom returns a EnvFrom from the given string.
<a name="ExchangeVolume"></a>
## type [ExchangeVolume](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelstructs/exchangeVolume.go#L5-L10>)
```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"`
}
```
<a name="NewExchangeVolumes"></a>
### func [NewExchangeVolumes](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelstructs/exchangeVolume.go#L12>)
```go
func NewExchangeVolumes(data string) ([]*ExchangeVolume, error)
```
<a name="HealthCheck"></a>
## type [HealthCheck](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelstructs/probes.go#L11-L14>)
```go
type HealthCheck struct {
LivenessProbe *corev1.Probe `yaml:"livenessProbe,omitempty" json:"livenessProbe,omitempty"`
ReadinessProbe *corev1.Probe `yaml:"readinessProbe,omitempty" json:"readinessProbe,omitempty"`
}
```
<a name="ProbeFrom"></a>
### func [ProbeFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelstructs/probes.go#L16>)
```go
func ProbeFrom(data string) (*HealthCheck, error)
```
<a name="Ingress"></a>
## type [Ingress](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelstructs/ingress.go#L14-L22>)
```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"`
}
```
<a name="IngressFrom"></a>
### func [IngressFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelstructs/ingress.go#L25>)
```go
func IngressFrom(data string) (*Ingress, error)
```
IngressFrom creates a new Ingress from a compose service.
<a name="MapEnv"></a>
## type [MapEnv](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelstructs/mapenv.go#L5>)
```go
type MapEnv map[string]string
```
<a name="MapEnvFrom"></a>
### func [MapEnvFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelstructs/mapenv.go#L8>)
```go
func MapEnvFrom(data string) (MapEnv, error)
```
MapEnvFrom returns a MapEnv from the given string.
<a name="Ports"></a>
## type [Ports](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelstructs/ports.go#L5>)
```go
type Ports []uint32
```
<a name="PortsFrom"></a>
### func [PortsFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelstructs/ports.go#L8>)
```go
func PortsFrom(data string) (Ports, error)
```
PortsFrom returns a Ports from the given string.
<a name="Secrets"></a>
## type [Secrets](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelstructs/secrets.go#L5>)
```go
type Secrets []string
```
<a name="SecretsFrom"></a>
### func [SecretsFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelstructs/secrets.go#L7>)
```go
func SecretsFrom(data string) (Secrets, error)
```
<a name="TLS"></a>
## type [TLS](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelstructs/ingress.go#L10-L12>)
```go
type TLS struct {
Enabled bool `yaml:"enabled" json:"enabled,omitempty"`
}
```
<a name="ValueFrom"></a>
## type [ValueFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelstructs/valueFrom.go#L5>)
```go
type ValueFrom map[string]string
```
<a name="GetValueFrom"></a>
### func [GetValueFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labels/labelstructs/valueFrom.go#L7>)
```go
func GetValueFrom(data string) (*ValueFrom, error)
```
Generated by [gomarkdoc](<https://github.com/princjef/gomarkdoc>)

View File

@@ -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](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L193>)
## Constants
<a name="DirectoryPermission"></a>DirectoryPermission is the default values for permissions apply to created directories.
```go
const DirectoryPermission = 0o755
```
<a name="AsResourceName"></a>
## func [AsResourceName](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L196>)
```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.
<a name="Confirm"></a>
## func [Confirm](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L161>)
## func [Confirm](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L164>)
```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.
<a name="CountStartingSpaces"></a>
## func [CountStartingSpaces](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L38>)
## func [CountStartingSpaces](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L41>)
```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.
<a name="EncodeBasicYaml"></a>
## func [EncodeBasicYaml](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L175>)
## func [EncodeBasicYaml](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L178>)
```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.
<a name="FixedResourceName"></a>
## func [FixedResourceName](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L187>)
## func [FixedResourceName](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L190>)
```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.
<a name="GetContainerByName"></a>
## func [GetContainerByName](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L84>)
## func [GetContainerByName](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L87>)
```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.
<a name="GetKind"></a>
## func [GetKind](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L51>)
## func [GetKind](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L54>)
```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.
<a name="GetServiceNameByPort"></a>
## func [GetServiceNameByPort](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L74>)
## func [GetServiceNameByPort](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L77>)
```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.
<a name="GetValuesFromLabel"></a>
## func [GetValuesFromLabel](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L126>)
## func [GetValuesFromLabel](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L129>)
```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.
<a name="Int32Ptr"></a>
## func [Int32Ptr](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L32>)
## func [Int32Ptr](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L35>)
```go
func Int32Ptr(i int32) *int32
@@ -107,7 +116,7 @@ func Int32Ptr(i int32) *int32
Int32Ptr returns a pointer to an int32.
<a name="PathToName"></a>
## func [PathToName](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L103>)
## func [PathToName](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L106>)
```go
func PathToName(path string) string
@@ -116,7 +125,7 @@ func PathToName(path string) string
PathToName converts a path to a kubernetes complient name.
<a name="StrPtr"></a>
## func [StrPtr](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L35>)
## func [StrPtr](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L38>)
```go
func StrPtr(s string) *string
@@ -125,7 +134,7 @@ func StrPtr(s string) *string
StrPtr returns a pointer to a string.
<a name="TplName"></a>
## func [TplName](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L19>)
## func [TplName](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L22>)
```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.
<a name="TplValue"></a>
## func [TplValue](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L94>)
## func [TplValue](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L97>)
```go
func TplValue(serviceName, variable string, pipes ...string) string
@@ -152,7 +161,7 @@ func Warn(msg ...any)
Warn prints a warning message
<a name="WordWrap"></a>
## func [WordWrap](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L156>)
## func [WordWrap](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L159>)
```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.
<a name="Wrap"></a>
## func [Wrap](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L68>)
## func [Wrap](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L71>)
```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.
<a name="EnvConfig"></a>
## type [EnvConfig](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L120-L123>)
## type [EnvConfig](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L123-L126>)
EnvConfig is a struct to hold the description of an environment variable.

View File

@@ -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

View File

@@ -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)
}

View File

@@ -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)

View File

@@ -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

View File

@@ -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)
}

View File

@@ -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
}

View File

@@ -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)
}

View File

@@ -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

View File

@@ -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

2
generator/labels/doc.go Normal file
View File

@@ -0,0 +1,2 @@
// Package labels provides functionality to parse and manipulate labels.
package labels

View File

@@ -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 {

View File

@@ -1,2 +0,0 @@
// labelStructs is a package that contains the structs used to represent the labels in the yaml files.
package labelStructs

View File

@@ -1,4 +1,4 @@
package labelStructs
package labelstructs
import "gopkg.in/yaml.v3"

View File

@@ -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])
}
}

View File

@@ -1,4 +1,4 @@
package labelStructs
package labelstructs
import "gopkg.in/yaml.v3"

View File

@@ -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)
}
}

View File

@@ -1,4 +1,4 @@
package labelStructs
package labelstructs
import "gopkg.in/yaml.v3"

View File

@@ -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)
}
}

View File

@@ -0,0 +1,2 @@
// Package labelstructs is a package that contains the structs used to represent the labels in the yaml files.
package labelstructs

View File

@@ -1,4 +1,4 @@
package labelStructs
package labelstructs
import "gopkg.in/yaml.v3"

View File

@@ -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])
}
}

View File

@@ -1,4 +1,4 @@
package labelStructs
package labelstructs
import "gopkg.in/yaml.v3"

View File

@@ -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)
}
}

View File

@@ -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"`
}

View File

@@ -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")
}
}

View File

@@ -1,4 +1,4 @@
package labelStructs
package labelstructs
import "gopkg.in/yaml.v3"

View File

@@ -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))
}
}

View File

@@ -1,4 +1,4 @@
package labelStructs
package labelstructs
import "gopkg.in/yaml.v3"

View File

@@ -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)
}
}
}

View File

@@ -1,4 +1,4 @@
package labelStructs
package labelstructs
import (
"encoding/json"

View File

@@ -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)
}
}

View File

@@ -1,4 +1,4 @@
package labelStructs
package labelstructs
import "gopkg.in/yaml.v3"

View File

@@ -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)
}
}
}

View File

@@ -1,4 +1,4 @@
package labelStructs
package labelstructs
import "gopkg.in/yaml.v3"

View File

@@ -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"])
}
}

View File

@@ -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)

View File

@@ -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, ",")

View File

@@ -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)
}

View File

@@ -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 = "<html><body><h1>Hello, World!</h1></body></html>"
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)
}
}

View File

@@ -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."

View File

@@ -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 {