refactor: make domains a helm value

This will allow updating domains on the fly
This commit is contained in:
Jose Diaz-Gonzalez
2024-01-22 06:42:03 -05:00
parent 01ec08fd79
commit b0485495e4
3 changed files with 104 additions and 73 deletions

View File

@@ -1,11 +1,11 @@
package scheduler_k3s package scheduler_k3s
import ( import (
"bytes"
"crypto/rand" "crypto/rand"
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
"sort"
"strings" "strings"
appjson "github.com/dokku/dokku/plugins/app-json" appjson "github.com/dokku/dokku/plugins/app-json"
@@ -34,63 +34,82 @@ type Chart struct {
type Values struct { type Values struct {
DeploymentID string `yaml:"deploment_id"` DeploymentID string `yaml:"deploment_id"`
Secrets map[string]string `yaml:"secrets"` Secrets map[string]string `yaml:"secrets,omitempty"`
Processes map[string]ValuesProcess `yaml:"processes"` Processes map[string]ProcessValues `yaml:"processes"`
} }
type ValuesProcess struct { type ProcessValues struct {
Replicas int32 `yaml:"replicas"` Replicas int32 `yaml:"replicas"`
Domains []string `yaml:"domains,omitempty"`
} }
type CreateIngressRoutesInput struct { type CreateIngressRoutesInput struct {
AppName string AppName string
ChartDir string ChartDir string
Deployment appsv1.Deployment Deployment appsv1.Deployment
Namespace string Namespace string
PortMaps []PortMap ProcessType string
Service v1.Service PortMaps []PortMap
Service v1.Service
} }
func createIngressRoutesFiles(input CreateIngressRoutesInput) error { func createIngressRoutesFiles(input CreateIngressRoutesInput) error {
err := common.PlugnTrigger("domains-vhost-enabled", []string{input.AppName}...) for _, portMap := range input.PortMaps {
isAppVhostEnabled := err == nil ingressRoute := templateKubernetesIngressRoute(IngressRoute{
AppName: input.AppName,
Namespace: input.Namespace,
PortMap: portMap,
ProcessType: input.ProcessType,
ServiceName: input.Service.Name,
})
if isAppVhostEnabled { ingressRouteFile := filepath.Join(input.ChartDir, fmt.Sprintf("templates/ingress-route-%s.yaml", portMap.String()))
b, err := common.PlugnTriggerOutput("domains-list", []string{input.AppName}...) err := writeResourceToFile(WriteResourceInput{
Object: &ingressRoute,
Path: ingressRouteFile,
})
if err != nil { if err != nil {
return fmt.Errorf("Error getting domains for deployment: %w", err) return fmt.Errorf("Error printing ingress route: %w", err)
}
domains := []string{}
for _, domain := range strings.Split(string(b), "\n") {
domain = strings.TrimSpace(domain)
if domain != "" {
domains = append(domains, domain)
}
} }
if len(domains) == 0 { b, err := os.ReadFile(ingressRouteFile)
return nil if err != nil {
return fmt.Errorf("Error reading ingress route file: %w", err)
} }
for _, portMap := range input.PortMaps { append, err := templates.ReadFile("templates/ingress-routes-append.yaml")
ingressRoute := templateKubernetesIngressRoute(IngressRoute{ if err != nil {
AppName: input.AppName, return fmt.Errorf("Error reading ingress route append file: %w", err)
Domains: domains, }
Namespace: input.Namespace,
PortMap: portMap,
ProcessType: "web",
ServiceName: input.Service.Name,
})
err = writeResourceToFile(WriteResourceInput{ contents := string(bytes.Join([][]byte{b, append}, []byte("")))
Object: &ingressRoute, contents = strings.ReplaceAll(contents, " routes: null", "")
Path: filepath.Join(input.ChartDir, fmt.Sprintf("templates/ingress-route-%s-%d-%d.yaml", portMap.Scheme, portMap.HostPort, portMap.ContainerPort)), contents = strings.Join([]string{
}) "{{- if .Values.processes.PROCESS_TYPE.domains }}",
if err != nil { contents,
return fmt.Errorf("Error printing ingress route: %w", err) "{{- 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 return nil
} }
@@ -535,7 +554,6 @@ const (
type IngressRoute struct { type IngressRoute struct {
AppName string AppName string
Entrypoints []IngressRouteEntrypoint Entrypoints []IngressRouteEntrypoint
Domains []string
Namespace string Namespace string
PortMap PortMap PortMap PortMap
ProcessType string ProcessType string
@@ -567,32 +585,9 @@ func templateKubernetesIngressRoute(input IngressRoute) traefikv1alpha1.IngressR
}, },
Spec: traefikv1alpha1.IngressRouteSpec{ Spec: traefikv1alpha1.IngressRouteSpec{
EntryPoints: []string{string(entryPoint)}, 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 return ingressRoute
} }

View File

@@ -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 }}

View File

@@ -11,6 +11,7 @@ import (
"os" "os"
"os/signal" "os/signal"
"path/filepath" "path/filepath"
"sort"
"strconv" "strconv"
"strings" "strings"
"syscall" "syscall"
@@ -394,6 +395,7 @@ data:
} }
} }
domains := []string{}
if deployment, ok := deployments["web"]; ok { if deployment, ok := deployments["web"]; ok {
service := templateKubernetesService(Service{ service := templateKubernetesService(Service{
AppName: appName, AppName: appName,
@@ -410,13 +412,29 @@ data:
return fmt.Errorf("Error printing service: %w", err) 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{ err = createIngressRoutesFiles(CreateIngressRoutesInput{
AppName: appName, AppName: appName,
ChartDir: chartDir, ChartDir: chartDir,
Deployment: deployment, Deployment: deployment,
Namespace: namespace, Namespace: namespace,
PortMaps: portMaps, PortMaps: portMaps,
Service: service, ProcessType: "web",
Service: service,
}) })
if err != nil { if err != nil {
return fmt.Errorf("Error creating ingress routes: %w", err) return fmt.Errorf("Error creating ingress routes: %w", err)
@@ -441,13 +459,20 @@ data:
values := &Values{ values := &Values{
DeploymentID: fmt.Sprint(deploymentId), DeploymentID: fmt.Sprint(deploymentId),
Secrets: map[string]string{}, Secrets: map[string]string{},
Processes: map[string]ValuesProcess{}, Processes: map[string]ProcessValues{},
} }
for processType, processCount := range processes { for processType, processCount := range processes {
values.Processes[processType] = ValuesProcess{ processValues := ProcessValues{
Replicas: int32(processCount), Replicas: int32(processCount),
} }
if processType == "web" {
sort.Strings(domains)
processValues.Domains = domains
}
values.Processes[processType] = processValues
} }
for key, value := range env.Map() { for key, value := range env.Map() {
values.Secrets[key] = base64.StdEncoding.EncodeToString([]byte(value)) values.Secrets[key] = base64.StdEncoding.EncodeToString([]byte(value))
} }