From afbd6fc1acecd130d128f27d7efe3214098dc6b9 Mon Sep 17 00:00:00 2001 From: Patrice Ferlet Date: Tue, 15 Jul 2025 21:13:22 +0200 Subject: [PATCH] fix(katenaryfile): Fix parsing katenary file It seems that "json" annotation fails to get dashed names (like configmap-files). That means that all labels in katernay.yaml file couldn't be parsed. Using `yaml` annotaiton fixes the problem. Fixes #144. --- generator/chart.go | 4 +- generator/generator.go | 4 +- generator/katenaryfile/main.go | 36 +++++++------- generator/katenaryfile/main_test.go | 55 ++++++++++++++++++++++ generator/labels/katenaryLabels.go | 2 +- generator/labels/labelstructs/configMap.go | 6 +-- 6 files changed, 81 insertions(+), 26 deletions(-) diff --git a/generator/chart.go b/generator/chart.go index 25c0f89..8bfa65e 100644 --- a/generator/chart.go +++ b/generator/chart.go @@ -348,10 +348,10 @@ func (chart *HelmChart) setSharedConf(service types.ServiceConfig, deployments m // setEnvironmentValuesFrom sets the environment values from another service. func (chart *HelmChart) setEnvironmentValuesFrom(service types.ServiceConfig, deployments map[string]*Deployment) { - if _, ok := service.Labels[labels.LabelValueFrom]; !ok { + if _, ok := service.Labels[labels.LabelValuesFrom]; !ok { return } - mapping, err := labelstructs.GetValueFrom(service.Labels[labels.LabelValueFrom]) + mapping, err := labelstructs.GetValueFrom(service.Labels[labels.LabelValuesFrom]) if err != nil { log.Fatal("error unmarshaling values-from label:", err) } diff --git a/generator/generator.go b/generator/generator.go index cbaa288..109e61b 100644 --- a/generator/generator.go +++ b/generator/generator.go @@ -226,7 +226,7 @@ func fixResourceNames(project *types.Project) error { project.Services[j] = s } // also, the value-from label should be updated - if valuefrom, ok := s.Labels[labels.LabelValueFrom]; ok { + if valuefrom, ok := s.Labels[labels.LabelValuesFrom]; ok { vf, err := labelstructs.GetValueFrom(valuefrom) if err != nil { return err @@ -240,7 +240,7 @@ func fixResourceNames(project *types.Project) error { if err != nil { return err } - s.Labels[labels.LabelValueFrom] = string(output) + s.Labels[labels.LabelValuesFrom] = string(output) } } service.Name = fixed diff --git a/generator/katenaryfile/main.go b/generator/katenaryfile/main.go index 47f4624..74c9904 100644 --- a/generator/katenaryfile/main.go +++ b/generator/katenaryfile/main.go @@ -25,22 +25,22 @@ type StringOrMap any // Service is a struct that contains the service configuration for katenary type Service struct { - MainApp *bool `json:"main-app,omitempty" jsonschema:"title=Is this service the main application"` - Values []StringOrMap `json:"values,omitempty" jsonschema:"description=Environment variables to be set in values.yaml with or without a description"` - Secrets *labelstructs.Secrets `json:"secrets,omitempty" jsonschema:"title=Secrets,description=Environment variables to be set as secrets"` - Ports *labelstructs.Ports `json:"ports,omitempty" jsonschema:"title=Ports,description=Ports to be exposed in services"` - Ingress *labelstructs.Ingress `json:"ingress,omitempty" jsonschema:"title=Ingress,description=Ingress configuration"` - HealthCheck *labelstructs.HealthCheck `json:"health-check,omitempty" jsonschema:"title=Health Check,description=Health check configuration that respects the kubernetes api"` - SamePod *string `json:"same-pod,omitempty" jsonschema:"title=Same Pod,description=Service that should be in the same pod"` - Description *string `json:"description,omitempty" jsonschema:"title=Description,description=Description of the service that will be injected in the values.yaml file"` - Ignore *bool `json:"ignore,omitempty" jsonschema:"title=Ignore,description=Ignore the service in the conversion"` - Dependencies []labelstructs.Dependency `json:"dependencies,omitempty" jsonschema:"title=Dependencies,description=Services that should be injected in the Chart.yaml file"` - ConfigMapFile *labelstructs.ConfigMapFile `json:"configmap-files,omitempty" jsonschema:"title=ConfigMap Files,description=Files that should be injected as ConfigMap"` - MapEnv *labelstructs.MapEnv `json:"map-env,omitempty" jsonschema:"title=Map Env,description=Map environment variables to another value"` - CronJob *labelstructs.CronJob `json:"cron-job,omitempty" jsonschema:"title=Cron Job,description=Cron Job configuration"` - EnvFrom *labelstructs.EnvFrom `json:"env-from,omitempty" jsonschema:"title=Env From,description=Inject environment variables from another service"` - 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)"` + MainApp *bool `yaml:"main-app,omitempty" jsonschema:"title=Is this service the main application"` + Values []StringOrMap `yaml:"values,omitempty" jsonschema:"description=Environment variables to be set in values.yaml with or without a description"` + Secrets *labelstructs.Secrets `yaml:"secrets,omitempty" jsonschema:"title=Secrets,description=Environment variables to be set as secrets"` + Ports *labelstructs.Ports `yaml:"ports,omitempty" jsonschema:"title=Ports,description=Ports to be exposed in services"` + Ingress *labelstructs.Ingress `yaml:"ingress,omitempty" jsonschema:"title=Ingress,description=Ingress configuration"` + HealthCheck *labelstructs.HealthCheck `yaml:"health-check,omitempty" jsonschema:"title=Health Check,description=Health check configuration that respects the kubernetes api"` + SamePod *string `yaml:"same-pod,omitempty" jsonschema:"title=Same Pod,description=Service that should be in the same pod"` + Description *string `yaml:"description,omitempty" jsonschema:"title=Description,description=Description of the service that will be injected in the values.yaml file"` + Ignore *bool `yaml:"ignore,omitempty" jsonschema:"title=Ignore,description=Ignore the service in the conversion"` + Dependencies []labelstructs.Dependency `yaml:"dependencies,omitempty" jsonschema:"title=Dependencies,description=Services that should be injected in the Chart.yaml file"` + ConfigMapFiles *labelstructs.ConfigMapFiles `yaml:"configmap-files,omitempty" jsonschema:"title=ConfigMap Files,description=Files that should be injected as ConfigMap"` + MapEnv *labelstructs.MapEnv `yaml:"map-env,omitempty" jsonschema:"title=Map Env,description=Map environment variables to another value"` + CronJob *labelstructs.CronJob `yaml:"cron-job,omitempty" jsonschema:"title=Cron Job,description=Cron Job configuration"` + EnvFrom *labelstructs.EnvFrom `yaml:"env-from,omitempty" jsonschema:"title=Env From,description=Inject environment variables from another service"` + ExchangeVolumes []*labelstructs.ExchangeVolume `yaml:"exchange-volumes,omitempty" jsonschema:"title=Exchange Volumes,description=Exchange volumes between services"` + ValuesFrom *labelstructs.ValueFrom `yaml:"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 @@ -93,12 +93,12 @@ func OverrideWithConfig(project *types.Project) { mustGetLabelContent(s.Description, &project.Services[i], labels.LabelDescription) mustGetLabelContent(s.Ignore, &project.Services[i], labels.LabelIgnore) mustGetLabelContent(s.Dependencies, &project.Services[i], labels.LabelDependencies) - mustGetLabelContent(s.ConfigMapFile, &project.Services[i], labels.LabelConfigMapFiles) + mustGetLabelContent(s.ConfigMapFiles, &project.Services[i], labels.LabelConfigMapFiles) mustGetLabelContent(s.MapEnv, &project.Services[i], labels.LabelMapEnv) mustGetLabelContent(s.CronJob, &project.Services[i], labels.LabelCronJob) mustGetLabelContent(s.EnvFrom, &project.Services[i], labels.LabelEnvFrom) mustGetLabelContent(s.ExchangeVolumes, &project.Services[i], labels.LabelExchangeVolume) - mustGetLabelContent(s.ValuesFrom, &project.Services[i], labels.LabelValueFrom) + mustGetLabelContent(s.ValuesFrom, &project.Services[i], labels.LabelValuesFrom) } } fmt.Println(utils.IconInfo, "Katenary file loaded successfully, the services are now configured.") diff --git a/generator/katenaryfile/main_test.go b/generator/katenaryfile/main_test.go index 263c612..8b71e9b 100644 --- a/generator/katenaryfile/main_test.go +++ b/generator/katenaryfile/main_test.go @@ -123,3 +123,58 @@ webapp: t.Fatal("Expected ingress to be defined", v) } } + +func TestOverrideConfigMapFiles(t *testing.T) { + composeContent := ` +services: + webapp: + image: nginx:latest +` + + katenaryfileContent := ` +webapp: + configmap-files: + - foo/bar + ports: + - 80 + ingress: + port: 80 +` + + // create /tmp/katenary-test-override directory, save the compose.yaml file + tmpDir, err := os.MkdirTemp("", "katenary-test-override") + if err != nil { + t.Fatalf("Failed to create temp directory: %s", err.Error()) + } + composeFile := filepath.Join(tmpDir, "compose.yaml") + katenaryFile := filepath.Join(tmpDir, "katenary.yaml") + + os.MkdirAll(tmpDir, 0755) + if err := os.WriteFile(composeFile, []byte(composeContent), 0644); err != nil { + t.Log(err) + } + if err := os.WriteFile(katenaryFile, []byte(katenaryfileContent), 0644); err != nil { + t.Log(err) + } + defer os.RemoveAll(tmpDir) + + c, _ := os.ReadFile(composeFile) + log.Println(string(c)) + + // chand dir to this directory + os.Chdir(tmpDir) + options, _ := cli.NewProjectOptions(nil, + cli.WithWorkingDirectory(tmpDir), + 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 + if v, ok := w[labels.LabelConfigMapFiles]; !ok { + t.Fatal("Expected configmap-files to be defined", v) + } +} diff --git a/generator/labels/katenaryLabels.go b/generator/labels/katenaryLabels.go index 550520f..c926fc5 100644 --- a/generator/labels/katenaryLabels.go +++ b/generator/labels/katenaryLabels.go @@ -34,7 +34,7 @@ const ( LabelCronJob Label = KatenaryLabelPrefix + "/cronjob" LabelEnvFrom Label = KatenaryLabelPrefix + "/env-from" LabelExchangeVolume Label = KatenaryLabelPrefix + "/exchange-volumes" - LabelValueFrom Label = KatenaryLabelPrefix + "/values-from" + LabelValuesFrom Label = KatenaryLabelPrefix + "/values-from" ) var ( diff --git a/generator/labels/labelstructs/configMap.go b/generator/labels/labelstructs/configMap.go index a771d7b..c56fa94 100644 --- a/generator/labels/labelstructs/configMap.go +++ b/generator/labels/labelstructs/configMap.go @@ -2,10 +2,10 @@ package labelstructs import "gopkg.in/yaml.v3" -type ConfigMapFile []string +type ConfigMapFiles []string -func ConfigMapFileFrom(data string) (ConfigMapFile, error) { - var mapping ConfigMapFile +func ConfigMapFileFrom(data string) (ConfigMapFiles, error) { + var mapping ConfigMapFiles if err := yaml.Unmarshal([]byte(data), &mapping); err != nil { return nil, err }