Files
katenary/generator/ingress.go
Patrice Ferlet 4367a01769 Big refactorization
- reduce complexity
- use better tools to format the code
- add more tests
- and too many things to list here

We are rewriting for V3, so these commits are sometimes big and not
fully detailed. Of course, further work will be more documented.
2024-05-06 21:11:36 +02:00

166 lines
4.1 KiB
Go

package generator
import (
"log"
"strings"
"github.com/compose-spec/compose-go/types"
networkv1 "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/yaml"
"katenary/generator/labelStructs"
"katenary/utils"
)
var _ Yaml = (*Ingress)(nil)
type Ingress struct {
*networkv1.Ingress
service *types.ServiceConfig `yaml:"-"`
}
// NewIngress creates a new Ingress from a compose service.
func NewIngress(service types.ServiceConfig, Chart *HelmChart) *Ingress {
appName := Chart.Name
if service.Labels == nil {
service.Labels = make(map[string]string)
}
var label string
var ok bool
if label, ok = service.Labels[LabelIngress]; !ok {
return nil
}
mapping, err := labelStructs.IngressFrom(label)
if err != nil {
log.Fatalf("Failed to parse ingress label: %s\n", err)
}
if mapping.Hostname == "" {
mapping.Hostname = service.Name + ".tld"
}
// create the ingress
pathType := networkv1.PathTypeImplementationSpecific
serviceName := `{{ include "` + appName + `.fullname" . }}-` + service.Name
// Add the ingress host to the values.yaml
if Chart.Values[service.Name] == nil {
Chart.Values[service.Name] = &Value{}
}
Chart.Values[service.Name].(*Value).Ingress = &IngressValue{
Enabled: mapping.Enabled,
Path: mapping.Path,
Host: mapping.Hostname,
Class: mapping.Class,
Annotations: mapping.Annotations,
}
// ingressClassName := `{{ .Values.` + service.Name + `.ingress.class }}`
ingressClassName := utils.TplValue(service.Name, "ingress.class")
servicePortName := utils.GetServiceNameByPort(int(*mapping.Port))
ingressService := &networkv1.IngressServiceBackend{
Name: serviceName,
Port: networkv1.ServiceBackendPort{},
}
if servicePortName != "" {
ingressService.Port.Name = servicePortName
} else {
ingressService.Port.Number = *mapping.Port
}
ing := &Ingress{
service: &service,
Ingress: &networkv1.Ingress{
TypeMeta: metav1.TypeMeta{
Kind: "Ingress",
APIVersion: "networking.k8s.io/v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: utils.TplName(service.Name, appName),
Labels: GetLabels(service.Name, appName),
Annotations: Annotations,
},
Spec: networkv1.IngressSpec{
IngressClassName: &ingressClassName,
Rules: []networkv1.IngressRule{
{
Host: utils.TplValue(service.Name, "ingress.host"),
IngressRuleValue: networkv1.IngressRuleValue{
HTTP: &networkv1.HTTPIngressRuleValue{
Paths: []networkv1.HTTPIngressPath{
{
Path: utils.TplValue(service.Name, "ingress.path"),
PathType: &pathType,
Backend: networkv1.IngressBackend{
Service: ingressService,
},
},
},
},
},
},
},
TLS: []networkv1.IngressTLS{
{
Hosts: []string{
`{{ tpl .Values.` + service.Name + `.ingress.host . }}`,
},
SecretName: `{{ include "` + appName + `.fullname" . }}-` + service.Name + `-tls`,
},
},
},
},
}
return ing
}
func (ingress *Ingress) Yaml() ([]byte, error) {
serviceName := ingress.service.Name
ret, err := yaml.Marshal(ingress)
if err != nil {
return nil, err
}
lines := strings.Split(string(ret), "\n")
out := []string{
`{{- if .Values.` + serviceName + `.ingress.enabled -}}`,
}
for _, line := range lines {
if strings.Contains(line, "loadBalancer: ") {
continue
}
if strings.Contains(line, "labels:") {
// add annotations above labels from values.yaml
content := `` +
` {{- if .Values.` + serviceName + `.ingress.annotations -}}` + "\n" +
` {{- toYaml .Values.` + serviceName + `.ingress.annotations | nindent 4 }}` + "\n" +
` {{- end }}` + "\n" +
line
out = append(out, content)
} else if strings.Contains(line, "ingressClassName: ") {
content := utils.Wrap(
line,
`{{- if ne .Values.`+serviceName+`.ingress.class "-" }}`,
`{{- end }}`,
)
out = append(out, content)
} else {
out = append(out, line)
}
}
out = append(out, `{{- end -}}`)
ret = []byte(strings.Join(out, "\n"))
return ret, nil
}
func (ingress *Ingress) Filename() string {
return ingress.service.Name + ".ingress.yaml"
}