From b0485495e4660b208b04ea42f359b2869f4ff3bb Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Mon, 22 Jan 2024 06:42:03 -0500 Subject: [PATCH] refactor: make domains a helm value This will allow updating domains on the fly --- plugins/scheduler-k3s/template.go | 125 +++++++++--------- .../templates/ingress-routes-append.yaml | 11 ++ plugins/scheduler-k3s/triggers.go | 41 ++++-- 3 files changed, 104 insertions(+), 73 deletions(-) create mode 100644 plugins/scheduler-k3s/templates/ingress-routes-append.yaml diff --git a/plugins/scheduler-k3s/template.go b/plugins/scheduler-k3s/template.go index edb4e3d8e..e10b75c78 100644 --- a/plugins/scheduler-k3s/template.go +++ b/plugins/scheduler-k3s/template.go @@ -1,11 +1,11 @@ package scheduler_k3s import ( + "bytes" "crypto/rand" "fmt" "os" "path/filepath" - "sort" "strings" appjson "github.com/dokku/dokku/plugins/app-json" @@ -34,63 +34,82 @@ type Chart struct { type Values struct { DeploymentID string `yaml:"deploment_id"` - Secrets map[string]string `yaml:"secrets"` - Processes map[string]ValuesProcess `yaml:"processes"` + Secrets map[string]string `yaml:"secrets,omitempty"` + Processes map[string]ProcessValues `yaml:"processes"` } -type ValuesProcess struct { - Replicas int32 `yaml:"replicas"` +type ProcessValues struct { + Replicas int32 `yaml:"replicas"` + Domains []string `yaml:"domains,omitempty"` } type CreateIngressRoutesInput struct { - AppName string - ChartDir string - Deployment appsv1.Deployment - Namespace string - PortMaps []PortMap - Service v1.Service + AppName string + ChartDir string + Deployment appsv1.Deployment + Namespace string + ProcessType string + PortMaps []PortMap + Service v1.Service } func createIngressRoutesFiles(input CreateIngressRoutesInput) error { - err := common.PlugnTrigger("domains-vhost-enabled", []string{input.AppName}...) - isAppVhostEnabled := err == nil + for _, portMap := range input.PortMaps { + ingressRoute := templateKubernetesIngressRoute(IngressRoute{ + AppName: input.AppName, + Namespace: input.Namespace, + PortMap: portMap, + ProcessType: input.ProcessType, + ServiceName: input.Service.Name, + }) - if isAppVhostEnabled { - b, err := common.PlugnTriggerOutput("domains-list", []string{input.AppName}...) + ingressRouteFile := filepath.Join(input.ChartDir, fmt.Sprintf("templates/ingress-route-%s.yaml", portMap.String())) + err := writeResourceToFile(WriteResourceInput{ + Object: &ingressRoute, + Path: ingressRouteFile, + }) if err != nil { - return fmt.Errorf("Error getting domains for deployment: %w", err) - } - domains := []string{} - for _, domain := range strings.Split(string(b), "\n") { - domain = strings.TrimSpace(domain) - if domain != "" { - domains = append(domains, domain) - } + return fmt.Errorf("Error printing ingress route: %w", err) } - if len(domains) == 0 { - return nil + b, err := os.ReadFile(ingressRouteFile) + if err != nil { + return fmt.Errorf("Error reading ingress route file: %w", err) } - for _, portMap := range input.PortMaps { - ingressRoute := templateKubernetesIngressRoute(IngressRoute{ - AppName: input.AppName, - Domains: domains, - Namespace: input.Namespace, - PortMap: portMap, - ProcessType: "web", - ServiceName: input.Service.Name, - }) + append, err := templates.ReadFile("templates/ingress-routes-append.yaml") + if err != nil { + return fmt.Errorf("Error reading ingress route append file: %w", err) + } - err = writeResourceToFile(WriteResourceInput{ - Object: &ingressRoute, - Path: filepath.Join(input.ChartDir, fmt.Sprintf("templates/ingress-route-%s-%d-%d.yaml", portMap.Scheme, portMap.HostPort, portMap.ContainerPort)), - }) - if err != nil { - return fmt.Errorf("Error printing ingress route: %w", err) - } + contents := string(bytes.Join([][]byte{b, append}, []byte(""))) + contents = strings.ReplaceAll(contents, " routes: null", "") + contents = strings.Join([]string{ + "{{- if .Values.processes.PROCESS_TYPE.domains }}", + contents, + "{{- end }}", + }, "\n") + + replacements := orderedmap.New[string, string]() + replacements.Set("PROCESS_TYPE", input.ProcessType) + replacements.Set("APP_NAME", input.AppName) + replacements.Set("NAMESPACE", input.Namespace) + replacements.Set("PORT_MAPPING", portMap.String()) + replacements.Set("PORT_SCHEME", portMap.Scheme) + for pair := replacements.Oldest(); pair != nil; pair = pair.Next() { + contents = strings.ReplaceAll(contents, pair.Key, pair.Value) + } + + err = os.WriteFile(ingressRouteFile, []byte(contents), os.FileMode(0644)) + if err != nil { + return fmt.Errorf("Error writing ingress route file: %w", err) + } + + if os.Getenv("DOKKU_TRACE") == "1" { + common.CatFile(ingressRouteFile) } } + return nil } @@ -535,7 +554,6 @@ const ( type IngressRoute struct { AppName string Entrypoints []IngressRouteEntrypoint - Domains []string Namespace string PortMap PortMap ProcessType string @@ -567,32 +585,9 @@ func templateKubernetesIngressRoute(input IngressRoute) traefikv1alpha1.IngressR }, Spec: traefikv1alpha1.IngressRouteSpec{ EntryPoints: []string{string(entryPoint)}, - Routes: []traefikv1alpha1.Route{}, }, } - sort.Strings(input.Domains) - - for _, hostname := range input.Domains { - rule := traefikv1alpha1.Route{ - Kind: "Rule", - Match: "Host(`" + hostname + "`)", - Services: []traefikv1alpha1.Service{ - { - LoadBalancerSpec: traefikv1alpha1.LoadBalancerSpec{ - Name: input.ServiceName, - Namespace: input.Namespace, - PassHostHeader: ptr.To(true), - Port: intstr.FromString(port), - Scheme: input.PortMap.Scheme, - }, - }, - }, - } - - ingressRoute.Spec.Routes = append(ingressRoute.Spec.Routes, rule) - } - return ingressRoute } diff --git a/plugins/scheduler-k3s/templates/ingress-routes-append.yaml b/plugins/scheduler-k3s/templates/ingress-routes-append.yaml new file mode 100644 index 000000000..a4b0a1e98 --- /dev/null +++ b/plugins/scheduler-k3s/templates/ingress-routes-append.yaml @@ -0,0 +1,11 @@ + routes: + {{- range .Values.processes.PROCESS_TYPE.domains }} + - kind: Rule + match: Host(`{{ . }}`) + services: + - name: APP_NAME-PROCESS_TYPE + namespace: NAMESPACE + passHostHeader: true + port: PORT_MAPPING + scheme: PORT_SCHEME + {{- end }} \ No newline at end of file diff --git a/plugins/scheduler-k3s/triggers.go b/plugins/scheduler-k3s/triggers.go index 0515747ba..7eb1022aa 100644 --- a/plugins/scheduler-k3s/triggers.go +++ b/plugins/scheduler-k3s/triggers.go @@ -11,6 +11,7 @@ import ( "os" "os/signal" "path/filepath" + "sort" "strconv" "strings" "syscall" @@ -394,6 +395,7 @@ data: } } + domains := []string{} if deployment, ok := deployments["web"]; ok { service := templateKubernetesService(Service{ AppName: appName, @@ -410,13 +412,29 @@ data: return fmt.Errorf("Error printing service: %w", err) } + err = common.PlugnTrigger("domains-vhost-enabled", []string{appName}...) + if err == nil { + b, err := common.PlugnTriggerOutput("domains-list", []string{appName}...) + if err != nil { + return fmt.Errorf("Error getting domains for deployment: %w", err) + } + + for _, domain := range strings.Split(string(b), "\n") { + domain = strings.TrimSpace(domain) + if domain != "" { + domains = append(domains, domain) + } + } + } + err = createIngressRoutesFiles(CreateIngressRoutesInput{ - AppName: appName, - ChartDir: chartDir, - Deployment: deployment, - Namespace: namespace, - PortMaps: portMaps, - Service: service, + AppName: appName, + ChartDir: chartDir, + Deployment: deployment, + Namespace: namespace, + PortMaps: portMaps, + ProcessType: "web", + Service: service, }) if err != nil { return fmt.Errorf("Error creating ingress routes: %w", err) @@ -441,13 +459,20 @@ data: values := &Values{ DeploymentID: fmt.Sprint(deploymentId), Secrets: map[string]string{}, - Processes: map[string]ValuesProcess{}, + Processes: map[string]ProcessValues{}, } for processType, processCount := range processes { - values.Processes[processType] = ValuesProcess{ + processValues := ProcessValues{ Replicas: int32(processCount), } + if processType == "web" { + sort.Strings(domains) + processValues.Domains = domains + } + + values.Processes[processType] = processValues } + for key, value := range env.Map() { values.Secrets[key] = base64.StdEncoding.EncodeToString([]byte(value)) }