diff --git a/cmd/nelm/chart_lint.go b/cmd/nelm/chart_lint.go index e2e6e30f..bfd4a71f 100644 --- a/cmd/nelm/chart_lint.go +++ b/cmd/nelm/chart_lint.go @@ -189,9 +189,14 @@ func newChartLintCommand(ctx context.Context, afterAllCommandsBuiltFuncs map[*co return fmt.Errorf("add flag: %w", err) } - if err := cli.AddFlag(cmd, &cfg.RegistryCredentialsPath, "oci-chart-repos-creds", common.DefaultRegistryCredentialsPath, "Credentials to access OCI chart repositories", cli.AddFlagOptions{ + if err := AddDockerConfigFlag(cmd, &cfg.DockerConfig); err != nil { + return fmt.Errorf("add docker config flag: %w", err) + } + + if err := cli.AddFlag(cmd, &cfg.RegistryCredentialsPath, "oci-chart-repos-creds", "", "Credentials to access OCI chart repositories", cli.AddFlagOptions{ GetEnvVarRegexesFunc: cli.GetFlagGlobalAndLocalEnvVarRegexes, Group: chartRepoFlagGroup, + Type: cli.FlagTypeFile, }); err != nil { return fmt.Errorf("add flag: %w", err) } diff --git a/cmd/nelm/chart_render.go b/cmd/nelm/chart_render.go index 438000fa..a9e2e38c 100644 --- a/cmd/nelm/chart_render.go +++ b/cmd/nelm/chart_render.go @@ -159,9 +159,14 @@ func newChartRenderCommand(ctx context.Context, afterAllCommandsBuiltFuncs map[* return fmt.Errorf("add flag: %w", err) } - if err := cli.AddFlag(cmd, &cfg.RegistryCredentialsPath, "oci-chart-repos-creds", common.DefaultRegistryCredentialsPath, "Credentials to access OCI chart repositories", cli.AddFlagOptions{ + if err := AddDockerConfigFlag(cmd, &cfg.DockerConfig); err != nil { + return fmt.Errorf("add docker config flag: %w", err) + } + + if err := cli.AddFlag(cmd, &cfg.RegistryCredentialsPath, "oci-chart-repos-creds", "", "Credentials to access OCI chart repositories", cli.AddFlagOptions{ GetEnvVarRegexesFunc: cli.GetFlagGlobalAndLocalEnvVarRegexes, Group: chartRepoFlagGroup, + Type: cli.FlagTypeFile, }); err != nil { return fmt.Errorf("add flag: %w", err) } diff --git a/cmd/nelm/common_flags.go b/cmd/nelm/common_flags.go index e7117689..7821b3c5 100644 --- a/cmd/nelm/common_flags.go +++ b/cmd/nelm/common_flags.go @@ -86,6 +86,28 @@ func AddChartRepoConnectionFlags(cmd *cobra.Command, cfg *common.ChartRepoConnec return nil } +func AddDockerConfigFlag(cmd *cobra.Command, dockerConfig *string) error { + if err := cli.AddFlag(cmd, dockerConfig, "docker-config", common.DefaultDockerConfig, "Docker config directory path", cli.AddFlagOptions{ + GetEnvVarRegexesFunc: func(cmd *cobra.Command, flagName string) ([]*cli.FlagRegexExpr, error) { + regexes := []*cli.FlagRegexExpr{cli.NewFlagRegexExpr("^DOCKER_CONFIG$", "$DOCKER_CONFIG")} + + if r, err := cli.GetFlagGlobalAndLocalEnvVarRegexes(cmd, flagName); err != nil { + return nil, fmt.Errorf("get env var regexes: %w", err) + } else { + regexes = append(regexes, r...) + } + + return regexes, nil + }, + Group: chartRepoFlagGroup, + Type: cli.FlagTypeDir, + }); err != nil { + return fmt.Errorf("add flag: %w", err) + } + + return nil +} + func AddKubeConnectionFlags(cmd *cobra.Command, cfg *common.KubeConnectionOptions) error { if err := cli.AddFlag(cmd, &cfg.KubeAPIServerAddress, "kube-api-server", "", "Kubernetes API server address", cli.AddFlagOptions{ GetEnvVarRegexesFunc: cli.GetFlagGlobalAndLocalEnvVarRegexes, diff --git a/cmd/nelm/release_install.go b/cmd/nelm/release_install.go index e587134f..0a5a7b25 100644 --- a/cmd/nelm/release_install.go +++ b/cmd/nelm/release_install.go @@ -208,9 +208,14 @@ func newReleaseInstallCommand(ctx context.Context, afterAllCommandsBuiltFuncs ma return fmt.Errorf("add flag: %w", err) } - if err := cli.AddFlag(cmd, &cfg.RegistryCredentialsPath, "oci-chart-repos-creds", common.DefaultRegistryCredentialsPath, "Credentials to access OCI chart repositories", cli.AddFlagOptions{ + if err := AddDockerConfigFlag(cmd, &cfg.DockerConfig); err != nil { + return fmt.Errorf("add docker config flag: %w", err) + } + + if err := cli.AddFlag(cmd, &cfg.RegistryCredentialsPath, "oci-chart-repos-creds", "", "Credentials to access OCI chart repositories", cli.AddFlagOptions{ GetEnvVarRegexesFunc: cli.GetFlagGlobalAndLocalEnvVarRegexes, Group: chartRepoFlagGroup, + Type: cli.FlagTypeFile, }); err != nil { return fmt.Errorf("add flag: %w", err) } diff --git a/cmd/nelm/release_plan_install.go b/cmd/nelm/release_plan_install.go index 449a2e95..87576e55 100644 --- a/cmd/nelm/release_plan_install.go +++ b/cmd/nelm/release_plan_install.go @@ -205,9 +205,14 @@ func newReleasePlanInstallCommand(ctx context.Context, afterAllCommandsBuiltFunc return fmt.Errorf("add flag: %w", err) } - if err := cli.AddFlag(cmd, &cfg.RegistryCredentialsPath, "oci-chart-repos-creds", common.DefaultRegistryCredentialsPath, "Credentials to access OCI chart repositories", cli.AddFlagOptions{ + if err := AddDockerConfigFlag(cmd, &cfg.DockerConfig); err != nil { + return fmt.Errorf("add docker config flag: %w", err) + } + + if err := cli.AddFlag(cmd, &cfg.RegistryCredentialsPath, "oci-chart-repos-creds", "", "Credentials to access OCI chart repositories", cli.AddFlagOptions{ GetEnvVarRegexesFunc: cli.GetFlagGlobalAndLocalEnvVarRegexes, Group: chartRepoFlagGroup, + Type: cli.FlagTypeFile, }); err != nil { return fmt.Errorf("add flag: %w", err) } diff --git a/go.mod b/go.mod index 46242a80..0dc18372 100644 --- a/go.mod +++ b/go.mod @@ -56,7 +56,7 @@ require ( github.com/stretchr/testify v1.11.1 github.com/tidwall/sjson v1.2.5 github.com/wI2L/jsondiff v0.7.0 - github.com/werf/common-go v0.0.0-20260212174520-adf7d95a1579 + github.com/werf/common-go v0.0.0-20260428201303-b0dcadceca5c github.com/werf/kubedog v0.13.1-0.20260320165832-7d97aaf7aab9 github.com/werf/lockgate v0.1.1 github.com/werf/logboek v0.6.1 diff --git a/go.sum b/go.sum index a6da4310..4b4df940 100644 --- a/go.sum +++ b/go.sum @@ -404,6 +404,8 @@ github.com/werf/3p-cobra v0.0.0-20260403075225-552c82797324 h1:aqEM5aboMpBfsILja github.com/werf/3p-cobra v0.0.0-20260403075225-552c82797324/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= github.com/werf/common-go v0.0.0-20260212174520-adf7d95a1579 h1:LojMRgEoMNrUnfsbDG5GT4M5HXC9LAYH+5DWBY3p4uU= github.com/werf/common-go v0.0.0-20260212174520-adf7d95a1579/go.mod h1:MXS0JR9zut+oR9oEM8PEkdXXoEbKDILTmWopt0z1eZs= +github.com/werf/common-go v0.0.0-20260428201303-b0dcadceca5c h1:4/qKB2licflIlCZGX4U1o4Ij/oraYyuNc2cWFiutZ10= +github.com/werf/common-go v0.0.0-20260428201303-b0dcadceca5c/go.mod h1:DlN/hD9tXLxYgdAMkulQdzHkiaPrvs3MzgPZvjluea4= github.com/werf/kubedog v0.13.1-0.20260320165832-7d97aaf7aab9 h1:N+XKTPiXT5pf5lxThhaQQPARLUpZTlYJeMNoNtn+540= github.com/werf/kubedog v0.13.1-0.20260320165832-7d97aaf7aab9/go.mod h1:93L6aIdpj7iIhL30Obkv7bWgUyTeuxas1ijtzjmyb4Q= github.com/werf/lockgate v0.1.1 h1:S400JFYjtWfE4i4LY9FA8zx0fMdfui9DPrBiTciCrx4= diff --git a/pkg/action/chart_lint.go b/pkg/action/chart_lint.go index 1de25d00..72914579 100644 --- a/pkg/action/chart_lint.go +++ b/pkg/action/chart_lint.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "os" + "path/filepath" "github.com/samber/lo" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -59,6 +60,8 @@ type ChartLintOptions struct { DefaultDeletePropagation string // DenoBinaryPath, if specified, uses this path as the Deno binary instead of auto-downloading. DenoBinaryPath string + // DockerConfig is the path to the Docker configuration directory (e.g., ~/.docker). + DockerConfig string // ExtraAPIVersions is a list of additional Kubernetes API versions to include during linting. // Used by Capabilities.APIVersions in templates to check for API availability. ExtraAPIVersions []string @@ -100,7 +103,7 @@ type ChartLintOptions struct { // Used in the validation dry-run to check resource compatibility. NoRemoveManualChanges bool // RegistryCredentialsPath is the path to Docker config.json file with registry credentials. - // Defaults to DefaultRegistryCredentialsPath (~/.docker/config.json) if not set. + // Defaults to DockerConfig/config.json if not set. // Used for authenticating to OCI registries when pulling charts. RegistryCredentialsPath string // ReleaseName is the name of the release to use for linting. @@ -422,7 +425,7 @@ func applyChartLintOptionsDefaults(opts ChartLintOptions, currentDir, homeDir st } if opts.RegistryCredentialsPath == "" { - opts.RegistryCredentialsPath = common.DefaultRegistryCredentialsPath + opts.RegistryCredentialsPath = filepath.Join(opts.DockerConfig, "config.json") } if opts.ChartProvenanceStrategy == "" { diff --git a/pkg/action/chart_render.go b/pkg/action/chart_render.go index 284b78ac..38b436ed 100644 --- a/pkg/action/chart_render.go +++ b/pkg/action/chart_render.go @@ -59,6 +59,8 @@ type ChartRenderOptions struct { DefaultChartVersion string // DenoBinaryPath, if specified, uses this path as the Deno binary instead of auto-downloading. DenoBinaryPath string + // DockerConfig is the path to the Docker configuration directory (e.g., ~/.docker). + DockerConfig string // ExtraAPIVersions is a list of additional Kubernetes API versions to include when rendering. // Used by Capabilities.APIVersions in templates to check for API availability. ExtraAPIVersions []string @@ -94,7 +96,7 @@ type ChartRenderOptions struct { // Useful when only the result data structure is needed. OutputNoPrint bool // RegistryCredentialsPath is the path to Docker config.json file with registry credentials. - // Defaults to DefaultRegistryCredentialsPath (~/.docker/config.json) if not set. + // Defaults to DockerConfig/config.json if not set. // Used for authenticating to OCI registries when pulling charts. RegistryCredentialsPath string // ReleaseName is the name of the release to use in templates. @@ -421,7 +423,7 @@ func applyChartRenderOptionsDefaults(opts ChartRenderOptions, currentDir, homeDi } if opts.RegistryCredentialsPath == "" { - opts.RegistryCredentialsPath = common.DefaultRegistryCredentialsPath + opts.RegistryCredentialsPath = filepath.Join(opts.DockerConfig, "config.json") } if opts.ChartProvenanceStrategy == "" { diff --git a/pkg/action/release_install.go b/pkg/action/release_install.go index 6de3977e..374544e7 100644 --- a/pkg/action/release_install.go +++ b/pkg/action/release_install.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "os" + "path/filepath" "sort" "time" @@ -75,6 +76,8 @@ type ReleaseInstallOptions struct { DefaultChartVersion string // DenoBinaryPath, if specified, uses this path as the Deno binary instead of auto-downloading. DenoBinaryPath string + // DockerConfig is the path to the Docker configuration directory (e.g., ~/.docker). + DockerConfig string // IgnoreBundleJS, when true, ignores the existing bundle.js and rebuilds it from TypeScript sources. IgnoreBundleJS bool // InstallGraphPath, if specified, saves the Graphviz representation of the install plan to this file path. @@ -110,7 +113,7 @@ type ReleaseInstallOptions struct { // PlanArtifactPath, if specified, saves the install plan artifact to this file path. PlanArtifactPath string // RegistryCredentialsPath is the path to Docker config.json file with registry credentials. - // Defaults to DefaultRegistryCredentialsPath (~/.docker/config.json) if not set. + // Defaults to DockerConfig/config.json if not set. // Used for authenticating to OCI registries when pulling charts. RegistryCredentialsPath string // RollbackGraphPath, if specified, saves the Graphviz representation of the rollback plan (if auto-rollback occurs) @@ -728,7 +731,7 @@ func applyReleaseInstallOptionsDefaults(opts ReleaseInstallOptions, currentDir, } if opts.RegistryCredentialsPath == "" { - opts.RegistryCredentialsPath = common.DefaultRegistryCredentialsPath + opts.RegistryCredentialsPath = filepath.Join(opts.DockerConfig, "config.json") } if opts.ChartProvenanceStrategy == "" { diff --git a/pkg/action/release_plan_install.go b/pkg/action/release_plan_install.go index ba09cc70..ae5ad28c 100644 --- a/pkg/action/release_plan_install.go +++ b/pkg/action/release_plan_install.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "os" + "path/filepath" "strings" "time" @@ -69,6 +70,8 @@ type ReleasePlanInstallOptions struct { DefaultChartVersion string // DenoBinaryPath, if specified, uses this path as the Deno binary instead of auto-downloading. DenoBinaryPath string + // DockerConfig is the path to the Docker configuration directory (e.g., ~/.docker). + DockerConfig string // ErrorIfChangesPlanned, when true, returns ErrChangesPlanned if any changes are detected. // Used with --exit-code flag to return exit code 2 if changes are planned, 0 if no changes, 1 on error. ErrorIfChangesPlanned bool @@ -97,7 +100,7 @@ type ReleasePlanInstallOptions struct { // PlanArtifactPath, if specified, saves the install plan artifact to this file path. PlanArtifactPath string // RegistryCredentialsPath is the path to Docker config.json file with registry credentials. - // Defaults to DefaultRegistryCredentialsPath (~/.docker/config.json) if not set. + // Defaults to DockerConfig/config.json if not set. // Used for authenticating to OCI registries when pulling charts. RegistryCredentialsPath string // TempDirPath is the directory for temporary files during the operation. @@ -538,7 +541,7 @@ func applyReleasePlanInstallOptionsDefaults(opts ReleasePlanInstallOptions, curr } if opts.RegistryCredentialsPath == "" { - opts.RegistryCredentialsPath = common.DefaultRegistryCredentialsPath + opts.RegistryCredentialsPath = filepath.Join(opts.DockerConfig, "config.json") } if opts.ChartProvenanceStrategy == "" { diff --git a/pkg/common/common.go b/pkg/common/common.go index e4418d7a..a5ee070a 100644 --- a/pkg/common/common.go +++ b/pkg/common/common.go @@ -152,9 +152,7 @@ var ( StagePostPostUninstall, StageFinal, } - OrderedStoreAs = []StoreAs{StoreAsNone, StoreAsHook, StoreAsRegular} - // TODO(major): now it respects DOCKER_CONFIG? Is it a breaking change? Anyways, I feel like it shouldn't be a constant, but a proper option for actions - DefaultRegistryCredentialsPath = filepath.Join(dockerConfigDir(), "config.json") + OrderedStoreAs = []StoreAs{StoreAsNone, StoreAsHook, StoreAsRegular} LabelKeyHumanManagedBy = "app.kubernetes.io/managed-by" LabelKeyPatternManagedBy = regexp.MustCompile(`^app.kubernetes.io/managed-by$`) AnnotationKeyHumanReleaseName = "meta.helm.sh/release-name" @@ -225,6 +223,7 @@ var ( AnnotationKeyHumanDeletePropagation = "werf.io/delete-propagation" AnnotationKeyPatternDeletePropagation = regexp.MustCompile(`^werf.io/delete-propagation$`) SprigFuncs = sprig.TxtFuncMap() + DefaultDockerConfig = filepath.Join(userHomeDir(), ".docker") DefaultPlanArtifactLifetime = 2 * time.Hour DefaultResourceValidationSchema = []string{ "https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/{{ .NormalizedKubernetesVersion }}-standalone{{ .StrictSuffix }}/{{ .ResourceKind }}{{ .KindSuffix }}.json", @@ -308,14 +307,6 @@ func SubStageWeighted(stage Stage, weight int) Stage { return Stage(fmt.Sprintf("%s/weight:%d", stage, weight)) } -func dockerConfigDir() string { - if d := os.Getenv("DOCKER_CONFIG"); d != "" { - return d - } - - return filepath.Join(userHomeDir(), ".docker") -} - func userHomeDir() string { home, _ := os.UserHomeDir() if home == "" && runtime.GOOS != "windows" {