2022-06-22 09:38:07 +02:00
|
|
|
package generator
|
|
|
|
|
|
|
|
import (
|
2023-12-06 15:24:02 +01:00
|
|
|
"fmt"
|
|
|
|
"log"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"regexp"
|
|
|
|
"strings"
|
|
|
|
"time"
|
2022-06-22 09:38:07 +02:00
|
|
|
|
2024-04-05 07:56:27 +02:00
|
|
|
"katenary/utils"
|
|
|
|
|
2022-06-22 09:38:07 +02:00
|
|
|
"github.com/compose-spec/compose-go/types"
|
2023-12-06 15:24:02 +01:00
|
|
|
appsv1 "k8s.io/api/apps/v1"
|
|
|
|
corev1 "k8s.io/api/core/v1"
|
|
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
|
|
"sigs.k8s.io/yaml"
|
2022-06-22 09:38:07 +02:00
|
|
|
)
|
|
|
|
|
2023-12-06 15:24:02 +01:00
|
|
|
var _ Yaml = (*Deployment)(nil)
|
2022-06-22 09:38:07 +02:00
|
|
|
|
2024-04-19 11:13:24 +02:00
|
|
|
type mountPathConfig struct {
|
|
|
|
mountPath string
|
|
|
|
subPath string
|
|
|
|
}
|
|
|
|
|
|
|
|
type ConfigMapMount struct {
|
|
|
|
configMap *ConfigMap
|
|
|
|
mountPath []mountPathConfig
|
|
|
|
}
|
|
|
|
|
2023-12-06 15:24:02 +01:00
|
|
|
// Deployment is a kubernetes Deployment.
|
|
|
|
type Deployment struct {
|
|
|
|
*appsv1.Deployment `yaml:",inline"`
|
2024-04-19 11:13:24 +02:00
|
|
|
chart *HelmChart `yaml:"-"`
|
|
|
|
configMaps map[string]*ConfigMapMount `yaml:"-"`
|
|
|
|
service *types.ServiceConfig `yaml:"-"`
|
|
|
|
defaultTag string `yaml:"-"`
|
|
|
|
isMainApp bool `yaml:"-"`
|
2023-12-06 15:24:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewDeployment creates a new Deployment from a compose service. The appName is the name of the application taken from the project name.
|
|
|
|
// It also creates the Values map that will be used to create the values.yaml file.
|
|
|
|
func NewDeployment(service types.ServiceConfig, chart *HelmChart) *Deployment {
|
|
|
|
isMainApp := false
|
|
|
|
if mainLabel, ok := service.Labels[LABEL_MAIN_APP]; ok {
|
|
|
|
main := strings.ToLower(mainLabel)
|
|
|
|
isMainApp = main == "true" || main == "yes" || main == "1"
|
|
|
|
}
|
|
|
|
|
|
|
|
defaultTag := `default "latest"`
|
|
|
|
if isMainApp {
|
|
|
|
defaultTag = `default .Chart.AppVersion "latest"`
|
|
|
|
}
|
|
|
|
|
|
|
|
chart.Values[service.Name] = NewValue(service, isMainApp)
|
|
|
|
appName := chart.Name
|
|
|
|
|
|
|
|
dep := &Deployment{
|
|
|
|
isMainApp: isMainApp,
|
|
|
|
defaultTag: defaultTag,
|
|
|
|
service: &service,
|
|
|
|
chart: chart,
|
|
|
|
Deployment: &appsv1.Deployment{
|
|
|
|
TypeMeta: metav1.TypeMeta{
|
|
|
|
Kind: "Deployment",
|
|
|
|
APIVersion: "apps/v1",
|
|
|
|
},
|
|
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
|
|
Name: utils.TplName(service.Name, appName),
|
|
|
|
Labels: GetLabels(service.Name, appName),
|
|
|
|
Annotations: Annotations,
|
|
|
|
},
|
|
|
|
Spec: appsv1.DeploymentSpec{
|
|
|
|
Replicas: utils.Int32Ptr(1),
|
|
|
|
Selector: &metav1.LabelSelector{
|
|
|
|
MatchLabels: GetMatchLabels(service.Name, appName),
|
|
|
|
},
|
|
|
|
Template: corev1.PodTemplateSpec{
|
|
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
|
|
Labels: GetMatchLabels(service.Name, appName),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2024-04-19 11:13:24 +02:00
|
|
|
configMaps: map[string]*ConfigMapMount{},
|
2023-12-06 15:24:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// add containers
|
|
|
|
dep.AddContainer(service)
|
|
|
|
|
|
|
|
// add volumes
|
|
|
|
dep.AddVolumes(service, appName)
|
|
|
|
|
|
|
|
if service.Environment != nil {
|
|
|
|
dep.SetEnvFrom(service, appName)
|
|
|
|
}
|
|
|
|
|
|
|
|
return dep
|
|
|
|
}
|
|
|
|
|
|
|
|
// DependsOn adds a initContainer to the deployment that will wait for the service to be up.
|
2024-04-03 22:22:48 +02:00
|
|
|
func (d *Deployment) DependsOn(to *Deployment, servicename string) error {
|
2023-12-06 15:24:02 +01:00
|
|
|
// Add a initContainer with busybox:latest using netcat to check if the service is up
|
|
|
|
// it will wait until the service responds to all ports
|
|
|
|
for _, container := range to.Spec.Template.Spec.Containers {
|
|
|
|
commands := []string{}
|
2024-04-03 22:22:48 +02:00
|
|
|
if len(container.Ports) == 0 {
|
|
|
|
utils.Warn("No ports found for service ", servicename, ". You should declare a port in the service or use "+LABEL_PORTS+" label.")
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
2023-12-06 15:24:02 +01:00
|
|
|
for _, port := range container.Ports {
|
|
|
|
command := fmt.Sprintf("until nc -z %s %d; do\n sleep 1;\ndone", to.Name, port.ContainerPort)
|
|
|
|
commands = append(commands, command)
|
|
|
|
}
|
|
|
|
|
|
|
|
command := []string{"/bin/sh", "-c", strings.Join(commands, "\n")}
|
|
|
|
d.Spec.Template.Spec.InitContainers = append(d.Spec.Template.Spec.InitContainers, corev1.Container{
|
|
|
|
Name: "wait-for-" + to.service.Name,
|
|
|
|
Image: "busybox:latest",
|
|
|
|
Command: command,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// AddContainer adds a container to the deployment.
|
|
|
|
func (d *Deployment) AddContainer(service types.ServiceConfig) {
|
|
|
|
ports := []corev1.ContainerPort{}
|
|
|
|
|
|
|
|
for _, port := range service.Ports {
|
|
|
|
name := utils.GetServiceNameByPort(int(port.Target))
|
|
|
|
if name == "" {
|
|
|
|
utils.Warn("Port name not found for port ", port.Target, " in service ", service.Name, ". Using port number instead")
|
2024-04-08 23:15:05 +02:00
|
|
|
name = fmt.Sprintf("port-%d", port.Target)
|
2023-12-06 15:24:02 +01:00
|
|
|
}
|
|
|
|
ports = append(ports, corev1.ContainerPort{
|
|
|
|
ContainerPort: int32(port.Target),
|
|
|
|
Name: name,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
container := corev1.Container{
|
|
|
|
Image: utils.TplValue(service.Name, "repository.image") + ":" +
|
|
|
|
utils.TplValue(service.Name, "repository.tag", d.defaultTag),
|
|
|
|
Ports: ports,
|
|
|
|
Name: service.Name,
|
|
|
|
ImagePullPolicy: corev1.PullIfNotPresent,
|
|
|
|
}
|
|
|
|
if _, ok := d.chart.Values[service.Name]; !ok {
|
|
|
|
d.chart.Values[service.Name] = NewValue(service, d.isMainApp)
|
|
|
|
}
|
|
|
|
d.chart.Values[service.Name].(*Value).ImagePullPolicy = string(corev1.PullIfNotPresent)
|
|
|
|
|
|
|
|
// add an imagePullSecret, it actually does not work because the secret is not
|
|
|
|
// created but it add the reference in the YAML file. We'll change it in Yaml()
|
|
|
|
// method.
|
|
|
|
d.Spec.Template.Spec.ImagePullSecrets = []corev1.LocalObjectReference{{
|
|
|
|
Name: `{{ .Values.pullSecrets | toYaml | indent __indent__ }}`,
|
|
|
|
}}
|
|
|
|
|
|
|
|
d.AddHealthCheck(service, &container)
|
|
|
|
|
|
|
|
d.Spec.Template.Spec.Containers = append(d.Spec.Template.Spec.Containers, container)
|
|
|
|
}
|
|
|
|
|
|
|
|
// AddIngress adds an ingress to the deployment. It creates the ingress object.
|
|
|
|
func (d *Deployment) AddIngress(service types.ServiceConfig, appName string) *Ingress {
|
|
|
|
return NewIngress(service, d.chart)
|
|
|
|
}
|
|
|
|
|
|
|
|
// AddVolumes adds a volume to the deployment. It does not create the PVC, it only adds the volumes to the deployment.
|
|
|
|
// If the volume is a bind volume it will warn the user that it is not supported yet.
|
|
|
|
func (d *Deployment) AddVolumes(service types.ServiceConfig, appName string) {
|
|
|
|
tobind := map[string]bool{}
|
|
|
|
if v, ok := service.Labels[LABEL_CM_FILES]; ok {
|
|
|
|
binds := []string{}
|
|
|
|
if err := yaml.Unmarshal([]byte(v), &binds); err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
for _, bind := range binds {
|
|
|
|
tobind[bind] = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
isSamePod := false
|
|
|
|
if v, ok := service.Labels[LABEL_SAME_POD]; !ok {
|
|
|
|
isSamePod = false
|
|
|
|
} else {
|
|
|
|
isSamePod = v != ""
|
|
|
|
}
|
|
|
|
|
2024-04-19 11:13:24 +02:00
|
|
|
container, index := utils.GetContainerByName(service.Name, d.Spec.Template.Spec.Containers)
|
2023-12-06 15:24:02 +01:00
|
|
|
for _, volume := range service.Volumes {
|
|
|
|
// not declared as a bind volume, skip
|
|
|
|
if _, ok := tobind[volume.Source]; !isSamePod && volume.Type == "bind" && !ok {
|
|
|
|
utils.Warn(
|
|
|
|
"Bind volumes are not supported yet, " +
|
|
|
|
"excepting for those declared as " +
|
|
|
|
LABEL_CM_FILES +
|
|
|
|
", skipping volume " + volume.Source +
|
|
|
|
" from service " + service.Name,
|
|
|
|
)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if container == nil {
|
|
|
|
utils.Warn("Container not found for volume", volume.Source)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// ensure that the volume is not already present in the container
|
|
|
|
for _, vm := range container.VolumeMounts {
|
|
|
|
if vm.Name == volume.Source {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch volume.Type {
|
|
|
|
case "volume":
|
|
|
|
// Add volume to container
|
|
|
|
container.VolumeMounts = append(container.VolumeMounts, corev1.VolumeMount{
|
|
|
|
Name: volume.Source,
|
|
|
|
MountPath: volume.Target,
|
|
|
|
})
|
|
|
|
// Add volume to values.yaml only if it the service is not in the same pod that another service.
|
|
|
|
// If it is in the same pod, the volume will be added to the other service later
|
|
|
|
if _, ok := service.Labels[LABEL_SAME_POD]; !ok {
|
|
|
|
d.chart.Values[service.Name].(*Value).AddPersistence(volume.Source)
|
|
|
|
}
|
|
|
|
// Add volume to deployment
|
|
|
|
d.Spec.Template.Spec.Volumes = append(d.Spec.Template.Spec.Volumes, corev1.Volume{
|
|
|
|
Name: volume.Source,
|
|
|
|
VolumeSource: corev1.VolumeSource{
|
|
|
|
PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{
|
|
|
|
ClaimName: utils.TplName(service.Name, appName, volume.Source),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
case "bind":
|
|
|
|
// Add volume to container
|
|
|
|
stat, err := os.Stat(volume.Source)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
2024-04-19 11:13:24 +02:00
|
|
|
|
2023-12-06 15:24:02 +01:00
|
|
|
if stat.IsDir() {
|
2024-04-19 11:13:24 +02:00
|
|
|
pathnme := utils.PathToName(volume.Source)
|
|
|
|
if _, ok := d.configMaps[pathnme]; !ok {
|
|
|
|
d.configMaps[pathnme] = &ConfigMapMount{
|
|
|
|
mountPath: []mountPathConfig{},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: make it recursive to add all files in the directory and subdirectories
|
|
|
|
_, err := os.ReadDir(volume.Source)
|
2023-12-06 15:24:02 +01:00
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
2024-04-19 11:13:24 +02:00
|
|
|
cm := NewConfigMapFromDirectory(service, appName, volume.Source)
|
|
|
|
d.configMaps[pathnme] = &ConfigMapMount{
|
|
|
|
configMap: cm,
|
|
|
|
mountPath: append(d.configMaps[pathnme].mountPath, mountPathConfig{
|
|
|
|
mountPath: volume.Target,
|
|
|
|
}),
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
dirname := filepath.Dir(volume.Source)
|
|
|
|
pathnme := utils.PathToName(dirname)
|
|
|
|
var cm *ConfigMap
|
|
|
|
if v, ok := d.configMaps[pathnme]; !ok {
|
|
|
|
cm = NewConfigMap(*d.service, appName)
|
|
|
|
cm.usage = FileMapUsageFiles
|
|
|
|
cm.path = dirname
|
|
|
|
cm.Name = utils.TplName(service.Name, appName) + "-" + pathnme
|
|
|
|
d.configMaps[pathnme] = &ConfigMapMount{
|
|
|
|
configMap: cm,
|
|
|
|
mountPath: []mountPathConfig{},
|
2023-12-06 15:24:02 +01:00
|
|
|
}
|
2024-04-19 11:13:24 +02:00
|
|
|
} else {
|
|
|
|
cm = v.configMap
|
|
|
|
}
|
|
|
|
|
|
|
|
cm.AppendFile(volume.Source)
|
|
|
|
d.configMaps[pathnme] = &ConfigMapMount{
|
|
|
|
configMap: cm,
|
|
|
|
mountPath: append(d.configMaps[pathnme].mountPath, mountPathConfig{
|
|
|
|
mountPath: volume.Target,
|
|
|
|
subPath: filepath.Base(volume.Source),
|
|
|
|
}),
|
2023-12-06 15:24:02 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2024-04-19 11:13:24 +02:00
|
|
|
|
|
|
|
d.Spec.Template.Spec.Containers[index] = *container
|
2023-12-06 15:24:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Deployment) BindFrom(service types.ServiceConfig, binded *Deployment) {
|
|
|
|
// find the volume in the binded deployment
|
|
|
|
for _, bindedVolume := range binded.Spec.Template.Spec.Volumes {
|
|
|
|
skip := false
|
|
|
|
for _, targetVol := range d.Spec.Template.Spec.Volumes {
|
|
|
|
if targetVol.Name == bindedVolume.Name {
|
|
|
|
skip = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !skip {
|
|
|
|
// add the volume to the current deployment
|
|
|
|
d.Spec.Template.Spec.Volumes = append(d.Spec.Template.Spec.Volumes, bindedVolume)
|
|
|
|
// get the container
|
|
|
|
}
|
|
|
|
// add volume mount to the container
|
|
|
|
targetContainer, ti := utils.GetContainerByName(service.Name, d.Spec.Template.Spec.Containers)
|
|
|
|
sourceContainer, _ := utils.GetContainerByName(service.Name, binded.Spec.Template.Spec.Containers)
|
|
|
|
for _, bindedMount := range sourceContainer.VolumeMounts {
|
|
|
|
if bindedMount.Name == bindedVolume.Name {
|
|
|
|
targetContainer.VolumeMounts = append(targetContainer.VolumeMounts, bindedMount)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
d.Spec.Template.Spec.Containers[ti] = *targetContainer
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetEnvFrom sets the environment variables to a configmap. The configmap is created.
|
|
|
|
func (d *Deployment) SetEnvFrom(service types.ServiceConfig, appName string) {
|
|
|
|
if len(service.Environment) == 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
drop := []string{}
|
|
|
|
secrets := []string{}
|
|
|
|
|
|
|
|
// secrets from label
|
|
|
|
labelSecrets := []string{}
|
|
|
|
if v, ok := service.Labels[LABEL_SECRETS]; ok {
|
|
|
|
err := yaml.Unmarshal([]byte(v), &labelSecrets)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// values from label
|
|
|
|
varDescriptons := utils.GetValuesFromLabel(service, LABEL_VALUES)
|
|
|
|
labelValues := []string{}
|
|
|
|
for v := range varDescriptons {
|
|
|
|
labelValues = append(labelValues, v)
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, secret := range labelSecrets {
|
|
|
|
// get the secret name
|
|
|
|
_, ok := service.Environment[secret]
|
|
|
|
if !ok {
|
|
|
|
drop = append(drop, secret)
|
|
|
|
utils.Warn("Secret " + secret + " not found in service " + service.Name + " - skpped")
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
secrets = append(secrets, secret)
|
|
|
|
}
|
|
|
|
|
|
|
|
// for each values from label "values", add it to Values map and change the envFrom
|
|
|
|
// value to {{ .Values.<service>.<value> }}
|
|
|
|
for _, value := range labelValues {
|
|
|
|
// get the environment variable name
|
|
|
|
val, ok := service.Environment[value]
|
|
|
|
if !ok {
|
|
|
|
drop = append(drop, value)
|
|
|
|
utils.Warn("Environment variable " + value + " not found in service " + service.Name + " - skpped")
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if d.chart.Values[service.Name].(*Value).Environment == nil {
|
|
|
|
d.chart.Values[service.Name].(*Value).Environment = make(map[string]any)
|
|
|
|
}
|
|
|
|
d.chart.Values[service.Name].(*Value).Environment[value] = *val
|
|
|
|
// set the environment variable to bind to the values.yaml file
|
|
|
|
v := utils.TplValue(service.Name, "environment."+value)
|
|
|
|
service.Environment[value] = &v
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, value := range drop {
|
|
|
|
delete(service.Environment, value)
|
|
|
|
}
|
|
|
|
|
|
|
|
fromSources := []corev1.EnvFromSource{}
|
|
|
|
|
|
|
|
if len(service.Environment) > 0 {
|
|
|
|
fromSources = append(fromSources, corev1.EnvFromSource{
|
|
|
|
ConfigMapRef: &corev1.ConfigMapEnvSource{
|
|
|
|
LocalObjectReference: corev1.LocalObjectReference{
|
|
|
|
Name: utils.TplName(service.Name, appName),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(secrets) > 0 {
|
|
|
|
fromSources = append(fromSources, corev1.EnvFromSource{
|
|
|
|
SecretRef: &corev1.SecretEnvSource{
|
|
|
|
LocalObjectReference: corev1.LocalObjectReference{
|
|
|
|
Name: utils.TplName(service.Name, appName),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
container, index := utils.GetContainerByName(service.Name, d.Spec.Template.Spec.Containers)
|
|
|
|
if container == nil {
|
|
|
|
utils.Warn("Container not found for service " + service.Name)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
container.EnvFrom = append(container.EnvFrom, fromSources...)
|
|
|
|
|
|
|
|
if container.Env == nil {
|
|
|
|
container.Env = []corev1.EnvVar{}
|
|
|
|
}
|
|
|
|
|
|
|
|
d.Spec.Template.Spec.Containers[index] = *container
|
|
|
|
}
|
2022-06-22 09:38:07 +02:00
|
|
|
|
2023-12-06 15:24:02 +01:00
|
|
|
func (d *Deployment) AddHealthCheck(service types.ServiceConfig, container *corev1.Container) {
|
|
|
|
// get the label for healthcheck
|
|
|
|
if v, ok := service.Labels[LABEL_HEALTHCHECK]; ok {
|
|
|
|
probes := struct {
|
|
|
|
LivenessProbe *corev1.Probe `yaml:"livenessProbe"`
|
|
|
|
ReadinessProbe *corev1.Probe `yaml:"readinessProbe"`
|
|
|
|
}{}
|
|
|
|
err := yaml.Unmarshal([]byte(v), &probes)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
container.LivenessProbe = probes.LivenessProbe
|
|
|
|
container.ReadinessProbe = probes.ReadinessProbe
|
|
|
|
return
|
2022-06-22 09:38:07 +02:00
|
|
|
}
|
|
|
|
|
2023-12-06 15:24:02 +01:00
|
|
|
if service.HealthCheck != nil {
|
|
|
|
period := 30.0
|
|
|
|
if service.HealthCheck.Interval != nil {
|
|
|
|
period = time.Duration(*service.HealthCheck.Interval).Seconds()
|
|
|
|
}
|
|
|
|
container.LivenessProbe = &corev1.Probe{
|
|
|
|
ProbeHandler: corev1.ProbeHandler{
|
|
|
|
Exec: &corev1.ExecAction{
|
|
|
|
Command: service.HealthCheck.Test[1:],
|
|
|
|
},
|
|
|
|
},
|
|
|
|
PeriodSeconds: int32(period),
|
2022-06-22 09:38:07 +02:00
|
|
|
}
|
|
|
|
}
|
2023-12-06 15:24:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Yaml returns the yaml representation of the deployment.
|
|
|
|
func (d *Deployment) Yaml() ([]byte, error) {
|
|
|
|
serviceName := d.service.Name
|
|
|
|
y, err := yaml.Marshal(d)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2022-06-22 09:38:07 +02:00
|
|
|
|
2023-12-06 15:24:02 +01:00
|
|
|
// for each volume mount, add a condition "if values has persistence"
|
|
|
|
changing := false
|
|
|
|
content := strings.Split(string(y), "\n")
|
|
|
|
spaces := ""
|
|
|
|
volumeName := ""
|
|
|
|
|
|
|
|
// this loop add condition for each volume mount
|
|
|
|
for line, volume := range content {
|
|
|
|
// find the volume name
|
|
|
|
for i := line; i < len(content); i++ {
|
|
|
|
if strings.Contains(content[i], "name: ") {
|
|
|
|
volumeName = strings.TrimSpace(strings.Replace(content[i], "name: ", "", 1))
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if volumeName == "" {
|
2022-06-22 09:38:07 +02:00
|
|
|
continue
|
2023-12-06 15:24:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if _, ok := d.configMaps[volumeName]; ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if strings.Contains(volume, "- mountPath: ") {
|
|
|
|
spaces = strings.Repeat(" ", utils.CountStartingSpaces(volume))
|
|
|
|
content[line] = spaces + `{{- if .Values.` + serviceName + `.persistence.` + volumeName + `.enabled }}` + "\n" + volume
|
|
|
|
changing = true
|
|
|
|
}
|
|
|
|
if strings.Contains(volume, "name: ") && changing {
|
|
|
|
content[line] = volume + "\n" + spaces + "{{- end }}"
|
|
|
|
changing = false
|
2022-06-22 09:38:07 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-06 15:24:02 +01:00
|
|
|
changing = false
|
|
|
|
inVolumes := false
|
|
|
|
volumeName = ""
|
|
|
|
// this loop changes imagePullPolicy to {{ .Values.<service>.imagePullPolicy }}
|
|
|
|
// and the volume definition adding the condition "if values has persistence"
|
|
|
|
for i, line := range content {
|
|
|
|
|
|
|
|
if strings.Contains(line, "imagePullPolicy:") {
|
|
|
|
spaces = strings.Repeat(" ", utils.CountStartingSpaces(line))
|
|
|
|
content[i] = spaces + "imagePullPolicy: {{ .Values." + serviceName + ".imagePullPolicy }}"
|
|
|
|
}
|
|
|
|
|
|
|
|
// find the volume name
|
|
|
|
for i := i; i < len(content); i++ {
|
|
|
|
if strings.Contains(content[i], "- name: ") {
|
|
|
|
volumeName = strings.TrimSpace(strings.Replace(content[i], "- name: ", "", 1))
|
|
|
|
break
|
2022-06-22 09:38:07 +02:00
|
|
|
}
|
|
|
|
}
|
2023-12-06 15:24:02 +01:00
|
|
|
if strings.Contains(line, "volumes:") {
|
|
|
|
inVolumes = true
|
|
|
|
}
|
|
|
|
|
|
|
|
if volumeName == "" {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, ok := d.configMaps[volumeName]; ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if strings.Contains(line, "- name: ") && inVolumes {
|
|
|
|
spaces = strings.Repeat(" ", utils.CountStartingSpaces(line))
|
|
|
|
content[i] = spaces + `{{- if .Values.` + serviceName + `.persistence.` + volumeName + `.enabled }}` + "\n" + line
|
|
|
|
changing = true
|
|
|
|
}
|
|
|
|
if strings.Contains(line, "claimName: ") && changing {
|
|
|
|
content[i] = line + "\n" + spaces + "{{- end }}"
|
|
|
|
changing = false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// for impagePullSecrets, replace the name with the value from values.yaml
|
|
|
|
inpullsecrets := false
|
|
|
|
for i, line := range content {
|
|
|
|
if strings.Contains(line, "imagePullSecrets:") {
|
|
|
|
inpullsecrets = true
|
|
|
|
}
|
|
|
|
if inpullsecrets && strings.Contains(line, "- name: ") && inpullsecrets {
|
|
|
|
line = strings.Replace(line, "- name: ", "", 1)
|
|
|
|
line = strings.ReplaceAll(line, "'", "")
|
|
|
|
content[i] = line
|
|
|
|
inpullsecrets = false
|
|
|
|
}
|
2022-06-22 09:38:07 +02:00
|
|
|
}
|
|
|
|
|
2023-12-06 15:24:02 +01:00
|
|
|
// Find the replicas line and replace it with the value from values.yaml
|
|
|
|
for i, line := range content {
|
|
|
|
if strings.Contains(line, "replicas:") {
|
|
|
|
line = regexp.MustCompile("replicas: .*$").ReplaceAllString(line, "replicas: {{ .Values."+serviceName+".replicas }}")
|
|
|
|
content[i] = line
|
|
|
|
}
|
2022-06-22 09:38:07 +02:00
|
|
|
}
|
|
|
|
|
2023-12-06 15:24:02 +01:00
|
|
|
return []byte(strings.Join(content, "\n")), nil
|
|
|
|
}
|
2022-06-22 09:38:07 +02:00
|
|
|
|
2024-04-05 07:56:27 +02:00
|
|
|
// Filename returns the filename of the deployment.
|
2023-12-06 15:24:02 +01:00
|
|
|
func (d *Deployment) Filename() string {
|
|
|
|
return d.service.Name + ".deployment.yaml"
|
2022-06-22 09:38:07 +02:00
|
|
|
}
|