Merge pull request #7379 from dokku/scheduler-k3s-charts-set
This commit is contained in:
@@ -572,6 +572,36 @@ dokku scheduler-k3s:set --global kube-context
|
|||||||
|
|
||||||
The default value for the `kube-context` is an empty string, and will result in Dokku using the current context within the kubeconfig.
|
The default value for the `kube-context` is an empty string, and will result in Dokku using the current context within the kubeconfig.
|
||||||
|
|
||||||
|
### Customizing Helm Chart Properties
|
||||||
|
|
||||||
|
Dokku includes a number of helm charts by default with settings that are optimized for Dokku. That said, it may be useful to further customize the charts for a given environment. Users can customize which charts are installed by setting properties prefixed with `chart.$CHART_NAME.` with the `--global` flag.
|
||||||
|
|
||||||
|
```shell
|
||||||
|
dokku scheduler-k3s:set --global chart.cert-manager.version 1.13.3
|
||||||
|
```
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Properties follow dot-notation, and are expanded according to Helm's internal logic. See the [Helm documentation](https://helm.sh/docs/helm/helm_install/#helm-install) for `helm install` for further details.
|
||||||
|
|
||||||
|
|
||||||
|
To unset a chart property, omit the value from the `scheduler-k3s:set` call:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
dokku scheduler-k3s:set --global chart.cert-manager.version
|
||||||
|
```
|
||||||
|
|
||||||
|
A `scheduler-k3s:ensure-charts` command with the `--force` flag is required after changing any chart properties in order to have them apply. This will install all charts, not just the ones that have changed.
|
||||||
|
|
||||||
|
```shell
|
||||||
|
dokku scheduler-k3s:ensure-charts --force
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternatively, a comma separated list of chart names can be specified to only force install the specified charts:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
dokku scheduler-k3s:ensure-charts --force --chart-names cert-manager
|
||||||
|
```
|
||||||
|
|
||||||
## Scheduler Interface
|
## Scheduler Interface
|
||||||
|
|
||||||
The following sections describe implemented and unimplemented scheduler functionality for the `k3s` scheduler.
|
The following sections describe implemented and unimplemented scheduler functionality for the `k3s` scheduler.
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import (
|
|||||||
kedav1alpha1 "github.com/kedacore/keda/v2/apis/keda/v1alpha1"
|
kedav1alpha1 "github.com/kedacore/keda/v2/apis/keda/v1alpha1"
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
|
"helm.sh/helm/v3/pkg/strvals"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
@@ -1493,7 +1494,7 @@ func installHelmCharts(ctx context.Context, clientset KubernetesClient, shouldIn
|
|||||||
return fmt.Errorf("Error reading values file %s: %w", chart.ReleaseName, err)
|
return fmt.Errorf("Error reading values file %s: %w", chart.ReleaseName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var values map[string]interface{}
|
values := map[string]interface{}{}
|
||||||
if len(contents) > 0 {
|
if len(contents) > 0 {
|
||||||
err = yaml.Unmarshal(contents, &values)
|
err = yaml.Unmarshal(contents, &values)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1501,6 +1502,18 @@ func installHelmCharts(ctx context.Context, clientset KubernetesClient, shouldIn
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chartProperties, err := common.PropertyGetAllByPrefix("scheduler-k3s", "--global", "chart."+chart.ReleaseName+".")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error getting chart properties: %w", err)
|
||||||
|
}
|
||||||
|
for key, value := range chartProperties {
|
||||||
|
key = strings.TrimPrefix(key, "chart."+chart.ReleaseName+".")
|
||||||
|
strval := fmt.Sprintf("%s=%s", key, value)
|
||||||
|
if err := strvals.ParseInto(strval, values); err != nil {
|
||||||
|
return fmt.Errorf("Error parsing chart property %s: %w", strval, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
helmAgent, err := NewHelmAgent(chart.Namespace, DeployLogPrinter)
|
helmAgent, err := NewHelmAgent(chart.Namespace, DeployLogPrinter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error creating helm agent: %w", err)
|
return fmt.Errorf("Error creating helm agent: %w", err)
|
||||||
|
|||||||
@@ -37,6 +37,17 @@ func ReportSingleApp(appName string, format string, infoFlag string) error {
|
|||||||
"--scheduler-k3s-global-rollback-on-failure": reportGlobalRollbackOnFailure,
|
"--scheduler-k3s-global-rollback-on-failure": reportGlobalRollbackOnFailure,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chartProperties, err := common.PropertyGetAllByPrefix("scheduler-k3s", "--global", "chart.")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Unable to get property list: %w", err)
|
||||||
|
}
|
||||||
|
for name, value := range chartProperties {
|
||||||
|
flagName := "--scheduler-k3s-global-" + name
|
||||||
|
flags[flagName] = func(appName string) string {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
flagKeys := []string{}
|
flagKeys := []string{}
|
||||||
for flagKey := range flags {
|
for flagKey := range flags {
|
||||||
flagKeys = append(flagKeys, flagKey)
|
flagKeys = append(flagKeys, flagKey)
|
||||||
|
|||||||
@@ -75,8 +75,10 @@ func main() {
|
|||||||
err = scheduler_k3s.CommandClusterRemove(nodeName)
|
err = scheduler_k3s.CommandClusterRemove(nodeName)
|
||||||
case "ensure-charts":
|
case "ensure-charts":
|
||||||
args := flag.NewFlagSet("scheduler-k3s:ensure-charts", flag.ExitOnError)
|
args := flag.NewFlagSet("scheduler-k3s:ensure-charts", flag.ExitOnError)
|
||||||
|
forceInstall := args.Bool("force", false, "--force: force install all charts")
|
||||||
|
chartNames := args.StringSlice("charts", []string{}, "--charts: comma separated list of chart names to force install")
|
||||||
args.Parse(os.Args[2:])
|
args.Parse(os.Args[2:])
|
||||||
err = scheduler_k3s.CommandEnsureCharts()
|
err = scheduler_k3s.CommandEnsureCharts(*forceInstall, *chartNames)
|
||||||
case "initialize":
|
case "initialize":
|
||||||
args := flag.NewFlagSet("scheduler-k3s:initialize", flag.ExitOnError)
|
args := flag.NewFlagSet("scheduler-k3s:initialize", flag.ExitOnError)
|
||||||
taintScheduling := args.Bool("taint-scheduling", false, "taint-scheduling: add a taint against scheduling app workloads")
|
taintScheduling := args.Bool("taint-scheduling", false, "taint-scheduling: add a taint against scheduling app workloads")
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
"slices"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
@@ -799,7 +800,7 @@ func CommandClusterRemove(nodeName string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CommandEnsureCharts ensures that the required helm charts are installed
|
// CommandEnsureCharts ensures that the required helm charts are installed
|
||||||
func CommandEnsureCharts() error {
|
func CommandEnsureCharts(forceInstall bool, forceChartNames []string) error {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
signals := make(chan os.Signal, 1)
|
signals := make(chan os.Signal, 1)
|
||||||
signal.Notify(signals, os.Interrupt, syscall.SIGHUP,
|
signal.Notify(signals, os.Interrupt, syscall.SIGHUP,
|
||||||
@@ -844,6 +845,16 @@ func CommandEnsureCharts() error {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if forceInstall {
|
||||||
|
common.LogVerbose("Force installing chart")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(forceChartNames) > 0 && slices.Contains(forceChartNames, chart.ReleaseName) {
|
||||||
|
common.LogVerbose("Force installing chart due to flag")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
helmAgent := namespacedHelmAgents[chart.Namespace]
|
helmAgent := namespacedHelmAgents[chart.Namespace]
|
||||||
latestRevision, err := helmAgent.InstalledRevision(chart.ReleaseName)
|
latestRevision, err := helmAgent.InstalledRevision(chart.ReleaseName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -944,7 +955,37 @@ func CommandReport(appName string, format string, infoFlag string) error {
|
|||||||
|
|
||||||
// CommandSet set or clear a scheduler-k3s property for an app
|
// CommandSet set or clear a scheduler-k3s property for an app
|
||||||
func CommandSet(appName string, property string, value string) error {
|
func CommandSet(appName string, property string, value string) error {
|
||||||
common.CommandPropertySet("scheduler-k3s", appName, property, value, DefaultProperties, GlobalProperties)
|
validProperties := DefaultProperties
|
||||||
|
globalProperties := GlobalProperties
|
||||||
|
if strings.HasPrefix(property, "chart.") {
|
||||||
|
if appName != "--global" {
|
||||||
|
return fmt.Errorf("Chart properties can only be set globally")
|
||||||
|
}
|
||||||
|
|
||||||
|
chartParts := strings.SplitN(property, ".", 3)
|
||||||
|
if len(chartParts) != 3 {
|
||||||
|
return fmt.Errorf("Invalid chart property, expected format: chart.$CHART_NAME.$PROPERTY: %s", property)
|
||||||
|
}
|
||||||
|
|
||||||
|
if chartParts[1] == "" {
|
||||||
|
return fmt.Errorf("Invalid chart property, missing chart name")
|
||||||
|
}
|
||||||
|
|
||||||
|
chartName := chartParts[1]
|
||||||
|
for _, chart := range HelmCharts {
|
||||||
|
if chart.ReleaseName == chartName {
|
||||||
|
validProperties[property] = ""
|
||||||
|
globalProperties[property] = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := validProperties[property]; !ok {
|
||||||
|
return fmt.Errorf("Invalid chart property, no matching chart found: %s", property)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
common.CommandPropertySet("scheduler-k3s", appName, property, value, validProperties, globalProperties)
|
||||||
|
|
||||||
letsencryptProperties := map[string]bool{
|
letsencryptProperties := map[string]bool{
|
||||||
"letsencrypt-email-prod": true,
|
"letsencrypt-email-prod": true,
|
||||||
|
|||||||
Reference in New Issue
Block a user