diff --git a/plugins/scheduler-k3s/functions.go b/plugins/scheduler-k3s/functions.go index 3338548bf..2cf64ba9f 100644 --- a/plugins/scheduler-k3s/functions.go +++ b/plugins/scheduler-k3s/functions.go @@ -2,7 +2,6 @@ package scheduler_k3s import ( "context" - "encoding/json" "errors" "fmt" "os" @@ -255,48 +254,105 @@ func extractStartCommand(input StartCommandInput) string { return command } -type PortMap struct { - ContainerPort int32 `json:"container_port"` - HostPort int32 `json:"host_port"` - Scheme string `json:"scheme"` +func getDeployTimeout(appName string) string { + return common.PropertyGetDefault("scheduler-k3s", appName, "deploy-timeout", "") } -func (p PortMap) String() string { - return fmt.Sprintf("%s-%d-%d", p.Scheme, p.HostPort, p.ContainerPort) +func getGlobalDeployTimeout() string { + return common.PropertyGetDefault("scheduler-k3s", "--global", "deploy-timeout", "300s") } -func (p PortMap) IsAllowedHttp() bool { - return p.Scheme == "http" || p.ContainerPort == 80 -} - -func (p PortMap) IsAllowedHttps() bool { - return p.Scheme == "https" || p.ContainerPort == 443 -} - -func getPortMaps(appName string) ([]PortMap, error) { - portMaps := []PortMap{} - - output, err := common.PlugnTriggerOutputAsString("ports-get", []string{appName, "json"}...) - if err != nil { - return portMaps, err +func getComputedDeployTimeout(appName string) string { + deployTimeout := getDeployTimeout(appName) + if deployTimeout == "" { + deployTimeout = getGlobalDeployTimeout() } - err = json.Unmarshal([]byte(output), &portMaps) - if err != nil { - return portMaps, err + return deployTimeout +} + +func getImagePullSecrets(appName string) string { + return common.PropertyGetDefault("scheduler-k3s", appName, "image-pull-secrets", "") +} + +func getGlobalImagePullSecrets() string { + return common.PropertyGetDefault("scheduler-k3s", "--global", "image-pull-secrets", "") +} + +func getComputedImagePullSecrets(appName string) string { + imagePullSecrets := getImagePullSecrets(appName) + if imagePullSecrets == "" { + imagePullSecrets = getGlobalImagePullSecrets() } - allowedMappings := []PortMap{} - for _, portMap := range portMaps { - if !portMap.IsAllowedHttp() && !portMap.IsAllowedHttps() { - // todo: log warning - continue - } + return imagePullSecrets +} - allowedMappings = append(allowedMappings, portMap) +func getLetsencryptServer(appName string) string { + return common.PropertyGetDefault("scheduler-k3s", appName, "letsencrypt-server", "") +} + +func getGlobalLetsencryptServer(appName string) string { + return common.PropertyGetDefault("scheduler-k3s", appName, "letsencrypt-server", "prod") +} + +func getComputedLetsencryptServer(appName string) string { + letsencryptServer := getLetsencryptServer(appName) + if letsencryptServer == "" { + letsencryptServer = getGlobalLetsencryptServer(appName) } - return allowedMappings, nil + return letsencryptServer +} + +func getGlobalLetsencryptEmailProd() string { + return common.PropertyGetDefault("scheduler-k3s", "--global", "letsencrypt-email-prod", "") +} + +func getGlobalLetsencryptEmailStag() string { + return common.PropertyGetDefault("scheduler-k3s", "--global", "letsencrypt-email-stag", "") +} + +func getNamespace(appName string) string { + return common.PropertyGetDefault("scheduler-k3s", appName, "namespace", "") +} + +func getGlobalNamespace() string { + return common.PropertyGetDefault("scheduler-k3s", "--global", "namespace", "default") +} + +func getComputedNamespace(appName string) string { + namespace := getNamespace(appName) + if namespace == "" { + namespace = getGlobalNamespace() + } + + return namespace +} + +func getGlobalNetworkInterface() string { + return common.PropertyGetDefault("scheduler-k3s", "--global", "network-interface", "eth0") +} + +func getRollbackOnFailure(appName string) string { + return common.PropertyGetDefault("scheduler-k3s", appName, "rollback-on-failure", "") +} + +func getGlobalRollbackOnFailure() string { + return common.PropertyGetDefault("scheduler-k3s", "--global", "rollback-on-failure", "") +} + +func getComputedRollbackOnFailure(appName string) string { + rollbackOnFailure := getRollbackOnFailure(appName) + if rollbackOnFailure == "" { + rollbackOnFailure = getGlobalRollbackOnFailure() + } + + return rollbackOnFailure +} + +func getGlobalGlobalToken() string { + return common.PropertyGet("scheduler-k3s", "--global", "token") } func getStartCommand(input StartCommandInput) (StartCommandOutput, error) { diff --git a/plugins/scheduler-k3s/portmap.go b/plugins/scheduler-k3s/portmap.go new file mode 100644 index 000000000..e4aa03807 --- /dev/null +++ b/plugins/scheduler-k3s/portmap.go @@ -0,0 +1,52 @@ +package scheduler_k3s + +import ( + "encoding/json" + "fmt" + + "github.com/dokku/dokku/plugins/common" +) + +type PortMap struct { + ContainerPort int32 `json:"container_port"` + HostPort int32 `json:"host_port"` + Scheme string `json:"scheme"` +} + +func (p PortMap) String() string { + return fmt.Sprintf("%s-%d-%d", p.Scheme, p.HostPort, p.ContainerPort) +} + +func (p PortMap) IsAllowedHttp() bool { + return p.Scheme == "http" || p.ContainerPort == 80 +} + +func (p PortMap) IsAllowedHttps() bool { + return p.Scheme == "https" || p.ContainerPort == 443 +} + +func getPortMaps(appName string) ([]PortMap, error) { + portMaps := []PortMap{} + + output, err := common.PlugnTriggerOutputAsString("ports-get", []string{appName, "json"}...) + if err != nil { + return portMaps, err + } + + err = json.Unmarshal([]byte(output), &portMaps) + if err != nil { + return portMaps, err + } + + allowedMappings := []PortMap{} + for _, portMap := range portMaps { + if !portMap.IsAllowedHttp() && !portMap.IsAllowedHttps() { + // todo: log warning + continue + } + + allowedMappings = append(allowedMappings, portMap) + } + + return allowedMappings, nil +} diff --git a/plugins/scheduler-k3s/scheduler_k3s.go b/plugins/scheduler-k3s/scheduler_k3s.go index 86250bfb2..5ec4631ca 100644 --- a/plugins/scheduler-k3s/scheduler_k3s.go +++ b/plugins/scheduler-k3s/scheduler_k3s.go @@ -17,18 +17,23 @@ import ( var ( // DefaultProperties is a map of all valid k3s properties with corresponding default property values DefaultProperties = map[string]string{ + "deploy-timeout": "", + "letsencrypt-server": "", "image-pull-secrets": "", + "namespace": "", "rollback-on-failure": "", - "namespace": "default", - "timeout": "300", } // GlobalProperties is a map of all valid global k3s properties GlobalProperties = map[string]bool{ - "network-interface": true, - "rollback-on-failure": true, - "token": true, - "timeout": true, + "deploy-timeout": true, + "image-pull-secrets": true, + "letsencrypt-email-prod": true, + "letsencrypt-email-stag": true, + "namespace": true, + "network-interface": true, + "rollback-on-failure": true, + "token": true, } ) diff --git a/plugins/scheduler-k3s/subcommands.go b/plugins/scheduler-k3s/subcommands.go index 1a251a2bc..8faeac9fa 100644 --- a/plugins/scheduler-k3s/subcommands.go +++ b/plugins/scheduler-k3s/subcommands.go @@ -34,7 +34,7 @@ func CommandInitialize(taintScheduling bool) error { cancel() }() - networkInterface := common.PropertyGetDefault("scheduler-k3s", "--global", "network-interface", "eth0") + networkInterface := getGlobalNetworkInterface() ifaces, err := net.Interfaces() if err != nil { return fmt.Errorf("Unable to get network interfaces: %w", err) @@ -142,7 +142,7 @@ func CommandInitialize(taintScheduling bool) error { return fmt.Errorf("Invalid k3s installer filesize") } - token := common.PropertyGet("scheduler-k3s", "--global", "token") + token := getGlobalGlobalToken() if len(token) == 0 { n := 5 b := make([]byte, n) @@ -289,7 +289,7 @@ func CommandClusterAdd(role string, remoteHost string, allowUknownHosts bool, ta return fmt.Errorf("Invalid server-type: %s", role) } - token := common.PropertyGet("scheduler-k3s", "--global", "token") + token := getGlobalGlobalToken() if len(token) == 0 { return fmt.Errorf("Missing k3s token") } @@ -298,7 +298,7 @@ func CommandClusterAdd(role string, remoteHost string, allowUknownHosts bool, ta return fmt.Errorf("Taint scheduling can only be used on the server role") } - networkInterface := common.PropertyGetDefault("scheduler-k3s", "--global", "network-interface", "eth0") + networkInterface := getGlobalNetworkInterface() ifaces, err := net.Interfaces() if err != nil { return fmt.Errorf("Unable to get network interfaces: %w", err) diff --git a/plugins/scheduler-k3s/triggers.go b/plugins/scheduler-k3s/triggers.go index bd1fb202a..9c4b8e6c6 100644 --- a/plugins/scheduler-k3s/triggers.go +++ b/plugins/scheduler-k3s/triggers.go @@ -188,7 +188,7 @@ func TriggerSchedulerDeploy(scheduler string, appName string, imageTag string) e cancel() }() - namespace := common.PropertyGetDefault("scheduler-k3s", appName, "namespace", "default") + namespace := getComputedNamespace(appName) if err := createKubernetesNamespace(ctx, namespace); err != nil { return fmt.Errorf("Error creating kubernetes namespace for deployment: %w", err) } @@ -198,18 +198,18 @@ func TriggerSchedulerDeploy(scheduler string, appName string, imageTag string) e return fmt.Errorf("Error getting deploying app image name: %w", err) } - deployTimeout := common.PropertyGetDefault("scheduler-k3s", appName, "deploy-timeout", "300s") + deployTimeout := getComputedDeployTimeout(appName) if _, err := strconv.Atoi(deployTimeout); err == nil { deployTimeout = fmt.Sprintf("%ss", deployTimeout) } - deployRollback := common.PropertyGetDefault("scheduler-k3s", appName, "rollback-on-failure", "false") + deployRollback := getComputedRollbackOnFailure(appName) allowRollbacks, err := strconv.ParseBool(deployRollback) if err != nil { return fmt.Errorf("Error parsing rollback-on-failure value as boolean: %w", err) } - imagePullSecrets := common.PropertyGetDefault("scheduler-k3s", appName, "image-pull-secrets", "") + imagePullSecrets := getComputedImagePullSecrets(appName) imageSourceType := "dockerfile" if common.IsImageCnbBased(image) { @@ -576,8 +576,7 @@ func TriggerSchedulerEnter(scheduler string, appName string, processType string, return fmt.Errorf("Error creating kubernetes client: %w", err) } - namespace := common.PropertyGetDefault("scheduler-k3s", appName, "namespace", "default") - + namespace := getComputedNamespace(appName) labelSelector := []string{fmt.Sprintf("app.kubernetes.io/part-of=%s", appName)} processIndex := 1 if processType != "" { @@ -682,7 +681,7 @@ func TriggerSchedulerLogs(scheduler string, appName string, processType string, labelSelector = append(labelSelector, fmt.Sprintf("app.kubernetes.io/name=%s", processType)) } - namespace := common.PropertyGetDefault("scheduler-k3s", appName, "namespace", "default") + namespace := getComputedNamespace(appName) pods, err := clientset.ListPods(ctx, ListPodsInput{ Namespace: namespace, LabelSelector: strings.Join(labelSelector, ","), @@ -881,7 +880,7 @@ func TriggerSchedulerRun(scheduler string, appName string, envCount int, args [] entrypoint = "/exec" } - namespace := common.PropertyGetDefault("scheduler-k3s", appName, "namespace", "default") + namespace := getComputedNamespace(appName) helmAgent, err := NewHelmAgent(namespace, DevNullPrinter) if err != nil { return fmt.Errorf("Error creating helm agent: %w", err) @@ -905,7 +904,7 @@ func TriggerSchedulerRun(scheduler string, appName string, envCount int, args [] } attachToPod := os.Getenv("DOKKU_DETACH_CONTAINER") != "1" - imagePullSecrets := common.PropertyGetDefault("scheduler-k3s", appName, "image-pull-secrets", "") + imagePullSecrets := getComputedImagePullSecrets(appName) workingDir := common.GetWorkingDir(appName, image) job, err := templateKubernetesJob(Job{ AppName: appName, @@ -1088,8 +1087,7 @@ func TriggerSchedulerRunList(scheduler string, appName string, format string) er return fmt.Errorf("Error creating kubernetes client: %w", err) } - namespace := common.PropertyGetDefault("scheduler-k3s", appName, "namespace", "default") - + namespace := getComputedNamespace(appName) cronJobs, err := clientset.ListCronJobs(ctx, ListCronJobsInput{ LabelSelector: fmt.Sprintf("app.kubernetes.io/part-of=%s", appName), Namespace: namespace, @@ -1149,7 +1147,7 @@ func TriggerSchedulerPostDelete(scheduler string, appName string) error { if scheduler != "k3s" { return nil } - namespace := common.PropertyGetDefault("scheduler-k3s", appName, "namespace", "default") + namespace := getComputedNamespace(appName) helmAgent, err := NewHelmAgent(namespace, DeployLogPrinter) if err != nil { return fmt.Errorf("Error creating helm agent: %w", err) @@ -1185,7 +1183,7 @@ func TriggerSchedulerStop(scheduler string, appName string) error { return fmt.Errorf("Error creating kubernetes client: %w", err) } - namespace := common.PropertyGetDefault("scheduler-k3s", appName, "namespace", "default") + namespace := getComputedNamespace(appName) deployments, err := clientset.ListDeployments(ctx, ListDeploymentsInput{ Namespace: namespace, LabelSelector: fmt.Sprintf("app.kubernetes.io/part-of=%s", appName),