The new config and pull secret helm releases need to honor user-set annotations and labels for `--resource-type secret` so existing scheduler-k3s annotation tests keep passing. The dedicated charts now render `.Values.global.annotations` and `.Values.global.labels` onto their Secret manifest, and the deploy trigger plumbs `SecretAnnotations` and `SecretLabels` from the global annotation/label config. The rollback regression bats test now uses `dokku ps:rebuild` for its second deploy because git push of an unchanged ref is rejected by the dokku remote.
184 lines
5.5 KiB
Go
184 lines
5.5 KiB
Go
package scheduler_k3s
|
|
|
|
import (
|
|
"context"
|
|
"encoding/base64"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/dokku/dokku/plugins/common"
|
|
)
|
|
|
|
// ImagePullSecretValues contains the values for the dokku-managed image pull secret helm chart
|
|
type ImagePullSecretValues struct {
|
|
Global ImagePullSecretGlobalValues `yaml:"global"`
|
|
}
|
|
|
|
// ImagePullSecretGlobalValues contains the global values for the image pull secret chart
|
|
type ImagePullSecretGlobalValues struct {
|
|
Annotations map[string]string `yaml:"annotations,omitempty"`
|
|
AppName string `yaml:"app_name"`
|
|
Labels map[string]string `yaml:"labels,omitempty"`
|
|
Namespace string `yaml:"namespace"`
|
|
PullSecretBase64 string `yaml:"pull_secret_base64"`
|
|
}
|
|
|
|
// GetImagePullSecretReleaseName returns the helm release name for the image pull secret
|
|
func GetImagePullSecretReleaseName(appName string) string {
|
|
return fmt.Sprintf("pull-secret-%s", appName)
|
|
}
|
|
|
|
// GetImagePullSecretName returns the kubernetes secret name for the dokku-managed image pull secret
|
|
func GetImagePullSecretName(appName string) string {
|
|
return fmt.Sprintf("pull-secret-%s", appName)
|
|
}
|
|
|
|
// CreateOrUpdateImagePullSecretInput contains the inputs to CreateOrUpdateImagePullSecret
|
|
type CreateOrUpdateImagePullSecretInput struct {
|
|
AppName string
|
|
DockerConfigJSON []byte
|
|
Annotations map[string]string
|
|
Labels map[string]string
|
|
}
|
|
|
|
// CreateOrUpdateImagePullSecret creates or updates the image pull secret helm chart for an app
|
|
func CreateOrUpdateImagePullSecret(ctx context.Context, input CreateOrUpdateImagePullSecretInput) error {
|
|
appName := input.AppName
|
|
if err := isKubernetesAvailable(); err != nil {
|
|
common.LogDebug("kubernetes not available, skipping image pull secret creation")
|
|
return nil
|
|
}
|
|
|
|
scheduler := common.PropertyGetDefault("scheduler", appName, "selected", "")
|
|
globalScheduler := common.PropertyGetDefault("scheduler", "--global", "selected", "docker-local")
|
|
if scheduler == "" {
|
|
scheduler = globalScheduler
|
|
}
|
|
if scheduler != "k3s" {
|
|
common.LogDebug("app does not use k3s scheduler, skipping image pull secret creation")
|
|
return nil
|
|
}
|
|
|
|
chartDir, err := os.MkdirTemp("", "dokku-pull-secret-chart-")
|
|
if err != nil {
|
|
return fmt.Errorf("error creating chart directory: %w", err)
|
|
}
|
|
defer os.RemoveAll(chartDir)
|
|
|
|
if err := os.MkdirAll(filepath.Join(chartDir, "templates"), os.FileMode(0755)); err != nil {
|
|
return fmt.Errorf("error creating chart templates directory: %w", err)
|
|
}
|
|
|
|
namespace := getComputedNamespace(appName)
|
|
releaseName := GetImagePullSecretReleaseName(appName)
|
|
|
|
chart := &Chart{
|
|
ApiVersion: "v2",
|
|
AppVersion: "1.0.0",
|
|
Name: releaseName,
|
|
Icon: "https://dokku.com/assets/dokku-logo.svg",
|
|
Version: "0.0.1",
|
|
}
|
|
|
|
err = writeYaml(WriteYamlInput{
|
|
Object: chart,
|
|
Path: filepath.Join(chartDir, "Chart.yaml"),
|
|
})
|
|
if err != nil {
|
|
return fmt.Errorf("error writing chart: %w", err)
|
|
}
|
|
|
|
b, err := templates.ReadFile("templates/pull-secret-chart/templates/pull-secret.yaml")
|
|
if err != nil {
|
|
return fmt.Errorf("error reading pull-secret template: %w", err)
|
|
}
|
|
|
|
filename := filepath.Join(chartDir, "templates", "pull-secret.yaml")
|
|
err = os.WriteFile(filename, b, os.FileMode(0644))
|
|
if err != nil {
|
|
return fmt.Errorf("error writing pull-secret template: %w", err)
|
|
}
|
|
|
|
if os.Getenv("DOKKU_TRACE") == "1" {
|
|
common.CatFile(filename)
|
|
}
|
|
|
|
values := &ImagePullSecretValues{
|
|
Global: ImagePullSecretGlobalValues{
|
|
Annotations: input.Annotations,
|
|
AppName: appName,
|
|
Labels: input.Labels,
|
|
Namespace: namespace,
|
|
PullSecretBase64: base64.StdEncoding.EncodeToString(input.DockerConfigJSON),
|
|
},
|
|
}
|
|
|
|
err = writeYaml(WriteYamlInput{
|
|
Object: values,
|
|
Path: filepath.Join(chartDir, "values.yaml"),
|
|
})
|
|
if err != nil {
|
|
return fmt.Errorf("error writing values: %w", err)
|
|
}
|
|
|
|
if err := createKubernetesNamespace(ctx, namespace); err != nil {
|
|
return fmt.Errorf("error creating namespace: %w", err)
|
|
}
|
|
|
|
helmAgent, err := NewHelmAgent(namespace, DeployLogPrinter)
|
|
if err != nil {
|
|
return fmt.Errorf("error creating helm agent: %w", err)
|
|
}
|
|
|
|
chartPath, err := filepath.Abs(chartDir)
|
|
if err != nil {
|
|
return fmt.Errorf("error getting chart path: %w", err)
|
|
}
|
|
|
|
common.LogVerboseQuiet(fmt.Sprintf("Installing image pull secret for %s", appName))
|
|
err = helmAgent.InstallOrUpgradeChart(ctx, ChartInput{
|
|
ChartPath: chartPath,
|
|
Namespace: namespace,
|
|
ReleaseName: releaseName,
|
|
Wait: false,
|
|
})
|
|
if err != nil {
|
|
return fmt.Errorf("error installing image pull secret chart: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// DeleteImagePullSecret deletes the image pull secret helm chart for an app
|
|
func DeleteImagePullSecret(ctx context.Context, appName string) error {
|
|
if err := isKubernetesAvailable(); err != nil {
|
|
common.LogDebug("kubernetes not available, skipping image pull secret deletion")
|
|
return nil
|
|
}
|
|
|
|
namespace := getComputedNamespace(appName)
|
|
releaseName := GetImagePullSecretReleaseName(appName)
|
|
|
|
helmAgent, err := NewHelmAgent(namespace, DeployLogPrinter)
|
|
if err != nil {
|
|
return fmt.Errorf("error creating helm agent: %w", err)
|
|
}
|
|
|
|
exists, err := helmAgent.ChartExists(releaseName)
|
|
if err != nil {
|
|
return fmt.Errorf("error checking if image pull secret chart exists: %w", err)
|
|
}
|
|
|
|
if !exists {
|
|
return nil
|
|
}
|
|
|
|
common.LogVerboseQuiet(fmt.Sprintf("Removing image pull secret for %s", appName))
|
|
if err := helmAgent.UninstallChart(releaseName); err != nil {
|
|
return fmt.Errorf("error uninstalling image pull secret chart: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|