Adds include-crds and refactor using flagRegistrar and generic flag system
Signed-off-by: yxxhero <aiopsclub@163.com>
This commit is contained in:
parent
da3402de85
commit
4aa54423b6
11
cmd/apply.go
11
cmd/apply.go
|
|
@ -5,15 +5,20 @@ import (
|
||||||
|
|
||||||
"github.com/helmfile/helmfile/pkg/app"
|
"github.com/helmfile/helmfile/pkg/app"
|
||||||
"github.com/helmfile/helmfile/pkg/config"
|
"github.com/helmfile/helmfile/pkg/config"
|
||||||
|
"github.com/helmfile/helmfile/pkg/flags"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewApplyCmd returns apply subcmd
|
// NewApplyCmd returns apply subcmd
|
||||||
func NewApplyCmd(globalCfg *config.GlobalImpl) *cobra.Command {
|
func NewApplyCmd(globalCfg *config.GlobalImpl) *cobra.Command {
|
||||||
applyOptions := &config.ApplyOptions{}
|
applyOptions := config.NewApplyOptions()
|
||||||
|
flagRegistrar := flags.NewApplyFlagRegistrar()
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "apply",
|
Use: "apply",
|
||||||
Short: "Apply all resources from state file only when there are changes",
|
Short: "Apply all resources from state file only when there are changes",
|
||||||
|
PreRun: func(cmd *cobra.Command, args []string) {
|
||||||
|
flagRegistrar.TransferFlags(cmd, applyOptions)
|
||||||
|
},
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
applyImpl := config.NewApplyImpl(globalCfg, applyOptions)
|
applyImpl := config.NewApplyImpl(globalCfg, applyOptions)
|
||||||
|
|
||||||
|
|
@ -44,7 +49,6 @@ func NewApplyCmd(globalCfg *config.GlobalImpl) *cobra.Command {
|
||||||
f.StringVar(&applyOptions.SyncArgs, "sync-args", "", `pass args to helm upgrade`)
|
f.StringVar(&applyOptions.SyncArgs, "sync-args", "", `pass args to helm upgrade`)
|
||||||
f.StringVar(&globalCfg.GlobalOptions.Args, "args", "", "pass args to helm exec")
|
f.StringVar(&globalCfg.GlobalOptions.Args, "args", "", "pass args to helm exec")
|
||||||
f.BoolVar(&applyOptions.SkipCleanup, "skip-cleanup", false, "Stop cleaning up temporary values generated by helmfile and helm-secrets. Useful for debugging. Don't use in production for security")
|
f.BoolVar(&applyOptions.SkipCleanup, "skip-cleanup", false, "Stop cleaning up temporary values generated by helmfile and helm-secrets. Useful for debugging. Don't use in production for security")
|
||||||
f.BoolVar(&applyOptions.SkipCRDs, "skip-crds", false, "if set, no CRDs will be installed on sync. By default, CRDs are installed if not already present")
|
|
||||||
f.BoolVar(&applyOptions.SkipNeeds, "skip-needs", true, `do not automatically include releases from the target release's "needs" when --selector/-l flag is provided. Does nothing when --selector/-l flag is not provided. Defaults to true when --include-needs or --include-transitive-needs is not provided`)
|
f.BoolVar(&applyOptions.SkipNeeds, "skip-needs", true, `do not automatically include releases from the target release's "needs" when --selector/-l flag is provided. Does nothing when --selector/-l flag is not provided. Defaults to true when --include-needs or --include-transitive-needs is not provided`)
|
||||||
f.BoolVar(&applyOptions.IncludeNeeds, "include-needs", false, `automatically include releases from the target release's "needs" when --selector/-l flag is provided. Does nothing when --selector/-l flag is not provided`)
|
f.BoolVar(&applyOptions.IncludeNeeds, "include-needs", false, `automatically include releases from the target release's "needs" when --selector/-l flag is provided. Does nothing when --selector/-l flag is not provided`)
|
||||||
f.BoolVar(&applyOptions.IncludeTransitiveNeeds, "include-transitive-needs", false, `like --include-needs, but also includes transitive needs (needs of needs). Does nothing when --selector/-l flag is not provided. Overrides exclusions of other selectors and conditions.`)
|
f.BoolVar(&applyOptions.IncludeTransitiveNeeds, "include-transitive-needs", false, `like --include-needs, but also includes transitive needs (needs of needs). Does nothing when --selector/-l flag is not provided. Overrides exclusions of other selectors and conditions.`)
|
||||||
|
|
@ -68,5 +72,8 @@ func NewApplyCmd(globalCfg *config.GlobalImpl) *cobra.Command {
|
||||||
f.StringVar(&applyOptions.Cascade, "cascade", "", "pass cascade to helm exec, default: background")
|
f.StringVar(&applyOptions.Cascade, "cascade", "", "pass cascade to helm exec, default: background")
|
||||||
f.StringArrayVar(&applyOptions.SuppressOutputLineRegex, "suppress-output-line-regex", nil, "a list of regex patterns to suppress output lines from the diff output")
|
f.StringArrayVar(&applyOptions.SuppressOutputLineRegex, "suppress-output-line-regex", nil, "a list of regex patterns to suppress output lines from the diff output")
|
||||||
|
|
||||||
|
// Register flags using the registrar
|
||||||
|
flagRegistrar.RegisterFlags(cmd)
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,15 +5,20 @@ import (
|
||||||
|
|
||||||
"github.com/helmfile/helmfile/pkg/app"
|
"github.com/helmfile/helmfile/pkg/app"
|
||||||
"github.com/helmfile/helmfile/pkg/config"
|
"github.com/helmfile/helmfile/pkg/config"
|
||||||
|
"github.com/helmfile/helmfile/pkg/flags"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewDiffCmd returns diff subcmd
|
// NewDiffCmd returns diff subcmd
|
||||||
func NewDiffCmd(globalCfg *config.GlobalImpl) *cobra.Command {
|
func NewDiffCmd(globalCfg *config.GlobalImpl) *cobra.Command {
|
||||||
diffOptions := config.NewDiffOptions()
|
diffOptions := config.NewDiffOptions()
|
||||||
|
flagRegistrar := flags.NewDiffFlagRegistrar()
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "diff",
|
Use: "diff",
|
||||||
Short: "Diff releases defined in state file",
|
Short: "Diff releases defined in state file",
|
||||||
|
PreRun: func(cmd *cobra.Command, args []string) {
|
||||||
|
flagRegistrar.TransferFlags(cmd, diffOptions)
|
||||||
|
},
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
diffImpl := config.NewDiffImpl(globalCfg, diffOptions)
|
diffImpl := config.NewDiffImpl(globalCfg, diffOptions)
|
||||||
err := config.NewCLIConfigImpl(diffImpl.GlobalImpl)
|
err := config.NewCLIConfigImpl(diffImpl.GlobalImpl)
|
||||||
|
|
@ -56,5 +61,8 @@ func NewDiffCmd(globalCfg *config.GlobalImpl) *cobra.Command {
|
||||||
f.StringArrayVar(&diffOptions.PostRendererArgs, "post-renderer-args", nil, `pass --post-renderer-args to "helm template" or "helm upgrade --install"`)
|
f.StringArrayVar(&diffOptions.PostRendererArgs, "post-renderer-args", nil, `pass --post-renderer-args to "helm template" or "helm upgrade --install"`)
|
||||||
f.StringArrayVar(&diffOptions.SuppressOutputLineRegex, "suppress-output-line-regex", nil, "a list of regex patterns to suppress output lines from the diff output")
|
f.StringArrayVar(&diffOptions.SuppressOutputLineRegex, "suppress-output-line-regex", nil, "a list of regex patterns to suppress output lines from the diff output")
|
||||||
|
|
||||||
|
// Register flags using the registrar
|
||||||
|
flagRegistrar.RegisterFlags(cmd)
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,15 +5,20 @@ import (
|
||||||
|
|
||||||
"github.com/helmfile/helmfile/pkg/app"
|
"github.com/helmfile/helmfile/pkg/app"
|
||||||
"github.com/helmfile/helmfile/pkg/config"
|
"github.com/helmfile/helmfile/pkg/config"
|
||||||
|
"github.com/helmfile/helmfile/pkg/flags"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewSyncCmd returns sync subcmd
|
// NewSyncCmd returns sync subcmd
|
||||||
func NewSyncCmd(globalCfg *config.GlobalImpl) *cobra.Command {
|
func NewSyncCmd(globalCfg *config.GlobalImpl) *cobra.Command {
|
||||||
syncOptions := config.NewSyncOptions()
|
syncOptions := config.NewSyncOptions()
|
||||||
|
flagRegistrar := flags.NewSyncFlagRegistrar()
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "sync",
|
Use: "sync",
|
||||||
Short: "Sync releases defined in state file",
|
Short: "Sync releases defined in state file",
|
||||||
|
PreRun: func(cmd *cobra.Command, args []string) {
|
||||||
|
flagRegistrar.TransferFlags(cmd, syncOptions)
|
||||||
|
},
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
syncImpl := config.NewSyncImpl(globalCfg, syncOptions)
|
syncImpl := config.NewSyncImpl(globalCfg, syncOptions)
|
||||||
err := config.NewCLIConfigImpl(syncImpl.GlobalImpl)
|
err := config.NewCLIConfigImpl(syncImpl.GlobalImpl)
|
||||||
|
|
@ -38,7 +43,6 @@ func NewSyncCmd(globalCfg *config.GlobalImpl) *cobra.Command {
|
||||||
f.IntVar(&syncOptions.Concurrency, "concurrency", 0, "maximum number of concurrent helm processes to run, 0 is unlimited")
|
f.IntVar(&syncOptions.Concurrency, "concurrency", 0, "maximum number of concurrent helm processes to run, 0 is unlimited")
|
||||||
f.BoolVar(&syncOptions.Validate, "validate", false, "validate your manifests against the Kubernetes cluster you are currently pointing at. Note that this requires access to a Kubernetes cluster to obtain information necessary for validating, like the sync of available API versions")
|
f.BoolVar(&syncOptions.Validate, "validate", false, "validate your manifests against the Kubernetes cluster you are currently pointing at. Note that this requires access to a Kubernetes cluster to obtain information necessary for validating, like the sync of available API versions")
|
||||||
f.BoolVar(&syncOptions.SkipNeeds, "skip-needs", true, `do not automatically include releases from the target release's "needs" when --selector/-l flag is provided. Does nothing when --selector/-l flag is not provided. Defaults to true when --include-needs or --include-transitive-needs is not provided`)
|
f.BoolVar(&syncOptions.SkipNeeds, "skip-needs", true, `do not automatically include releases from the target release's "needs" when --selector/-l flag is provided. Does nothing when --selector/-l flag is not provided. Defaults to true when --include-needs or --include-transitive-needs is not provided`)
|
||||||
f.BoolVar(&syncOptions.SkipCRDs, "skip-crds", false, "if set, no CRDs will be installed on sync. By default, CRDs are installed if not already present")
|
|
||||||
f.BoolVar(&syncOptions.IncludeNeeds, "include-needs", false, `automatically include releases from the target release's "needs" when --selector/-l flag is provided. Does nothing when --selector/-l flag is not provided`)
|
f.BoolVar(&syncOptions.IncludeNeeds, "include-needs", false, `automatically include releases from the target release's "needs" when --selector/-l flag is provided. Does nothing when --selector/-l flag is not provided`)
|
||||||
f.BoolVar(&syncOptions.IncludeTransitiveNeeds, "include-transitive-needs", false, `like --include-needs, but also includes transitive needs (needs of needs). Does nothing when --selector/-l flag is not provided. Overrides exclusions of other selectors and conditions.`)
|
f.BoolVar(&syncOptions.IncludeTransitiveNeeds, "include-transitive-needs", false, `like --include-needs, but also includes transitive needs (needs of needs). Does nothing when --selector/-l flag is not provided. Overrides exclusions of other selectors and conditions.`)
|
||||||
f.BoolVar(&syncOptions.HideNotes, "hide-notes", false, "add --hide-notes flag to helm")
|
f.BoolVar(&syncOptions.HideNotes, "hide-notes", false, "add --hide-notes flag to helm")
|
||||||
|
|
@ -53,5 +57,8 @@ func NewSyncCmd(globalCfg *config.GlobalImpl) *cobra.Command {
|
||||||
f.BoolVar(&syncOptions.SkipSchemaValidation, "skip-schema-validation", false, `pass --skip-schema-validation to "helm template" or "helm upgrade --install"`)
|
f.BoolVar(&syncOptions.SkipSchemaValidation, "skip-schema-validation", false, `pass --skip-schema-validation to "helm template" or "helm upgrade --install"`)
|
||||||
f.StringVar(&syncOptions.Cascade, "cascade", "", "pass cascade to helm exec, default: background")
|
f.StringVar(&syncOptions.Cascade, "cascade", "", "pass cascade to helm exec, default: background")
|
||||||
|
|
||||||
|
// Register flags using the registrar
|
||||||
|
flagRegistrar.RegisterFlags(cmd)
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,15 +5,20 @@ import (
|
||||||
|
|
||||||
"github.com/helmfile/helmfile/pkg/app"
|
"github.com/helmfile/helmfile/pkg/app"
|
||||||
"github.com/helmfile/helmfile/pkg/config"
|
"github.com/helmfile/helmfile/pkg/config"
|
||||||
|
"github.com/helmfile/helmfile/pkg/flags"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewTemplateCmd returm template subcmd
|
// NewTemplateCmd returm template subcmd
|
||||||
func NewTemplateCmd(globalCfg *config.GlobalImpl) *cobra.Command {
|
func NewTemplateCmd(globalCfg *config.GlobalImpl) *cobra.Command {
|
||||||
templateOptions := config.NewTemplateOptions()
|
templateOptions := config.NewTemplateOptions()
|
||||||
|
flagRegistrar := flags.NewDiffFlagRegistrar()
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "template",
|
Use: "template",
|
||||||
Short: "Template releases defined in state file",
|
Short: "Template releases defined in state file",
|
||||||
|
PreRun: func(cmd *cobra.Command, args []string) {
|
||||||
|
flagRegistrar.TransferFlags(cmd, templateOptions)
|
||||||
|
},
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
templateImpl := config.NewTemplateImpl(globalCfg, templateOptions)
|
templateImpl := config.NewTemplateImpl(globalCfg, templateOptions)
|
||||||
err := config.NewCLIConfigImpl(templateImpl.GlobalImpl)
|
err := config.NewCLIConfigImpl(templateImpl.GlobalImpl)
|
||||||
|
|
@ -38,7 +43,6 @@ func NewTemplateCmd(globalCfg *config.GlobalImpl) *cobra.Command {
|
||||||
f.StringVar(&templateOptions.OutputDirTemplate, "output-dir-template", "", "go text template for generating the output directory. Default: {{ .OutputDir }}/{{ .State.BaseName }}-{{ .State.AbsPathSHA1 }}-{{ .Release.Name}}")
|
f.StringVar(&templateOptions.OutputDirTemplate, "output-dir-template", "", "go text template for generating the output directory. Default: {{ .OutputDir }}/{{ .State.BaseName }}-{{ .State.AbsPathSHA1 }}-{{ .Release.Name}}")
|
||||||
f.IntVar(&templateOptions.Concurrency, "concurrency", 0, "maximum number of concurrent helm processes to run, 0 is unlimited")
|
f.IntVar(&templateOptions.Concurrency, "concurrency", 0, "maximum number of concurrent helm processes to run, 0 is unlimited")
|
||||||
f.BoolVar(&templateOptions.Validate, "validate", false, "validate your manifests against the Kubernetes cluster you are currently pointing at. Note that this requires access to a Kubernetes cluster to obtain information necessary for validating, like the template of available API versions")
|
f.BoolVar(&templateOptions.Validate, "validate", false, "validate your manifests against the Kubernetes cluster you are currently pointing at. Note that this requires access to a Kubernetes cluster to obtain information necessary for validating, like the template of available API versions")
|
||||||
f.BoolVar(&templateOptions.IncludeCRDs, "include-crds", false, "include CRDs in the templated output")
|
|
||||||
f.BoolVar(&templateOptions.SkipTests, "skip-tests", false, "skip tests from templated output")
|
f.BoolVar(&templateOptions.SkipTests, "skip-tests", false, "skip tests from templated output")
|
||||||
f.BoolVar(&templateOptions.SkipNeeds, "skip-needs", true, `do not automatically include releases from the target release's "needs" when --selector/-l flag is provided. Does nothing when --selector/-l flag is not provided. Defaults to true when --include-needs or --include-transitive-needs is not provided`)
|
f.BoolVar(&templateOptions.SkipNeeds, "skip-needs", true, `do not automatically include releases from the target release's "needs" when --selector/-l flag is provided. Does nothing when --selector/-l flag is not provided. Defaults to true when --include-needs or --include-transitive-needs is not provided`)
|
||||||
f.BoolVar(&templateOptions.IncludeNeeds, "include-needs", false, `automatically include releases from the target release's "needs" when --selector/-l flag is provided. Does nothing when --selector/-l flag is not provided`)
|
f.BoolVar(&templateOptions.IncludeNeeds, "include-needs", false, `automatically include releases from the target release's "needs" when --selector/-l flag is provided. Does nothing when --selector/-l flag is not provided`)
|
||||||
|
|
@ -51,5 +55,6 @@ func NewTemplateCmd(globalCfg *config.GlobalImpl) *cobra.Command {
|
||||||
f.StringVar(&templateOptions.KubeVersion, "kube-version", "", `pass --kube-version to "helm template". Overrides kubeVersion in helmfile.yaml`)
|
f.StringVar(&templateOptions.KubeVersion, "kube-version", "", `pass --kube-version to "helm template". Overrides kubeVersion in helmfile.yaml`)
|
||||||
f.StringArrayVar(&templateOptions.ShowOnly, "show-only", nil, `pass --show-only to "helm template"`)
|
f.StringArrayVar(&templateOptions.ShowOnly, "show-only", nil, `pass --show-only to "helm template"`)
|
||||||
|
|
||||||
|
flagRegistrar.RegisterFlags(cmd)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -152,13 +152,11 @@ func (a *App) Diff(c DiffConfigProvider) error {
|
||||||
|
|
||||||
var errs []error
|
var errs []error
|
||||||
|
|
||||||
includeCRDs := !c.SkipCRDs()
|
|
||||||
|
|
||||||
prepErr := run.withPreparedCharts("diff", state.ChartPrepareOptions{
|
prepErr := run.withPreparedCharts("diff", state.ChartPrepareOptions{
|
||||||
SkipRepos: c.SkipRefresh() || c.SkipDeps(),
|
SkipRepos: c.SkipRefresh() || c.SkipDeps(),
|
||||||
SkipRefresh: c.SkipRefresh(),
|
SkipRefresh: c.SkipRefresh(),
|
||||||
SkipDeps: c.SkipDeps(),
|
SkipDeps: c.SkipDeps(),
|
||||||
IncludeCRDs: &includeCRDs,
|
IncludeCRDs: c.ShouldIncludeCRDs(),
|
||||||
Validate: c.Validate(),
|
Validate: c.Validate(),
|
||||||
Concurrency: c.Concurrency(),
|
Concurrency: c.Concurrency(),
|
||||||
IncludeTransitiveNeeds: c.IncludeNeeds(),
|
IncludeTransitiveNeeds: c.IncludeNeeds(),
|
||||||
|
|
@ -215,8 +213,6 @@ func (a *App) Diff(c DiffConfigProvider) error {
|
||||||
|
|
||||||
func (a *App) Template(c TemplateConfigProvider) error {
|
func (a *App) Template(c TemplateConfigProvider) error {
|
||||||
return a.ForEachState(func(run *Run) (ok bool, errs []error) {
|
return a.ForEachState(func(run *Run) (ok bool, errs []error) {
|
||||||
includeCRDs := c.IncludeCRDs()
|
|
||||||
|
|
||||||
// Live output should never be enabled for the "template" subcommand to avoid breaking `helmfile template | kubectl apply -f -`
|
// Live output should never be enabled for the "template" subcommand to avoid breaking `helmfile template | kubectl apply -f -`
|
||||||
run.helm.SetEnableLiveOutput(false)
|
run.helm.SetEnableLiveOutput(false)
|
||||||
|
|
||||||
|
|
@ -228,7 +224,7 @@ func (a *App) Template(c TemplateConfigProvider) error {
|
||||||
SkipRepos: c.SkipRefresh() || c.SkipDeps(),
|
SkipRepos: c.SkipRefresh() || c.SkipDeps(),
|
||||||
SkipRefresh: c.SkipRefresh(),
|
SkipRefresh: c.SkipRefresh(),
|
||||||
SkipDeps: c.SkipDeps(),
|
SkipDeps: c.SkipDeps(),
|
||||||
IncludeCRDs: &includeCRDs,
|
IncludeCRDs: c.ShouldIncludeCRDs(),
|
||||||
SkipCleanup: c.SkipCleanup(),
|
SkipCleanup: c.SkipCleanup(),
|
||||||
Validate: c.Validate(),
|
Validate: c.Validate(),
|
||||||
Concurrency: c.Concurrency(),
|
Concurrency: c.Concurrency(),
|
||||||
|
|
@ -358,8 +354,6 @@ func (a *App) Fetch(c FetchConfigProvider) error {
|
||||||
|
|
||||||
func (a *App) Sync(c SyncConfigProvider) error {
|
func (a *App) Sync(c SyncConfigProvider) error {
|
||||||
return a.ForEachState(func(run *Run) (ok bool, errs []error) {
|
return a.ForEachState(func(run *Run) (ok bool, errs []error) {
|
||||||
includeCRDs := !c.SkipCRDs()
|
|
||||||
|
|
||||||
prepErr := run.withPreparedCharts("sync", state.ChartPrepareOptions{
|
prepErr := run.withPreparedCharts("sync", state.ChartPrepareOptions{
|
||||||
SkipRepos: c.SkipRefresh() || c.SkipDeps(),
|
SkipRepos: c.SkipRefresh() || c.SkipDeps(),
|
||||||
SkipRefresh: c.SkipRefresh(),
|
SkipRefresh: c.SkipRefresh(),
|
||||||
|
|
@ -367,7 +361,7 @@ func (a *App) Sync(c SyncConfigProvider) error {
|
||||||
Wait: c.Wait(),
|
Wait: c.Wait(),
|
||||||
WaitRetries: c.WaitRetries(),
|
WaitRetries: c.WaitRetries(),
|
||||||
WaitForJobs: c.WaitForJobs(),
|
WaitForJobs: c.WaitForJobs(),
|
||||||
IncludeCRDs: &includeCRDs,
|
IncludeCRDs: c.ShouldIncludeCRDs(),
|
||||||
IncludeTransitiveNeeds: c.IncludeNeeds(),
|
IncludeTransitiveNeeds: c.IncludeNeeds(),
|
||||||
Validate: c.Validate(),
|
Validate: c.Validate(),
|
||||||
Concurrency: c.Concurrency(),
|
Concurrency: c.Concurrency(),
|
||||||
|
|
@ -393,8 +387,6 @@ func (a *App) Apply(c ApplyConfigProvider) error {
|
||||||
opts = append(opts, SetRetainValuesFiles(c.SkipCleanup()))
|
opts = append(opts, SetRetainValuesFiles(c.SkipCleanup()))
|
||||||
|
|
||||||
err := a.ForEachState(func(run *Run) (ok bool, errs []error) {
|
err := a.ForEachState(func(run *Run) (ok bool, errs []error) {
|
||||||
includeCRDs := !c.SkipCRDs()
|
|
||||||
|
|
||||||
prepErr := run.withPreparedCharts("apply", state.ChartPrepareOptions{
|
prepErr := run.withPreparedCharts("apply", state.ChartPrepareOptions{
|
||||||
SkipRepos: c.SkipRefresh() || c.SkipDeps(),
|
SkipRepos: c.SkipRefresh() || c.SkipDeps(),
|
||||||
SkipRefresh: c.SkipRefresh(),
|
SkipRefresh: c.SkipRefresh(),
|
||||||
|
|
@ -402,7 +394,7 @@ func (a *App) Apply(c ApplyConfigProvider) error {
|
||||||
Wait: c.Wait(),
|
Wait: c.Wait(),
|
||||||
WaitRetries: c.WaitRetries(),
|
WaitRetries: c.WaitRetries(),
|
||||||
WaitForJobs: c.WaitForJobs(),
|
WaitForJobs: c.WaitForJobs(),
|
||||||
IncludeCRDs: &includeCRDs,
|
IncludeCRDs: c.ShouldIncludeCRDs(),
|
||||||
SkipCleanup: c.SkipCleanup(),
|
SkipCleanup: c.SkipCleanup(),
|
||||||
Validate: c.Validate(),
|
Validate: c.Validate(),
|
||||||
Concurrency: c.Concurrency(),
|
Concurrency: c.Concurrency(),
|
||||||
|
|
@ -1385,6 +1377,7 @@ func (a *App) apply(r *Run, c ApplyConfigProvider) (bool, bool, []error) {
|
||||||
SkipDiffOnInstall: c.SkipDiffOnInstall(),
|
SkipDiffOnInstall: c.SkipDiffOnInstall(),
|
||||||
ReuseValues: c.ReuseValues(),
|
ReuseValues: c.ReuseValues(),
|
||||||
ResetValues: c.ResetValues(),
|
ResetValues: c.ResetValues(),
|
||||||
|
IncludeCRDs: c.ShouldIncludeCRDs(),
|
||||||
DiffArgs: c.DiffArgs(),
|
DiffArgs: c.DiffArgs(),
|
||||||
PostRenderer: c.PostRenderer(),
|
PostRenderer: c.PostRenderer(),
|
||||||
PostRendererArgs: c.PostRendererArgs(),
|
PostRendererArgs: c.PostRendererArgs(),
|
||||||
|
|
|
||||||
|
|
@ -50,13 +50,14 @@ type ApplyConfigProvider interface {
|
||||||
|
|
||||||
Values() []string
|
Values() []string
|
||||||
Set() []string
|
Set() []string
|
||||||
SkipCRDs() bool
|
|
||||||
SkipDeps() bool
|
SkipDeps() bool
|
||||||
SkipRefresh() bool
|
SkipRefresh() bool
|
||||||
Wait() bool
|
Wait() bool
|
||||||
WaitRetries() int
|
WaitRetries() int
|
||||||
WaitForJobs() bool
|
WaitForJobs() bool
|
||||||
|
|
||||||
|
CRDConfig
|
||||||
|
|
||||||
IncludeTests() bool
|
IncludeTests() bool
|
||||||
|
|
||||||
Suppress() []string
|
Suppress() []string
|
||||||
|
|
@ -101,9 +102,11 @@ type SyncConfigProvider interface {
|
||||||
|
|
||||||
Values() []string
|
Values() []string
|
||||||
Set() []string
|
Set() []string
|
||||||
SkipCRDs() bool
|
|
||||||
SkipDeps() bool
|
SkipDeps() bool
|
||||||
SkipRefresh() bool
|
SkipRefresh() bool
|
||||||
|
|
||||||
|
CRDConfig
|
||||||
|
|
||||||
Wait() bool
|
Wait() bool
|
||||||
WaitRetries() int
|
WaitRetries() int
|
||||||
WaitForJobs() bool
|
WaitForJobs() bool
|
||||||
|
|
@ -135,12 +138,13 @@ type DiffConfigProvider interface {
|
||||||
Values() []string
|
Values() []string
|
||||||
Set() []string
|
Set() []string
|
||||||
Validate() bool
|
Validate() bool
|
||||||
SkipCRDs() bool
|
|
||||||
SkipDeps() bool
|
SkipDeps() bool
|
||||||
SkipRefresh() bool
|
SkipRefresh() bool
|
||||||
|
|
||||||
IncludeTests() bool
|
IncludeTests() bool
|
||||||
|
|
||||||
|
CRDConfig
|
||||||
|
|
||||||
Suppress() []string
|
Suppress() []string
|
||||||
SuppressSecrets() bool
|
SuppressSecrets() bool
|
||||||
ShowSecrets() bool
|
ShowSecrets() bool
|
||||||
|
|
@ -226,8 +230,10 @@ type TemplateConfigProvider interface {
|
||||||
SkipRefresh() bool
|
SkipRefresh() bool
|
||||||
SkipCleanup() bool
|
SkipCleanup() bool
|
||||||
SkipTests() bool
|
SkipTests() bool
|
||||||
|
|
||||||
|
CRDConfig
|
||||||
|
|
||||||
OutputDir() string
|
OutputDir() string
|
||||||
IncludeCRDs() bool
|
|
||||||
NoHooks() bool
|
NoHooks() bool
|
||||||
KubeVersion() string
|
KubeVersion() string
|
||||||
ShowOnly() []string
|
ShowOnly() []string
|
||||||
|
|
@ -237,6 +243,12 @@ type TemplateConfigProvider interface {
|
||||||
concurrencyConfig
|
concurrencyConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CRDConfig interface {
|
||||||
|
SkipCRDs() bool
|
||||||
|
IncludeCRDs() bool
|
||||||
|
ShouldIncludeCRDs() bool
|
||||||
|
}
|
||||||
|
|
||||||
type DAGConfig interface {
|
type DAGConfig interface {
|
||||||
SkipNeeds() bool
|
SkipNeeds() bool
|
||||||
IncludeNeeds() bool
|
IncludeNeeds() bool
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
package common
|
||||||
|
|
||||||
|
// BoolFlag represents a boolean flag that tracks whether it was explicitly set
|
||||||
|
type BoolFlag interface {
|
||||||
|
// Value returns the current boolean value
|
||||||
|
Value() bool
|
||||||
|
|
||||||
|
// WasExplicitlySet returns whether the flag was explicitly set
|
||||||
|
WasExplicitlySet() bool
|
||||||
|
|
||||||
|
// Set sets the value and marks the flag as explicitly set
|
||||||
|
Set(value bool)
|
||||||
|
}
|
||||||
|
|
||||||
|
// boolFlag is the implementation of BoolFlag
|
||||||
|
type boolFlag struct {
|
||||||
|
value bool
|
||||||
|
wasExplicitlySet bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBoolFlag creates a new BoolFlag with default values
|
||||||
|
func NewBoolFlag(defaultValue bool) BoolFlag {
|
||||||
|
return &boolFlag{
|
||||||
|
value: defaultValue,
|
||||||
|
wasExplicitlySet: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value returns the current boolean value
|
||||||
|
func (bf *boolFlag) Value() bool {
|
||||||
|
return bf.value
|
||||||
|
}
|
||||||
|
|
||||||
|
// WasExplicitlySet returns whether the flag was explicitly set
|
||||||
|
func (bf *boolFlag) WasExplicitlySet() bool {
|
||||||
|
return bf.wasExplicitlySet
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set sets the value and marks the flag as explicitly set
|
||||||
|
func (bf *boolFlag) Set(value bool) {
|
||||||
|
bf.value = value
|
||||||
|
bf.wasExplicitlySet = true
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,94 @@
|
||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNewBoolFlag(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
defaultValue bool
|
||||||
|
expected bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "default true",
|
||||||
|
defaultValue: true,
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "default false",
|
||||||
|
defaultValue: false,
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
flag := NewBoolFlag(tt.defaultValue)
|
||||||
|
|
||||||
|
// Check initial state
|
||||||
|
assert.Equal(t, tt.expected, flag.Value(), "Value should match default")
|
||||||
|
assert.False(t, flag.WasExplicitlySet(), "New flag should not be marked as explicitly set")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBoolFlag_Set(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
defaultValue bool
|
||||||
|
setValue bool
|
||||||
|
expected bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "default false, set true",
|
||||||
|
defaultValue: false,
|
||||||
|
setValue: true,
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "default true, set false",
|
||||||
|
defaultValue: true,
|
||||||
|
setValue: false,
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
flag := NewBoolFlag(tt.defaultValue)
|
||||||
|
|
||||||
|
// Set the value
|
||||||
|
flag.Set(tt.setValue)
|
||||||
|
|
||||||
|
// Check state after setting
|
||||||
|
assert.Equal(t, tt.expected, flag.Value(), "Value should match set value")
|
||||||
|
assert.True(t, flag.WasExplicitlySet(), "Flag should be marked as explicitly set")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBoolFlag_MultipleSet(t *testing.T) {
|
||||||
|
flag := NewBoolFlag(false)
|
||||||
|
|
||||||
|
// Initial state
|
||||||
|
assert.False(t, flag.Value())
|
||||||
|
assert.False(t, flag.WasExplicitlySet())
|
||||||
|
|
||||||
|
// First set
|
||||||
|
flag.Set(true)
|
||||||
|
assert.True(t, flag.Value())
|
||||||
|
assert.True(t, flag.WasExplicitlySet())
|
||||||
|
|
||||||
|
// Second set
|
||||||
|
flag.Set(false)
|
||||||
|
assert.False(t, flag.Value())
|
||||||
|
assert.True(t, flag.WasExplicitlySet(), "Flag should remain explicitly set")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBoolFlag_Implementation(t *testing.T) {
|
||||||
|
// Test that boolFlag properly implements BoolFlag interface
|
||||||
|
var _ BoolFlag = &boolFlag{}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
package common
|
||||||
|
|
||||||
|
// For array/slice flags
|
||||||
|
type StringArrayFlag interface {
|
||||||
|
Values() []string
|
||||||
|
WasExplicitlySet() bool
|
||||||
|
Add(value string)
|
||||||
|
Set(values []string)
|
||||||
|
}
|
||||||
|
|
||||||
|
type stringArrayFlag struct {
|
||||||
|
values []string
|
||||||
|
wasExplicitlySet bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewStringArrayFlag creates a new StringArrayFlag with the given default values
|
||||||
|
// Create a defensive copy of the default values to prevent external modifications
|
||||||
|
// and to ensure that the original values remain unchanged.
|
||||||
|
func NewStringArrayFlag(defaultValues []string) StringArrayFlag {
|
||||||
|
valuesCopy := make([]string, len(defaultValues))
|
||||||
|
copy(valuesCopy, defaultValues)
|
||||||
|
|
||||||
|
return &stringArrayFlag{
|
||||||
|
values: valuesCopy,
|
||||||
|
wasExplicitlySet: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Values returns the values of the flag
|
||||||
|
// It returns a copy of the values to prevent external modifications
|
||||||
|
// and to ensure that the original values remain unchanged.
|
||||||
|
// This is important for flags that may be modified by the user
|
||||||
|
// or other parts of the program.
|
||||||
|
func (f *stringArrayFlag) Values() []string {
|
||||||
|
// Return a copy to prevent external modifications
|
||||||
|
valuesCopy := make([]string, len(f.values))
|
||||||
|
copy(valuesCopy, f.values)
|
||||||
|
return valuesCopy
|
||||||
|
}
|
||||||
|
|
||||||
|
// WasExplicitlySet returns whether the flag was explicitly set
|
||||||
|
func (f *stringArrayFlag) WasExplicitlySet() bool {
|
||||||
|
return f.wasExplicitlySet
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set sets the values and marks the flag as explicitly set
|
||||||
|
func (f *stringArrayFlag) Set(values []string) {
|
||||||
|
f.values = values
|
||||||
|
f.wasExplicitlySet = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add sets the value and marks the flag as explicitly set
|
||||||
|
func (f *stringArrayFlag) Add(value string) {
|
||||||
|
f.values = append(f.values, value)
|
||||||
|
f.wasExplicitlySet = true
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,195 @@
|
||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNewStringArrayFlag(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
defaultValue []string
|
||||||
|
expected []string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "nil default",
|
||||||
|
defaultValue: nil,
|
||||||
|
expected: []string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "empty default",
|
||||||
|
defaultValue: []string{},
|
||||||
|
expected: []string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "non-empty default",
|
||||||
|
defaultValue: []string{"value1", "value2"},
|
||||||
|
expected: []string{"value1", "value2"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
flag := NewStringArrayFlag(tt.defaultValue)
|
||||||
|
|
||||||
|
// Check initial state
|
||||||
|
assert.Equal(t, tt.expected, flag.Values(), "Values should match default")
|
||||||
|
assert.False(t, flag.WasExplicitlySet(), "New flag should not be marked as explicitly set")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStringArrayFlag_Set(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
defaultValue []string
|
||||||
|
setValue []string
|
||||||
|
expected []string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "nil default, set values",
|
||||||
|
defaultValue: nil,
|
||||||
|
setValue: []string{"new1", "new2"},
|
||||||
|
expected: []string{"new1", "new2"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "non-empty default, set empty",
|
||||||
|
defaultValue: []string{"default1", "default2"},
|
||||||
|
setValue: []string{},
|
||||||
|
expected: []string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "non-empty default, set new values",
|
||||||
|
defaultValue: []string{"default1", "default2"},
|
||||||
|
setValue: []string{"new1", "new2"},
|
||||||
|
expected: []string{"new1", "new2"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
flag := NewStringArrayFlag(tt.defaultValue)
|
||||||
|
|
||||||
|
// Set the values
|
||||||
|
flag.Set(tt.setValue)
|
||||||
|
|
||||||
|
// Check state after setting
|
||||||
|
assert.Equal(t, tt.expected, flag.Values(), "Values should match set values")
|
||||||
|
assert.True(t, flag.WasExplicitlySet(), "Flag should be marked as explicitly set")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStringArrayFlag_Add(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
defaultValue []string
|
||||||
|
addValue string
|
||||||
|
expected []string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "nil default, add value",
|
||||||
|
defaultValue: nil,
|
||||||
|
addValue: "new",
|
||||||
|
expected: []string{"new"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "empty default, add value",
|
||||||
|
defaultValue: []string{},
|
||||||
|
addValue: "new",
|
||||||
|
expected: []string{"new"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "non-empty default, add value",
|
||||||
|
defaultValue: []string{"default1", "default2"},
|
||||||
|
addValue: "new",
|
||||||
|
expected: []string{"default1", "default2", "new"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
flag := NewStringArrayFlag(tt.defaultValue)
|
||||||
|
|
||||||
|
// Add the value
|
||||||
|
flag.Add(tt.addValue)
|
||||||
|
|
||||||
|
// Check state after adding
|
||||||
|
assert.Equal(t, tt.expected, flag.Values(), "Values should include added value")
|
||||||
|
assert.True(t, flag.WasExplicitlySet(), "Flag should be marked as explicitly set")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStringArrayFlag_MultipleOperations(t *testing.T) {
|
||||||
|
flag := NewStringArrayFlag([]string{"initial"})
|
||||||
|
|
||||||
|
// Initial state
|
||||||
|
assert.Equal(t, []string{"initial"}, flag.Values())
|
||||||
|
assert.False(t, flag.WasExplicitlySet())
|
||||||
|
|
||||||
|
// Add a value
|
||||||
|
flag.Add("added")
|
||||||
|
assert.Equal(t, []string{"initial", "added"}, flag.Values())
|
||||||
|
assert.True(t, flag.WasExplicitlySet())
|
||||||
|
|
||||||
|
// Set completely new values
|
||||||
|
flag.Set([]string{"new1", "new2"})
|
||||||
|
assert.Equal(t, []string{"new1", "new2"}, flag.Values())
|
||||||
|
assert.True(t, flag.WasExplicitlySet(), "Flag should remain explicitly set")
|
||||||
|
|
||||||
|
// Add another value after Set
|
||||||
|
flag.Add("added2")
|
||||||
|
assert.Equal(t, []string{"new1", "new2", "added2"}, flag.Values())
|
||||||
|
assert.True(t, flag.WasExplicitlySet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStringArrayFlag_Implementation(t *testing.T) {
|
||||||
|
// Test that stringArrayFlag properly implements StringArrayFlag interface
|
||||||
|
var _ StringArrayFlag = &stringArrayFlag{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStringArrayFlag_DefensiveCopy(t *testing.T) {
|
||||||
|
// Test that modifying the original slice doesn't affect the flag
|
||||||
|
original := []string{"value1", "value2"}
|
||||||
|
flag := NewStringArrayFlag(original)
|
||||||
|
|
||||||
|
// Verify initial state
|
||||||
|
assert.Equal(t, []string{"value1", "value2"}, flag.Values())
|
||||||
|
|
||||||
|
// Modify the original slice - should NOT affect the flag's internal state
|
||||||
|
// because NewStringArrayFlag creates a defensive copy
|
||||||
|
original[0] = "modified"
|
||||||
|
original = append(original, "added")
|
||||||
|
|
||||||
|
// Flag values should remain unchanged
|
||||||
|
assert.Equal(t, []string{"value1", "value2"}, flag.Values())
|
||||||
|
|
||||||
|
// Test that modifying the returned slice doesn't affect the flag
|
||||||
|
values := flag.Values()
|
||||||
|
values[0] = "modified"
|
||||||
|
values = append(values, "added")
|
||||||
|
|
||||||
|
// Flag values should remain unchanged because Values() returns a copy
|
||||||
|
assert.Equal(t, []string{"value1", "value2"}, flag.Values())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStringArrayFlag_SetDefensiveCopy(t *testing.T) {
|
||||||
|
// Test that Set doesn't create a defensive copy (current implementation)
|
||||||
|
flag := NewStringArrayFlag([]string{})
|
||||||
|
|
||||||
|
// Create a slice to set
|
||||||
|
setValues := []string{"value1", "value2"}
|
||||||
|
flag.Set(setValues)
|
||||||
|
|
||||||
|
// Verify state after setting
|
||||||
|
assert.Equal(t, []string{"value1", "value2"}, flag.Values())
|
||||||
|
|
||||||
|
// Modify the original slice - this WILL affect the flag's internal state
|
||||||
|
// because Set doesn't create a defensive copy in the current implementation
|
||||||
|
setValues[0] = "modified"
|
||||||
|
|
||||||
|
// Flag values will reflect the modification
|
||||||
|
assert.Equal(t, []string{"modified", "value2"}, flag.Values())
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
package common
|
||||||
|
|
||||||
|
type StringFlag interface {
|
||||||
|
Value() string
|
||||||
|
WasExplicitlySet() bool
|
||||||
|
Set(value string)
|
||||||
|
}
|
||||||
|
|
||||||
|
type stringFlag struct {
|
||||||
|
value string
|
||||||
|
wasExplicitlySet bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewStringFlag(defaultValue string) StringFlag {
|
||||||
|
return &stringFlag{
|
||||||
|
value: defaultValue,
|
||||||
|
wasExplicitlySet: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value returns the current boolean value
|
||||||
|
func (f *stringFlag) Value() string {
|
||||||
|
return f.value
|
||||||
|
}
|
||||||
|
|
||||||
|
// WasExplicitlySet returns whether the flag was explicitly set
|
||||||
|
func (f *stringFlag) WasExplicitlySet() bool {
|
||||||
|
return f.wasExplicitlySet
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set sets the value and marks the flag as explicitly set
|
||||||
|
func (f *stringFlag) Set(value string) {
|
||||||
|
f.value = value
|
||||||
|
f.wasExplicitlySet = true
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,100 @@
|
||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNewStringFlag(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
defaultValue string
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "empty default",
|
||||||
|
defaultValue: "",
|
||||||
|
expected: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "non-empty default",
|
||||||
|
defaultValue: "default",
|
||||||
|
expected: "default",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
flag := NewStringFlag(tt.defaultValue)
|
||||||
|
|
||||||
|
// Check initial state
|
||||||
|
assert.Equal(t, tt.expected, flag.Value(), "Value should match default")
|
||||||
|
assert.False(t, flag.WasExplicitlySet(), "New flag should not be marked as explicitly set")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStringFlag_Set(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
defaultValue string
|
||||||
|
setValue string
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "empty default, set value",
|
||||||
|
defaultValue: "",
|
||||||
|
setValue: "new value",
|
||||||
|
expected: "new value",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "non-empty default, set empty",
|
||||||
|
defaultValue: "default",
|
||||||
|
setValue: "",
|
||||||
|
expected: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "non-empty default, set new value",
|
||||||
|
defaultValue: "default",
|
||||||
|
setValue: "new value",
|
||||||
|
expected: "new value",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
flag := NewStringFlag(tt.defaultValue)
|
||||||
|
|
||||||
|
// Set the value
|
||||||
|
flag.Set(tt.setValue)
|
||||||
|
|
||||||
|
// Check state after setting
|
||||||
|
assert.Equal(t, tt.expected, flag.Value(), "Value should match set value")
|
||||||
|
assert.True(t, flag.WasExplicitlySet(), "Flag should be marked as explicitly set")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStringFlag_MultipleSet(t *testing.T) {
|
||||||
|
flag := NewStringFlag("initial")
|
||||||
|
|
||||||
|
// Initial state
|
||||||
|
assert.Equal(t, "initial", flag.Value())
|
||||||
|
assert.False(t, flag.WasExplicitlySet())
|
||||||
|
|
||||||
|
// First set
|
||||||
|
flag.Set("first")
|
||||||
|
assert.Equal(t, "first", flag.Value())
|
||||||
|
assert.True(t, flag.WasExplicitlySet())
|
||||||
|
|
||||||
|
// Second set
|
||||||
|
flag.Set("second")
|
||||||
|
assert.Equal(t, "second", flag.Value())
|
||||||
|
assert.True(t, flag.WasExplicitlySet(), "Flag should remain explicitly set")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStringFlag_Implementation(t *testing.T) {
|
||||||
|
// Test that stringFlag properly implements StringFlag interface
|
||||||
|
var _ StringFlag = &stringFlag{}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
package config
|
package config
|
||||||
|
|
||||||
|
import "github.com/helmfile/helmfile/pkg/common"
|
||||||
|
|
||||||
// ApplyOptoons is the options for the apply command
|
// ApplyOptoons is the options for the apply command
|
||||||
type ApplyOptions struct {
|
type ApplyOptions struct {
|
||||||
// Set is a list of key value pairs to be merged into the command
|
// Set is a list of key value pairs to be merged into the command
|
||||||
|
|
@ -20,8 +22,10 @@ type ApplyOptions struct {
|
||||||
StripTrailingCR bool
|
StripTrailingCR bool
|
||||||
// SkipCleanup is true if the cleanup of temporary values files should be skipped
|
// SkipCleanup is true if the cleanup of temporary values files should be skipped
|
||||||
SkipCleanup bool
|
SkipCleanup bool
|
||||||
// SkipCRDs is true if the CRDs should be skipped
|
// SkipCRDsFlag is true if the CRDs should be skipped
|
||||||
SkipCRDs bool
|
SkipCRDsFlag common.BoolFlag
|
||||||
|
// IncludeCRDsFlag is true if the CRDs should be included
|
||||||
|
IncludeCRDsFlag common.BoolFlag
|
||||||
// SkipNeeds is true if the needs should be skipped
|
// SkipNeeds is true if the needs should be skipped
|
||||||
SkipNeeds bool
|
SkipNeeds bool
|
||||||
// IncludeNeeds is true if the needs should be included
|
// IncludeNeeds is true if the needs should be included
|
||||||
|
|
@ -77,7 +81,12 @@ type ApplyOptions struct {
|
||||||
|
|
||||||
// NewApply creates a new Apply
|
// NewApply creates a new Apply
|
||||||
func NewApplyOptions() *ApplyOptions {
|
func NewApplyOptions() *ApplyOptions {
|
||||||
return &ApplyOptions{}
|
newOptions := &ApplyOptions{
|
||||||
|
IncludeCRDsFlag: common.NewBoolFlag(false),
|
||||||
|
SkipCRDsFlag: common.NewBoolFlag(false),
|
||||||
|
}
|
||||||
|
|
||||||
|
return newOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
// ApplyImpl is impl for applyOptions
|
// ApplyImpl is impl for applyOptions
|
||||||
|
|
@ -149,9 +158,22 @@ func (a *ApplyImpl) NoHooks() bool {
|
||||||
return a.ApplyOptions.NoHooks
|
return a.ApplyOptions.NoHooks
|
||||||
}
|
}
|
||||||
|
|
||||||
// SkipCRDs returns the skip crds.
|
// SkipCRDs returns the skip CRDs.
|
||||||
func (a *ApplyImpl) SkipCRDs() bool {
|
func (a *ApplyImpl) SkipCRDs() bool {
|
||||||
return a.ApplyOptions.SkipCRDs
|
return a.ApplyOptions.SkipCRDsFlag.Value()
|
||||||
|
}
|
||||||
|
|
||||||
|
// IncludeCRDs returns the include CRDs.
|
||||||
|
func (a *ApplyImpl) IncludeCRDs() bool {
|
||||||
|
return a.ApplyOptions.IncludeCRDsFlag.Value()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShouldIncludeCRDs returns true if CRDs should be included.
|
||||||
|
func (a *ApplyImpl) ShouldIncludeCRDs() bool {
|
||||||
|
includeCRDsExplicit := a.IncludeCRDsFlag.WasExplicitlySet() && a.IncludeCRDsFlag.Value()
|
||||||
|
skipCRDsExplicit := a.SkipCRDsFlag.WasExplicitlySet() && !a.SkipCRDsFlag.Value()
|
||||||
|
|
||||||
|
return includeCRDsExplicit || skipCRDsExplicit
|
||||||
}
|
}
|
||||||
|
|
||||||
// SkipCleanup returns the skip cleanup.
|
// SkipCleanup returns the skip cleanup.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
package config
|
package config
|
||||||
|
|
||||||
|
import "github.com/helmfile/helmfile/pkg/common"
|
||||||
|
|
||||||
// DiffOptions is the options for the build command
|
// DiffOptions is the options for the build command
|
||||||
type DiffOptions struct {
|
type DiffOptions struct {
|
||||||
// Set is the set flag
|
// Set is the set flag
|
||||||
|
|
@ -12,6 +14,10 @@ type DiffOptions struct {
|
||||||
StripTrailingCR bool
|
StripTrailingCR bool
|
||||||
// IncludeTests is the include tests flag
|
// IncludeTests is the include tests flag
|
||||||
IncludeTests bool
|
IncludeTests bool
|
||||||
|
// SkipCRDsFlag is the skip crds flag
|
||||||
|
SkipCRDsFlag common.BoolFlag
|
||||||
|
// IncludeCRDsFlag is the include crds flag
|
||||||
|
IncludeCRDsFlag common.BoolFlag
|
||||||
// SkipNeeds is the include crds flag
|
// SkipNeeds is the include crds flag
|
||||||
SkipNeeds bool
|
SkipNeeds bool
|
||||||
// IncludeNeeds is the include needs flag
|
// IncludeNeeds is the include needs flag
|
||||||
|
|
@ -53,7 +59,12 @@ type DiffOptions struct {
|
||||||
|
|
||||||
// NewDiffOptions creates a new Apply
|
// NewDiffOptions creates a new Apply
|
||||||
func NewDiffOptions() *DiffOptions {
|
func NewDiffOptions() *DiffOptions {
|
||||||
return &DiffOptions{}
|
newOptions := &DiffOptions{
|
||||||
|
IncludeCRDsFlag: common.NewBoolFlag(false),
|
||||||
|
SkipCRDsFlag: common.NewBoolFlag(false),
|
||||||
|
}
|
||||||
|
|
||||||
|
return newOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
// DiffImpl is impl for applyOptions
|
// DiffImpl is impl for applyOptions
|
||||||
|
|
@ -144,9 +155,22 @@ func (t *DiffImpl) NoHooks() bool {
|
||||||
return t.DiffOptions.NoHooks
|
return t.DiffOptions.NoHooks
|
||||||
}
|
}
|
||||||
|
|
||||||
// ShowCRDs returns the show crds
|
// SkipCRDs returns the skip crds
|
||||||
func (t *DiffImpl) SkipCRDs() bool {
|
func (t *DiffImpl) SkipCRDs() bool {
|
||||||
return false
|
return t.DiffOptions.SkipCRDsFlag.Value()
|
||||||
|
}
|
||||||
|
|
||||||
|
// IncludeCRDs returns the include crds
|
||||||
|
func (t *DiffImpl) IncludeCRDs() bool {
|
||||||
|
return t.DiffOptions.IncludeCRDsFlag.Value()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShouldIncludeCRDs returns true if CRDs should be included
|
||||||
|
func (t *DiffImpl) ShouldIncludeCRDs() bool {
|
||||||
|
includeCRDsExplicit := t.IncludeCRDsFlag.WasExplicitlySet() && t.IncludeCRDsFlag.Value()
|
||||||
|
skipCRDsExplicit := t.SkipCRDsFlag.WasExplicitlySet() && !t.SkipCRDsFlag.Value()
|
||||||
|
|
||||||
|
return includeCRDsExplicit || skipCRDsExplicit
|
||||||
}
|
}
|
||||||
|
|
||||||
// SkipDiffOnInstall returns the skip diff on install
|
// SkipDiffOnInstall returns the skip diff on install
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
func (o *ApplyOptions) HandleFlag(name string, value interface{}, changed bool) {
|
||||||
|
if !changed {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch name {
|
||||||
|
case "include-crds":
|
||||||
|
if boolVal, ok := value.(*bool); ok {
|
||||||
|
o.IncludeCRDsFlag.Set(*boolVal)
|
||||||
|
}
|
||||||
|
case "skip-crds":
|
||||||
|
if boolVal, ok := value.(*bool); ok {
|
||||||
|
o.SkipCRDsFlag.Set(*boolVal)
|
||||||
|
}
|
||||||
|
// Handle other flags...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *DiffOptions) HandleFlag(name string, value interface{}, changed bool) {
|
||||||
|
if !changed {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch name {
|
||||||
|
case "include-crds":
|
||||||
|
if boolVal, ok := value.(*bool); ok {
|
||||||
|
o.IncludeCRDsFlag.Set(*boolVal)
|
||||||
|
}
|
||||||
|
// Handle other flags...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *SyncOptions) HandleFlag(name string, value interface{}, changed bool) {
|
||||||
|
if !changed {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch name {
|
||||||
|
case "include-crds":
|
||||||
|
if boolVal, ok := value.(*bool); ok {
|
||||||
|
o.IncludeCRDsFlag.Set(*boolVal)
|
||||||
|
}
|
||||||
|
case "skip-crds":
|
||||||
|
if boolVal, ok := value.(*bool); ok {
|
||||||
|
o.SkipCRDsFlag.Set(*boolVal)
|
||||||
|
}
|
||||||
|
// Handle other flags...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *TemplateOptions) HandleFlag(name string, value interface{}, changed bool) {
|
||||||
|
if !changed {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch name {
|
||||||
|
case "include-crds":
|
||||||
|
if boolVal, ok := value.(*bool); ok {
|
||||||
|
o.IncludeCRDsFlag.Set(*boolVal)
|
||||||
|
}
|
||||||
|
// Handle other flags...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
package config
|
package config
|
||||||
|
|
||||||
|
import "github.com/helmfile/helmfile/pkg/common"
|
||||||
|
|
||||||
// SyncOptions is the options for the build command
|
// SyncOptions is the options for the build command
|
||||||
type SyncOptions struct {
|
type SyncOptions struct {
|
||||||
// Set is the set flag
|
// Set is the set flag
|
||||||
|
|
@ -16,8 +18,10 @@ type SyncOptions struct {
|
||||||
IncludeNeeds bool
|
IncludeNeeds bool
|
||||||
// IncludeTransitiveNeeds is the include transitive needs flag
|
// IncludeTransitiveNeeds is the include transitive needs flag
|
||||||
IncludeTransitiveNeeds bool
|
IncludeTransitiveNeeds bool
|
||||||
// SkipCrds is the skip crds flag
|
// SkipCRDsFlag is the skip crds flag
|
||||||
SkipCRDs bool
|
SkipCRDsFlag common.BoolFlag
|
||||||
|
// IncludeCRDsFlag is the include crds flag
|
||||||
|
IncludeCRDsFlag common.BoolFlag
|
||||||
// Wait is the wait flag
|
// Wait is the wait flag
|
||||||
Wait bool
|
Wait bool
|
||||||
// WaitRetries is the wait retries flag
|
// WaitRetries is the wait retries flag
|
||||||
|
|
@ -48,7 +52,12 @@ type SyncOptions struct {
|
||||||
|
|
||||||
// NewSyncOptions creates a new Apply
|
// NewSyncOptions creates a new Apply
|
||||||
func NewSyncOptions() *SyncOptions {
|
func NewSyncOptions() *SyncOptions {
|
||||||
return &SyncOptions{}
|
newOptions := &SyncOptions{
|
||||||
|
IncludeCRDsFlag: common.NewBoolFlag(false),
|
||||||
|
SkipCRDsFlag: common.NewBoolFlag(false),
|
||||||
|
}
|
||||||
|
|
||||||
|
return newOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
// SyncImpl is impl for applyOptions
|
// SyncImpl is impl for applyOptions
|
||||||
|
|
@ -104,9 +113,22 @@ func (t *SyncImpl) Values() []string {
|
||||||
return t.SyncOptions.Values
|
return t.SyncOptions.Values
|
||||||
}
|
}
|
||||||
|
|
||||||
// SkipCRDS returns the skip crds
|
// SkipCRDs returns the skip crds
|
||||||
func (t *SyncImpl) SkipCRDs() bool {
|
func (t *SyncImpl) SkipCRDs() bool {
|
||||||
return t.SyncOptions.SkipCRDs
|
return t.SyncOptions.SkipCRDsFlag.Value()
|
||||||
|
}
|
||||||
|
|
||||||
|
// IncludeCRDs returns the include crds
|
||||||
|
func (t *SyncImpl) IncludeCRDs() bool {
|
||||||
|
return t.SyncOptions.IncludeCRDsFlag.Value()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShouldIncludeCRDs returns true if CRDs should be included
|
||||||
|
func (t *SyncImpl) ShouldIncludeCRDs() bool {
|
||||||
|
includeCRDsExplicit := t.IncludeCRDsFlag.WasExplicitlySet() && t.IncludeCRDsFlag.Value()
|
||||||
|
skipCRDsExplicit := t.SkipCRDsFlag.WasExplicitlySet() && !t.SkipCRDsFlag.Value()
|
||||||
|
|
||||||
|
return includeCRDsExplicit || skipCRDsExplicit
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait returns the wait
|
// Wait returns the wait
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/helmfile/helmfile/pkg/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TemplateOptions is the options for the build command
|
// TemplateOptions is the options for the build command
|
||||||
|
|
@ -20,8 +22,11 @@ type TemplateOptions struct {
|
||||||
Concurrency int
|
Concurrency int
|
||||||
// Validate is the validate flag
|
// Validate is the validate flag
|
||||||
Validate bool
|
Validate bool
|
||||||
// IncludeCRDs is the include crds flag
|
// SkipCRDsFlag is the skip crds flag
|
||||||
IncludeCRDs bool
|
// Deprecated: Use IncludeCRDsFlag instead
|
||||||
|
SkipCRDsFlag common.BoolFlag
|
||||||
|
// IncludeCRDsFlag is the include crds flag
|
||||||
|
IncludeCRDsFlag common.BoolFlag
|
||||||
// SkipTests is the skip tests flag
|
// SkipTests is the skip tests flag
|
||||||
SkipTests bool
|
SkipTests bool
|
||||||
// SkipNeeds is the skip needs flag
|
// SkipNeeds is the skip needs flag
|
||||||
|
|
@ -48,7 +53,11 @@ type TemplateOptions struct {
|
||||||
|
|
||||||
// NewTemplateOptions creates a new Apply
|
// NewTemplateOptions creates a new Apply
|
||||||
func NewTemplateOptions() *TemplateOptions {
|
func NewTemplateOptions() *TemplateOptions {
|
||||||
return &TemplateOptions{}
|
newOptions := &TemplateOptions{
|
||||||
|
SkipCRDsFlag: common.NewBoolFlag(false),
|
||||||
|
IncludeCRDsFlag: common.NewBoolFlag(false),
|
||||||
|
}
|
||||||
|
return newOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
// TemplateImpl is impl for applyOptions
|
// TemplateImpl is impl for applyOptions
|
||||||
|
|
@ -70,9 +79,22 @@ func (t *TemplateImpl) Concurrency() int {
|
||||||
return t.TemplateOptions.Concurrency
|
return t.TemplateOptions.Concurrency
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SkipCRDs returns the skip crds
|
||||||
|
func (t *TemplateImpl) SkipCRDs() bool {
|
||||||
|
return t.TemplateOptions.SkipCRDsFlag.Value()
|
||||||
|
}
|
||||||
|
|
||||||
// IncludeCRDs returns the include crds
|
// IncludeCRDs returns the include crds
|
||||||
func (t *TemplateImpl) IncludeCRDs() bool {
|
func (t *TemplateImpl) IncludeCRDs() bool {
|
||||||
return t.TemplateOptions.IncludeCRDs
|
return t.TemplateOptions.IncludeCRDsFlag.Value()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShouldIncludeCRDs returns whether to include crds
|
||||||
|
func (t *TemplateImpl) ShouldIncludeCRDs() bool {
|
||||||
|
includeCRDsExplicit := t.IncludeCRDsFlag.WasExplicitlySet() && t.IncludeCRDsFlag.Value()
|
||||||
|
skipCRDsExplicit := t.SkipCRDsFlag.WasExplicitlySet() && !t.SkipCRDsFlag.Value()
|
||||||
|
|
||||||
|
return includeCRDsExplicit || skipCRDsExplicit
|
||||||
}
|
}
|
||||||
|
|
||||||
// NoHooks returns the no hooks
|
// NoHooks returns the no hooks
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
package flags
|
||||||
|
|
||||||
|
import "github.com/spf13/cobra"
|
||||||
|
|
||||||
|
// ApplyFlagRegistrar handles flags specific to the apply command
|
||||||
|
type ApplyFlagRegistrar struct {
|
||||||
|
*GenericFlagRegistrar
|
||||||
|
IncludeCRDs bool
|
||||||
|
SkipCRDs bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewApplyFlagRegistrar creates a new ApplyFlagRegistrar
|
||||||
|
func NewApplyFlagRegistrar() *ApplyFlagRegistrar {
|
||||||
|
return &ApplyFlagRegistrar{
|
||||||
|
GenericFlagRegistrar: NewGenericFlagRegistrar(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterFlags registers apply-specific flags
|
||||||
|
func (r *ApplyFlagRegistrar) RegisterFlags(cmd *cobra.Command) {
|
||||||
|
r.RegisterBoolFlag(cmd, "include-crds", &r.IncludeCRDs, false, "include CRDs in the diffing")
|
||||||
|
r.RegisterBoolFlag(cmd, "skip-crds", &r.SkipCRDs, false, "if set, no CRDs will be installed on sync. By default, CRDs are installed if not already present")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
package flags
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FlagRegistrar defines an interface for registering and transferring flags
|
||||||
|
type FlagRegistrar interface {
|
||||||
|
RegisterFlags(cmd *cobra.Command)
|
||||||
|
TransferFlags(cmd *cobra.Command, opts interface{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// FlagHandler is a generic interface for handling flag values
|
||||||
|
type FlagHandler interface {
|
||||||
|
// HandleFlag receives a flag name, value, and whether it was changed
|
||||||
|
HandleFlag(name string, value interface{}, changed bool)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenericFlagRegistrar is a base struct for flag registrars
|
||||||
|
type GenericFlagRegistrar struct {
|
||||||
|
// Map of flag names to their values
|
||||||
|
values map[string]interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewGenericFlagRegistrar creates a new GenericFlagRegistrar
|
||||||
|
func NewGenericFlagRegistrar() *GenericFlagRegistrar {
|
||||||
|
return &GenericFlagRegistrar{
|
||||||
|
values: make(map[string]interface{}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TransferFlags transfers all registered flags to the options
|
||||||
|
func (r *GenericFlagRegistrar) TransferFlags(cmd *cobra.Command, opts interface{}) {
|
||||||
|
if handler, ok := opts.(FlagHandler); ok {
|
||||||
|
flags := cmd.Flags()
|
||||||
|
|
||||||
|
// Transfer each registered flag
|
||||||
|
for name, value := range r.values {
|
||||||
|
changed := flags.Changed(name)
|
||||||
|
handler.HandleFlag(name, value, changed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterBoolFlag registers a boolean flag and stores its reference
|
||||||
|
func (r *GenericFlagRegistrar) RegisterBoolFlag(cmd *cobra.Command, name string, value *bool, defaultValue bool, usage string) {
|
||||||
|
cmd.Flags().BoolVar(value, name, defaultValue, usage)
|
||||||
|
r.values[name] = value
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,140 @@
|
||||||
|
package flags
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MockFlagHandler implements FlagHandler for testing
|
||||||
|
type MockFlagHandler struct {
|
||||||
|
handledFlags map[string]interface{}
|
||||||
|
changedFlags map[string]bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMockFlagHandler() *MockFlagHandler {
|
||||||
|
return &MockFlagHandler{
|
||||||
|
handledFlags: make(map[string]interface{}),
|
||||||
|
changedFlags: make(map[string]bool),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *MockFlagHandler) HandleFlag(name string, value interface{}, changed bool) {
|
||||||
|
h.handledFlags[name] = value
|
||||||
|
h.changedFlags[name] = changed
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewGenericFlagRegistrar(t *testing.T) {
|
||||||
|
registrar := NewGenericFlagRegistrar()
|
||||||
|
assert.NotNil(t, registrar)
|
||||||
|
assert.NotNil(t, registrar.values)
|
||||||
|
assert.Len(t, registrar.values, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGenericFlagRegistrar_RegisterBoolFlag(t *testing.T) {
|
||||||
|
registrar := NewGenericFlagRegistrar()
|
||||||
|
cmd := &cobra.Command{Use: "test"}
|
||||||
|
|
||||||
|
var testFlag bool
|
||||||
|
registrar.RegisterBoolFlag(cmd, "test-flag", &testFlag, false, "Test flag")
|
||||||
|
|
||||||
|
// Verify the flag was registered
|
||||||
|
flag := cmd.Flags().Lookup("test-flag")
|
||||||
|
assert.NotNil(t, flag)
|
||||||
|
assert.Equal(t, "test-flag", flag.Name)
|
||||||
|
assert.Equal(t, "false", flag.DefValue)
|
||||||
|
assert.Equal(t, "Test flag", flag.Usage)
|
||||||
|
|
||||||
|
// Verify the value was stored in the registrar
|
||||||
|
value, exists := registrar.values["test-flag"]
|
||||||
|
assert.True(t, exists)
|
||||||
|
assert.Equal(t, &testFlag, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGenericFlagRegistrar_TransferFlags_NoChanges(t *testing.T) {
|
||||||
|
registrar := NewGenericFlagRegistrar()
|
||||||
|
cmd := &cobra.Command{Use: "test"}
|
||||||
|
|
||||||
|
var testFlag bool
|
||||||
|
registrar.RegisterBoolFlag(cmd, "test-flag", &testFlag, false, "Test flag")
|
||||||
|
|
||||||
|
// Create a mock handler
|
||||||
|
handler := NewMockFlagHandler()
|
||||||
|
|
||||||
|
// Transfer flags (none changed)
|
||||||
|
registrar.TransferFlags(cmd, handler)
|
||||||
|
|
||||||
|
// Verify the handler was called with the right parameters
|
||||||
|
assert.Equal(t, &testFlag, handler.handledFlags["test-flag"])
|
||||||
|
assert.False(t, handler.changedFlags["test-flag"])
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGenericFlagRegistrar_TransferFlags_WithChanges(t *testing.T) {
|
||||||
|
registrar := NewGenericFlagRegistrar()
|
||||||
|
cmd := &cobra.Command{Use: "test"}
|
||||||
|
|
||||||
|
var testFlag bool
|
||||||
|
registrar.RegisterBoolFlag(cmd, "test-flag", &testFlag, false, "Test flag")
|
||||||
|
|
||||||
|
// Simulate flag being set on command line
|
||||||
|
err := cmd.Flags().Set("test-flag", "true")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
testFlag = true // Value would be updated by cobra
|
||||||
|
|
||||||
|
// Create a mock handler
|
||||||
|
handler := NewMockFlagHandler()
|
||||||
|
|
||||||
|
// Transfer flags (with changes)
|
||||||
|
registrar.TransferFlags(cmd, handler)
|
||||||
|
|
||||||
|
// Verify the handler was called with the right parameters
|
||||||
|
assert.Equal(t, &testFlag, handler.handledFlags["test-flag"])
|
||||||
|
assert.True(t, handler.changedFlags["test-flag"])
|
||||||
|
assert.True(t, *handler.handledFlags["test-flag"].(*bool))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGenericFlagRegistrar_TransferFlags_NonHandler(t *testing.T) {
|
||||||
|
registrar := NewGenericFlagRegistrar()
|
||||||
|
cmd := &cobra.Command{Use: "test"}
|
||||||
|
|
||||||
|
var testFlag bool
|
||||||
|
registrar.RegisterBoolFlag(cmd, "test-flag", &testFlag, false, "Test flag")
|
||||||
|
|
||||||
|
// Use a non-handler type
|
||||||
|
nonHandler := struct{}{}
|
||||||
|
|
||||||
|
// This should not panic
|
||||||
|
registrar.TransferFlags(cmd, nonHandler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGenericFlagRegistrar_MultipleFlags(t *testing.T) {
|
||||||
|
registrar := NewGenericFlagRegistrar()
|
||||||
|
cmd := &cobra.Command{Use: "test"}
|
||||||
|
|
||||||
|
var boolFlag bool
|
||||||
|
var boolFlag2 bool
|
||||||
|
|
||||||
|
registrar.RegisterBoolFlag(cmd, "bool-flag", &boolFlag, false, "Boolean flag")
|
||||||
|
registrar.RegisterBoolFlag(cmd, "bool-flag2", &boolFlag2, true, "Another boolean flag")
|
||||||
|
|
||||||
|
// Set one flag
|
||||||
|
err := cmd.Flags().Set("bool-flag", "true")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
boolFlag = true // Value would be updated by cobra
|
||||||
|
|
||||||
|
// Create a mock handler
|
||||||
|
handler := NewMockFlagHandler()
|
||||||
|
|
||||||
|
// Transfer flags
|
||||||
|
registrar.TransferFlags(cmd, handler)
|
||||||
|
|
||||||
|
// Verify both flags were handled correctly
|
||||||
|
assert.Equal(t, &boolFlag, handler.handledFlags["bool-flag"])
|
||||||
|
assert.True(t, handler.changedFlags["bool-flag"])
|
||||||
|
assert.True(t, *handler.handledFlags["bool-flag"].(*bool))
|
||||||
|
|
||||||
|
assert.Equal(t, &boolFlag2, handler.handledFlags["bool-flag2"])
|
||||||
|
assert.False(t, handler.changedFlags["bool-flag2"])
|
||||||
|
assert.True(t, *handler.handledFlags["bool-flag2"].(*bool)) // Default is true
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
package flags
|
||||||
|
|
||||||
|
import "github.com/spf13/cobra"
|
||||||
|
|
||||||
|
// DiffFlagRegistrar handles flags specific to the diff command
|
||||||
|
type DiffFlagRegistrar struct {
|
||||||
|
*GenericFlagRegistrar
|
||||||
|
IncludeCRDs bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDiffFlagRegistrar creates a new DiffFlagRegistrar
|
||||||
|
func NewDiffFlagRegistrar() *DiffFlagRegistrar {
|
||||||
|
return &DiffFlagRegistrar{
|
||||||
|
GenericFlagRegistrar: NewGenericFlagRegistrar(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterFlags registers diff-specific flags
|
||||||
|
func (r *DiffFlagRegistrar) RegisterFlags(cmd *cobra.Command) {
|
||||||
|
r.RegisterBoolFlag(cmd, "include-crds", &r.IncludeCRDs, false, "include CRDs in the diffing")
|
||||||
|
// Diff doesn't have skip-crds
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
package flags
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/helmfile/helmfile/pkg/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
// BoolFlagInitializer ensures a BoolFlag is initialized with a default value if nil
|
||||||
|
func EnsureBoolFlag(flag *common.BoolFlag, defaultValue bool) {
|
||||||
|
if *flag == nil {
|
||||||
|
*flag = common.NewBoolFlag(defaultValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringFlagInitializer ensures a StringFlag is initialized with a default value if nil
|
||||||
|
func EnsureStringFlag(flag *common.StringFlag, defaultValue string) {
|
||||||
|
if *flag == nil {
|
||||||
|
*flag = common.NewStringFlag(defaultValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringArrayFlagInitializer ensures a StringArrayFlag is initialized with default values if nil
|
||||||
|
func EnsureStringArrayFlag(flag *common.StringArrayFlag, defaultValues []string) {
|
||||||
|
if *flag == nil {
|
||||||
|
*flag = common.NewStringArrayFlag(defaultValues)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// InitializeOptions initializes all nil flag fields in an options struct
|
||||||
|
func InitializeOptions(options interface{}) {
|
||||||
|
// This could be expanded to use reflection to automatically find and initialize
|
||||||
|
// all flag fields in any options struct
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
package flags
|
||||||
|
|
||||||
|
import "github.com/spf13/cobra"
|
||||||
|
|
||||||
|
// SyncFlagRegistrar handles flags specific to the sync command
|
||||||
|
type SyncFlagRegistrar struct {
|
||||||
|
*GenericFlagRegistrar
|
||||||
|
IncludeCRDs bool
|
||||||
|
SkipCRDs bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSyncFlagRegistrar creates a new SyncFlagRegistrar
|
||||||
|
func NewSyncFlagRegistrar() *SyncFlagRegistrar {
|
||||||
|
return &SyncFlagRegistrar{
|
||||||
|
GenericFlagRegistrar: NewGenericFlagRegistrar(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterFlags registers sync-specific flags
|
||||||
|
func (r *SyncFlagRegistrar) RegisterFlags(cmd *cobra.Command) {
|
||||||
|
r.RegisterBoolFlag(cmd, "include-crds", &r.IncludeCRDs, false, "include CRDs in the diffing")
|
||||||
|
r.RegisterBoolFlag(cmd, "skip-crds", &r.SkipCRDs, false, "if set, no CRDs will be installed on sync. By default, CRDs are installed if not already present")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
package flags
|
||||||
|
|
||||||
|
import "github.com/spf13/cobra"
|
||||||
|
|
||||||
|
// TemplateFlagRegistrar handles flags specific to the template command
|
||||||
|
type TemplateFlagRegistrar struct {
|
||||||
|
*GenericFlagRegistrar
|
||||||
|
IncludeCRDs bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewTemplateFlagRegistrar creates a new TemplateFlagRegistrar
|
||||||
|
func NewTemplateFlagRegistrar() *TemplateFlagRegistrar {
|
||||||
|
return &TemplateFlagRegistrar{
|
||||||
|
GenericFlagRegistrar: NewGenericFlagRegistrar(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterFlags registers template-specific flags
|
||||||
|
func (r *TemplateFlagRegistrar) RegisterFlags(cmd *cobra.Command) {
|
||||||
|
r.RegisterBoolFlag(cmd, "include-crds", &r.IncludeCRDs, false, "include CRDs in the diffing")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1136,7 +1136,7 @@ type ChartPrepareOptions struct {
|
||||||
// Validate is a helm-3-only option. When it is set to true, it configures chartify to pass --validate to helm-template run by it.
|
// Validate is a helm-3-only option. When it is set to true, it configures chartify to pass --validate to helm-template run by it.
|
||||||
// It's required when one of your chart relies on Capabilities.APIVersions in a template
|
// It's required when one of your chart relies on Capabilities.APIVersions in a template
|
||||||
Validate bool
|
Validate bool
|
||||||
IncludeCRDs *bool
|
IncludeCRDs bool
|
||||||
Wait bool
|
Wait bool
|
||||||
WaitRetries int
|
WaitRetries int
|
||||||
WaitForJobs bool
|
WaitForJobs bool
|
||||||
|
|
@ -1298,33 +1298,7 @@ func (st *HelmState) PrepareCharts(helm helmexec.Interface, dir string, concurre
|
||||||
)
|
)
|
||||||
|
|
||||||
chartifyOpts := chartification.Opts
|
chartifyOpts := chartification.Opts
|
||||||
|
st.mergeChartifyOpts(chartifyOpts, opts, skipDeps, release)
|
||||||
if skipDeps {
|
|
||||||
chartifyOpts.SkipDeps = true
|
|
||||||
}
|
|
||||||
|
|
||||||
includeCRDs := true
|
|
||||||
if opts.IncludeCRDs != nil {
|
|
||||||
includeCRDs = *opts.IncludeCRDs
|
|
||||||
}
|
|
||||||
chartifyOpts.IncludeCRDs = includeCRDs
|
|
||||||
|
|
||||||
chartifyOpts.Validate = opts.Validate
|
|
||||||
|
|
||||||
chartifyOpts.KubeVersion = st.getKubeVersion(release, opts.KubeVersion)
|
|
||||||
chartifyOpts.ApiVersions = st.getApiVersions(release)
|
|
||||||
|
|
||||||
if opts.Values != nil {
|
|
||||||
chartifyOpts.ValuesFiles = append(opts.Values, chartifyOpts.ValuesFiles...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://github.com/helmfile/helmfile/pull/867
|
|
||||||
// https://github.com/helmfile/helmfile/issues/895
|
|
||||||
var flags []string
|
|
||||||
for _, s := range opts.Set {
|
|
||||||
flags = append(flags, "--set", s)
|
|
||||||
}
|
|
||||||
chartifyOpts.SetFlags = append(chartifyOpts.SetFlags, flags...)
|
|
||||||
|
|
||||||
out, err := c.Chartify(release.Name, chartPath, chartify.WithChartifyOpts(chartifyOpts))
|
out, err := c.Chartify(release.Name, chartPath, chartify.WithChartifyOpts(chartifyOpts))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -1454,6 +1428,33 @@ func (st *HelmState) PrepareCharts(helm helmexec.Interface, dir string, concurre
|
||||||
return prepareChartInfo, nil
|
return prepareChartInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mergeChartifyOpts merges the source opts into the destination opts, modifying dest directly
|
||||||
|
func (st *HelmState) mergeChartifyOpts(dest *chartify.ChartifyOpts, source ChartPrepareOptions, skipDeps bool, release *ReleaseSpec) {
|
||||||
|
// @TODO why is this not just `chartifyOpts.SkipDeps = skipDeps`??
|
||||||
|
if skipDeps {
|
||||||
|
dest.SkipDeps = true
|
||||||
|
}
|
||||||
|
|
||||||
|
dest.IncludeCRDs = source.IncludeCRDs
|
||||||
|
|
||||||
|
dest.Validate = source.Validate
|
||||||
|
|
||||||
|
dest.KubeVersion = st.getKubeVersion(release, source.KubeVersion)
|
||||||
|
dest.ApiVersions = st.getApiVersions(release)
|
||||||
|
|
||||||
|
if source.Values != nil {
|
||||||
|
dest.ValuesFiles = append(source.Values, dest.ValuesFiles...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://github.com/helmfile/helmfile/pull/867
|
||||||
|
// https://github.com/helmfile/helmfile/issues/895
|
||||||
|
var flags []string
|
||||||
|
for _, s := range source.Set {
|
||||||
|
flags = append(flags, "--set", s)
|
||||||
|
}
|
||||||
|
dest.SetFlags = append(dest.SetFlags, flags...)
|
||||||
|
}
|
||||||
|
|
||||||
// nolint: unparam
|
// nolint: unparam
|
||||||
func (st *HelmState) runHelmDepBuilds(helm helmexec.Interface, concurrency int, builds []*chartPrepareResult) error {
|
func (st *HelmState) runHelmDepBuilds(helm helmexec.Interface, concurrency int, builds []*chartPrepareResult) error {
|
||||||
// NOTES:
|
// NOTES:
|
||||||
|
|
@ -1852,6 +1853,12 @@ func (st *HelmState) commonDiffFlags(detailedExitCode bool, stripTrailingCR bool
|
||||||
flags = append(flags, "--set", s)
|
flags = append(flags, "--set", s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// internally we only care about include-crds since skip-crds is misleading and used only in command interface
|
||||||
|
if opt.IncludeCRDs {
|
||||||
|
flags = append(flags, "--include-crds")
|
||||||
|
}
|
||||||
|
|
||||||
flags = st.appendExtraDiffFlags(flags, opt)
|
flags = st.appendExtraDiffFlags(flags, opt)
|
||||||
|
|
||||||
return flags
|
return flags
|
||||||
|
|
@ -2029,6 +2036,7 @@ type DiffOpts struct {
|
||||||
// If this is true, Color has no effect.
|
// If this is true, Color has no effect.
|
||||||
NoColor bool
|
NoColor bool
|
||||||
Set []string
|
Set []string
|
||||||
|
IncludeCRDs bool
|
||||||
SkipCleanup bool
|
SkipCleanup bool
|
||||||
SkipDiffOnInstall bool
|
SkipDiffOnInstall bool
|
||||||
DiffArgs string
|
DiffArgs string
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue