From 73be50588ad97554347ed48b6e8334e342b3a4e8 Mon Sep 17 00:00:00 2001 From: Joshua Edward McLaughlin Cox Date: Sun, 30 Nov 2025 17:18:19 -0600 Subject: [PATCH] svc-optional --- README.md | 1 + doc/docs/labels.md | 16 ++++++++++++++++ .../packages/internal/generator/katenaryfile.md | 1 + doc/docs/packages/internal/generator/labels.md | 1 + doc/docs/usage.md | 2 +- internal/generator/chart.go | 6 ++++++ internal/generator/generator.go | 13 +++++++++++++ internal/generator/katenaryfile/main.go | 2 ++ internal/generator/labels/katenaryLabels.go | 1 + internal/generator/labels/katenaryLabelsDoc.yaml | 6 ++++++ internal/generator/utils.go | 8 ++++++++ katenary.json | 5 +++++ 12 files changed, 61 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e38cfaf..c3e0268 100644 --- a/README.md +++ b/README.md @@ -238,6 +238,7 @@ katenary.v3/env-from: []string Add environment variables from another service katenary.v3/exchange-volumes: []object Add exchange volumes (empty directory on the node) to share data katenary.v3/health-check: object Health check to be added to the deployment. katenary.v3/ignore: bool Ignore the service +katenary.v3/svc-optional: bool Make the service optional. katenary.v3/ingress: object Ingress rules to be added to the service. katenary.v3/main-app: bool Mark the service as the main app. katenary.v3/map-env: map[string]string Map env vars from the service to the deployment. diff --git a/doc/docs/labels.md b/doc/docs/labels.md index 43409ae..f47ffc8 100644 --- a/doc/docs/labels.md +++ b/doc/docs/labels.md @@ -26,6 +26,7 @@ Katenary will try to _Unmarshal_ these labels. | `katenary.v3/exchange-volumes` | Add exchange volumes (empty directory on the node) to share data | `[]object` | | `katenary.v3/health-check` | Health check to be added to the deployment. | `object` | | `katenary.v3/ignore` | Ignore the service | `bool` | +| `katenary.v3/svc-optional` | Make the service optional | `bool` | | `katenary.v3/ingress` | Ingress rules to be added to the service. | `object` | | `katenary.v3/main-app` | Mark the service as the main app. | `bool` | | `katenary.v3/map-env` | Map env vars from the service to the deployment. | `map[string]string` | @@ -270,6 +271,21 @@ labels: katenary.v3/ignore: "true" ``` +### katenary.v3/svc-optional + +Make the service optional + +**Type**: `bool` + +Making a service to be optional in the exported helm chart. + +**Example:** + +```yaml +labels: + katenary.v3/svc-optional: "true" +``` + ### katenary.v3/ingress diff --git a/doc/docs/packages/internal/generator/katenaryfile.md b/doc/docs/packages/internal/generator/katenaryfile.md index 214133a..c606181 100644 --- a/doc/docs/packages/internal/generator/katenaryfile.md +++ b/doc/docs/packages/internal/generator/katenaryfile.md @@ -45,6 +45,7 @@ type Service struct { SamePod *string `yaml:"same-pod,omitempty" json:"same-pod,omitempty" jsonschema:"title=Same Pod,description=Service that should be in the same pod"` Description *string `yaml:"description,omitempty" json:"description,omitempty" jsonschema:"title=Description,description=Description of the service that will be injected in the values.yaml file"` Ignore *bool `yaml:"ignore,omitempty" json:"ignore,omitempty" jsonschema:"title=Ignore,description=Ignore the service in the conversion"` + SvcOptional *bool `yaml:"svc-optional,omitempty" json:"svc-optional,omitempty" jsonschema:"title=SvcOptional,description=SvcOptional the service in the conversion"` Dependencies []labelstructs.Dependency `yaml:"dependencies,omitempty" json:"dependencies,omitempty" jsonschema:"title=Dependencies,description=Services that should be injected in the Chart.yaml file"` ConfigMapFiles *labelstructs.ConfigMapFiles `yaml:"configmap-files,omitempty" json:"configmap-files,omitempty" jsonschema:"title=ConfigMap Files,description=Files that should be injected as ConfigMap"` MapEnv *labelstructs.MapEnv `yaml:"map-env,omitempty" json:"map-env,omitempty" jsonschema:"title=Map Env,description=Map environment variables to another value"` diff --git a/doc/docs/packages/internal/generator/labels.md b/doc/docs/packages/internal/generator/labels.md index 617c95c..c7a9c40 100644 --- a/doc/docs/packages/internal/generator/labels.md +++ b/doc/docs/packages/internal/generator/labels.md @@ -89,6 +89,7 @@ const ( LabelSamePod Label = KatenaryLabelPrefix + "/same-pod" LabelDescription Label = KatenaryLabelPrefix + "/description" LabelIgnore Label = KatenaryLabelPrefix + "/ignore" + LabelSvcOptional Label = KatenaryLabelPrefix + "/svc-optional" LabelDependencies Label = KatenaryLabelPrefix + "/dependencies" LabelConfigMapFiles Label = KatenaryLabelPrefix + "/configmap-files" LabelCronJob Label = KatenaryLabelPrefix + "/cronjob" diff --git a/doc/docs/usage.md b/doc/docs/usage.md index 9d0ae8b..0ccaaf7 100644 --- a/doc/docs/usage.md +++ b/doc/docs/usage.md @@ -102,7 +102,7 @@ Katenary transforms compose services this way: For any other specific configuration, like binding local files as `ConfigMap`, bind variables, add values with documentation, etc. You'll need to use labels. -Katenary can also configure containers grouping in pods, declare dependencies, ignore some services, force variables as +Katenary can also configure containers grouping in pods, declare dependencies, ignore some services, make some services optional, force variables as secrets, mount files as `configMap`, and many others things. To adapt the helm chart generation, you will need to use some specific labels. diff --git a/internal/generator/chart.go b/internal/generator/chart.go index 39289c9..b01da64 100644 --- a/internal/generator/chart.go +++ b/internal/generator/chart.go @@ -200,6 +200,12 @@ func (chart *HelmChart) generateDeployment(service types.ServiceConfig, deployme logger.Info("Ignoring service ", service.Name) return nil } + + // isgnored service + if isSvcOptional(service) { + logger.Info("Optional service ", service.Name) + return nil + } // helm dependency if isHelmDependency, err := chart.setDependencies(service); err != nil { diff --git a/internal/generator/generator.go b/internal/generator/generator.go index 4e5d60c..b275a50 100644 --- a/internal/generator/generator.go +++ b/internal/generator/generator.go @@ -50,6 +50,9 @@ func Generate(project *types.Project) (*HelmChart, error) { // drop all services with the "ignore" label dropIngoredServices(project) + // optional all services with the "svc-optional" label + makeSvcOptionalServices(project) + fixContainerNames(project) // rename all services name to remove dashes @@ -223,6 +226,16 @@ func dropIngoredServices(project *types.Project) { } } +// makeSvcOptionalServices makes all services optional with the "svc-optional" label set to true (or yes). +func makeSvcOptionalServices(project *types.Project) { + for name, service := range project.Services { + if isSvcOptional(service) { + // delete(project.Services, name) + // make optional + } + } +} + // fixResourceNames renames all services and related resources to remove dashes. func fixResourceNames(project *types.Project) error { // rename all services name to remove dashes diff --git a/internal/generator/katenaryfile/main.go b/internal/generator/katenaryfile/main.go index f8a37d7..5556fd5 100644 --- a/internal/generator/katenaryfile/main.go +++ b/internal/generator/katenaryfile/main.go @@ -34,6 +34,7 @@ type Service struct { SamePod *string `yaml:"same-pod,omitempty" json:"same-pod,omitempty" jsonschema:"title=Same Pod,description=Service that should be in the same pod"` Description *string `yaml:"description,omitempty" json:"description,omitempty" jsonschema:"title=Description,description=Description of the service that will be injected in the values.yaml file"` Ignore *bool `yaml:"ignore,omitempty" json:"ignore,omitempty" jsonschema:"title=Ignore,description=Ignore the service in the conversion"` + SvcOptional *bool `yaml:"svc-optional,omitempty" json:"svc-optional,omitempty" jsonschema:"title=SvcOptional,description=SvcOptional the service in the conversion"` Dependencies []labelstructs.Dependency `yaml:"dependencies,omitempty" json:"dependencies,omitempty" jsonschema:"title=Dependencies,description=Services that should be injected in the Chart.yaml file"` ConfigMapFiles *labelstructs.ConfigMapFiles `yaml:"configmap-files,omitempty" json:"configmap-files,omitempty" jsonschema:"title=ConfigMap Files,description=Files that should be injected as ConfigMap"` MapEnv *labelstructs.MapEnv `yaml:"map-env,omitempty" json:"map-env,omitempty" jsonschema:"title=Map Env,description=Map environment variables to another value"` @@ -94,6 +95,7 @@ func OverrideWithConfig(project *types.Project) { mustGetLabelContent(s.SamePod, labels.LabelSamePod) mustGetLabelContent(s.Description, labels.LabelDescription) mustGetLabelContent(s.Ignore, labels.LabelIgnore) + mustGetLabelContent(s.SvcOptional, labels.LabelSvcOptional) mustGetLabelContent(s.Dependencies, labels.LabelDependencies) mustGetLabelContent(s.ConfigMapFiles, labels.LabelConfigMapFiles) mustGetLabelContent(s.MapEnv, labels.LabelMapEnv) diff --git a/internal/generator/labels/katenaryLabels.go b/internal/generator/labels/katenaryLabels.go index ac8dc30..2440b39 100644 --- a/internal/generator/labels/katenaryLabels.go +++ b/internal/generator/labels/katenaryLabels.go @@ -30,6 +30,7 @@ const ( LabelSamePod Label = KatenaryLabelPrefix + "/same-pod" LabelDescription Label = KatenaryLabelPrefix + "/description" LabelIgnore Label = KatenaryLabelPrefix + "/ignore" + LabelSvcOptional Label = KatenaryLabelPrefix + "/svc-optional" LabelDependencies Label = KatenaryLabelPrefix + "/dependencies" LabelConfigMapFiles Label = KatenaryLabelPrefix + "/configmap-files" LabelCronJob Label = KatenaryLabelPrefix + "/cronjob" diff --git a/internal/generator/labels/katenaryLabelsDoc.yaml b/internal/generator/labels/katenaryLabelsDoc.yaml index 5833b3f..99854bb 100644 --- a/internal/generator/labels/katenaryLabelsDoc.yaml +++ b/internal/generator/labels/katenaryLabelsDoc.yaml @@ -183,6 +183,12 @@ example: "labels:\n {{ .KatenaryPrefix }}/ignore: \"true\"" type: "bool" +"svc-optional": + short: "Make the service optional in the resulting helm chart" + long: "Making a service optional to be exported in helm chart." + example: "labels:\n {{ .KatenaryPrefix }}/svc-optional: \"true\"" + type: "bool" + "dependencies": short: "Add Helm dependencies to the service." long: |- diff --git a/internal/generator/utils.go b/internal/generator/utils.go index 6150d55..7224503 100644 --- a/internal/generator/utils.go +++ b/internal/generator/utils.go @@ -83,6 +83,14 @@ func isIgnored(service types.ServiceConfig) bool { return false } +// isSvcOptionald returns true if the service is optional. +func isSvcOptional(service types.ServiceConfig) bool { + if v, ok := service.Labels[labels.LabelSvcOptional]; ok { + return v == "true" || v == "yes" || v == "1" + } + return false +} + // UnWrapTPL removes the line wrapping from a template. func UnWrapTPL(in []byte) []byte { return regexpLineWrap.ReplaceAll(in, []byte(" }}")) diff --git a/katenary.json b/katenary.json index 9728b35..5ac5017 100644 --- a/katenary.json +++ b/katenary.json @@ -309,6 +309,11 @@ "title": "Ignore", "description": "Ignore the service in the conversion" }, + "svc-optional": { + "type": "boolean", + "title": "SvcOptional", + "description": "Make the service optional in the conversion" + }, "dependencies": { "items": { "$ref": "#/$defs/Dependency"