pkg/config: Split impl from options and integrate flag handler including tests

Signed-off-by: yxxhero <aiopsclub@163.com>
This commit is contained in:
Hubertbits 2025-04-16 15:44:19 +02:00 committed by yxxhero
parent 6b587e15f0
commit 912971c923
44 changed files with 1601 additions and 1238 deletions

118
pkg/config/README.md Normal file
View File

@ -0,0 +1,118 @@
# Config Package
## Overview
The `pkg/config` package contains configuration options for various Helmfile commands. These options control the behavior of commands like `apply`, `diff`, `template`, `sync`, and others.
## File Structure
```
pkg/config/
├── options.go # Base options interfaces and common functionality
├── options_test.go # Tests for base options
├── global.go # Global options shared across all commands
├── global_impl.go # Implementation of global options
├── apply.go # ApplyOptions implementation for 'apply' command
├── apply_impl.go # Implementation of ApplyOptions
├── apply_test.go # Tests for ApplyOptions
├── build.go # BuildOptions implementation for 'build' command
├── build_impl.go # Implementation of BuildOptions
├── cache.go # CacheOptions implementation for 'cache' command
├── cache_impl.go # Implementation of CacheOptions
├── deps.go # DepsOptions implementation for 'deps' command
├── deps_impl.go # Implementation of DepsOptions
├── destroy.go # DestroyOptions implementation for 'destroy' command
├── destroy_impl.go # Implementation of DestroyOptions
├── destroy_test.go # Tests for DestroyOptions
├── diff.go # DiffOptions implementation for 'diff' command
├── diff_impl.go # Implementation of DiffOptions
├── diff_test.go # Tests for DiffOptions
├── fetch.go # FetchOptions implementation for 'fetch' command
├── fetch_impl.go # Implementation of FetchOptions
├── fetch_test.go # Tests for FetchOptions
├── init.go # InitOptions implementation for 'init' command
├── init_impl.go # Implementation of InitOptions
├── lint.go # LintOptions implementation for 'lint' command
├── linit_impl.go # Implementation of LintOptions
├── lint_test.go # Tests for LintOptions
├── list.go # ListOptions implementation for 'list' command
├── list_impl.go # Implementation of ListOptions
├── list_test.go # Tests for ListOptions
├── repos.go # ReposOptions implementation for 'repos' command
├── repos_impl.go # Implementation of ReposOptions
├── show-dag.go # ShowDAGOptions implementation for 'show-dag' command
├── show-dag_impl.go # Implementation of ShowDAGOptions
├── status.go # StatusOptions implementation for 'status' command
├── status_impl.go # Implementation of StatusOptions
├── status_test.go # Tests for StatusOptions
├── sync.go # SyncOptions implementation for 'sync' command
├── sync_impl.go # Implementation of SyncOptions
├── sync_test.go # Tests for SyncOptions
├── template.go # TemplateOptions implementation for 'template' command
├── template_impl.go # Implementation of TemplateOptions
├── template_test.go # Tests for TemplateOptions
├── test.go # TestOptions implementation for 'test' command
├── test_impl.go # Implementation of TestOptions
├── write-values.go # WriteValuesOptions implementation for 'write-values' command
├── write-values_impl.go # Implementation of WriteValuesOptions
└── common/ # Common option types shared across commands
├── bool_flag.go # Boolean flag implementation
├── string_flag.go # String flag implementation
└── array_flag.go # String array flag implementation
```
## Components
- **Options Interfaces**: Base interfaces that define common option behaviors
- **Global Options**: Configuration options shared across all commands
- **Command-specific Options**: Implementations for each command (e.g., `ApplyOptions`, `DiffOptions`)
- **Implementation Classes**: Classes that combine global options with command-specific options
- **Flag Handling**: Each options struct implements the `FlagHandler` interface from the `pkg/flags` package
- **Common Flag Types**: Reusable flag implementations in the `common` subpackage
## Key Features
- **Command Configuration**: Each command has its own options type that controls its behavior
- **Flag Handling**: Options implement the `FlagHandler` interface to receive flag values
- **Default Values**: Options provide sensible defaults that can be overridden
- **Validation**: Some options include validation logic to ensure valid configurations
- **Implementation Pattern**: Each command has both an options struct and an implementation struct that combines global and command-specific options
## Usage
Options objects are typically created by factory methods and populated with values from command-line flags. They are then passed to command implementations to control their behavior.
### Example:
```go
// Create options
opts := config.NewApplyOptions()
// Handle flags
handled := opts.HandleFlag("include-crds", &includeCRDs, true)
if !handled {
// Flag wasn't recognized
}
// Create implementation with global options
globalOpts := config.NewGlobalImpl(&config.GlobalOptions{})
impl := config.NewApplyImpl(globalOpts, opts)
// Use in command
cmd.Execute(impl)
```
## Testing
All option implementations should have comprehensive tests in this package. Tests should verify:
1. Default values are set correctly
2. Flags are handled properly
3. The boolean return value from `HandleFlag` correctly indicates whether a flag was recognized
4. Option validation works as expected
## Related Packages
- `pkg/flags`: Provides flag registration and handling functionality
- `pkg/factory`: Creates properly configured options for commands
- `pkg/app`: Uses options to control command execution

View File

@ -1,6 +1,9 @@
package config
import "github.com/helmfile/helmfile/pkg/common"
import (
"github.com/helmfile/helmfile/pkg/common"
"github.com/helmfile/helmfile/pkg/flags"
)
// ApplyOptoons is the options for the apply command
type ApplyOptions struct {
@ -81,216 +84,34 @@ type ApplyOptions struct {
// NewApply creates a new Apply
func NewApplyOptions() *ApplyOptions {
newOptions := &ApplyOptions{
IncludeCRDsFlag: common.NewBoolFlag(false),
SkipCRDsFlag: common.NewBoolFlag(false),
}
newOptions := &ApplyOptions{}
newOptions.Initialize()
return newOptions
}
// ApplyImpl is impl for applyOptions
type ApplyImpl struct {
*GlobalImpl
*ApplyOptions
func (o *ApplyOptions) Initialize() {
flags.EnsureBoolFlag(&o.IncludeCRDsFlag, false)
flags.EnsureBoolFlag(&o.SkipCRDsFlag, false)
}
// NewApplyImpl creates a new ApplyImpl
func NewApplyImpl(g *GlobalImpl, a *ApplyOptions) *ApplyImpl {
return &ApplyImpl{
GlobalImpl: g,
ApplyOptions: a,
func (o *ApplyOptions) HandleFlag(name string, value interface{}, changed bool) bool {
switch name {
case "include-crds":
if changed {
if boolVal, ok := value.(*bool); ok {
o.IncludeCRDsFlag.Set(*boolVal)
}
}
return true
case "skip-crds":
if changed {
if boolVal, ok := value.(*bool); ok {
o.SkipCRDsFlag.Set(*boolVal)
}
}
return true
}
}
// Set returns the set.
func (a *ApplyImpl) Set() []string {
return a.ApplyOptions.Set
}
// Concurrency returns the concurrency.
func (a *ApplyImpl) Concurrency() int {
return a.ApplyOptions.Concurrency
}
// Context returns the context.
func (a *ApplyImpl) Context() int {
return a.ApplyOptions.Context
}
// DetailedExitcode returns the detailed exitcode.
func (a *ApplyImpl) DetailedExitcode() bool {
return a.ApplyOptions.DetailedExitcode
}
// StripTrailingCR is true if trailing carriage returns should be stripped during diffing
func (a *ApplyImpl) StripTrailingCR() bool {
return a.ApplyOptions.StripTrailingCR
}
// DiffOutput returns the diff output.
func (a *ApplyImpl) DiffOutput() string {
return a.Output
}
// IncludeNeeds returns the include needs.
func (a *ApplyImpl) IncludeNeeds() bool {
return a.ApplyOptions.IncludeNeeds || a.IncludeTransitiveNeeds()
}
// IncludeTests returns the include tests.
func (a *ApplyImpl) IncludeTests() bool {
return a.ApplyOptions.IncludeTests
}
// IncludeTransitiveNeeds returns the include transitive needs.
func (a *ApplyImpl) IncludeTransitiveNeeds() bool {
return a.ApplyOptions.IncludeTransitiveNeeds
}
// ShowSecrets returns the show secrets.
func (a *ApplyImpl) ShowSecrets() bool {
return a.ApplyOptions.ShowSecrets
}
// NoHooks skips hooks.
func (a *ApplyImpl) NoHooks() bool {
return a.ApplyOptions.NoHooks
}
// SkipCRDs returns the skip CRDs.
func (a *ApplyImpl) SkipCRDs() bool {
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.
func (a *ApplyImpl) SkipCleanup() bool {
return a.ApplyOptions.SkipCleanup
}
// SkipDiffOnInstall returns the skip diff on install.
func (a *ApplyImpl) SkipDiffOnInstall() bool {
return a.ApplyOptions.SkipDiffOnInstall
}
// DiffArgs is the list of arguments to pass to helm-diff.
func (a *ApplyImpl) DiffArgs() string {
return a.ApplyOptions.DiffArgs
}
// SkipNeeds returns the skip needs.
func (a *ApplyImpl) SkipNeeds() bool {
if !a.IncludeNeeds() {
return a.ApplyOptions.SkipNeeds
}
return false
}
// Suppress returns the suppress.
func (a *ApplyImpl) Suppress() []string {
return a.ApplyOptions.Suppress
}
// SuppressDiff returns the suppress diff.
func (a *ApplyImpl) SuppressDiff() bool {
return a.ApplyOptions.SuppressDiff
}
// SuppressSecrets returns the suppress secrets.
func (a *ApplyImpl) SuppressSecrets() bool {
return a.ApplyOptions.SuppressSecrets
}
// Validate returns the validate.
func (a *ApplyImpl) Validate() bool {
return a.ApplyOptions.Validate
}
// Values returns the values.
func (a *ApplyImpl) Values() []string {
return a.ApplyOptions.Values
}
// Wait returns the wait.
func (a *ApplyImpl) Wait() bool {
return a.ApplyOptions.Wait
}
// WaitRetries returns the wait retries.
func (a *ApplyImpl) WaitRetries() int {
return a.ApplyOptions.WaitRetries
}
// WaitForJobs returns the wait for jobs.
func (a *ApplyImpl) WaitForJobs() bool {
return a.ApplyOptions.WaitForJobs
}
// ReuseValues returns the ReuseValues.
func (a *ApplyImpl) ReuseValues() bool {
if !a.ResetValues() {
return a.ApplyOptions.ReuseValues
}
return false
}
func (a *ApplyImpl) ResetValues() bool {
return a.ApplyOptions.ResetValues
}
// PostRenderer returns the PostRenderer.
func (a *ApplyImpl) PostRenderer() string {
return a.ApplyOptions.PostRenderer
}
// PostRendererArgs returns the PostRendererArgs.
func (a *ApplyImpl) PostRendererArgs() []string {
return a.ApplyOptions.PostRendererArgs
}
// SkipSchemaValidation returns the SkipSchemaValidation.
func (a *ApplyImpl) SkipSchemaValidation() bool {
return a.ApplyOptions.SkipSchemaValidation
}
// Cascade returns cascade flag
func (a *ApplyImpl) Cascade() string {
return a.ApplyOptions.Cascade
}
// SuppressOutputLineRegex returns the SuppressOutputLineRegex.
func (a *ApplyImpl) SuppressOutputLineRegex() []string {
return a.ApplyOptions.SuppressOutputLineRegex
}
// SyncArgs returns the SyncArgs.
func (a *ApplyImpl) SyncArgs() string {
return a.ApplyOptions.SyncArgs
}
// HideNotes returns the HideNotes.
func (a *ApplyImpl) HideNotes() bool {
return a.ApplyOptions.HideNotes
}
// TakeOwnership returns the TakeOwnership.
func (a *ApplyImpl) TakeOwnership() bool {
return a.ApplyOptions.TakeOwnership
}
func (a *ApplyImpl) SyncReleaseLabels() bool {
return a.ApplyOptions.SyncReleaseLabels
}

204
pkg/config/apply_impl.go Normal file
View File

@ -0,0 +1,204 @@
package config
// ApplyImpl is impl for applyOptions
type ApplyImpl struct {
*GlobalImpl
*ApplyOptions
}
// NewApplyImpl creates a new ApplyImpl
func NewApplyImpl(g *GlobalImpl, a *ApplyOptions) *ApplyImpl {
return &ApplyImpl{
GlobalImpl: g,
ApplyOptions: a,
}
}
// Set returns the set.
func (t *ApplyImpl) Set() []string {
return t.ApplyOptions.Set
}
// Concurrency returns the concurrency.
func (t *ApplyImpl) Concurrency() int {
return t.ApplyOptions.Concurrency
}
// Context returns the context.
func (t *ApplyImpl) Context() int {
return t.ApplyOptions.Context
}
// DetailedExitcode returns the detailed exitcode.
func (t *ApplyImpl) DetailedExitcode() bool {
return t.ApplyOptions.DetailedExitcode
}
// StripTrailingCR is true if trailing carriage returns should be stripped during diffing
func (t *ApplyImpl) StripTrailingCR() bool {
return t.ApplyOptions.StripTrailingCR
}
// DiffOutput returns the diff output.
func (t *ApplyImpl) DiffOutput() string {
return t.Output
}
// IncludeNeeds returns the include needs.
func (t *ApplyImpl) IncludeNeeds() bool {
return t.ApplyOptions.IncludeNeeds || t.IncludeTransitiveNeeds()
}
// IncludeTests returns the include tests.
func (t *ApplyImpl) IncludeTests() bool {
return t.ApplyOptions.IncludeTests
}
// IncludeTransitiveNeeds returns the include transitive needs.
func (t *ApplyImpl) IncludeTransitiveNeeds() bool {
return t.ApplyOptions.IncludeTransitiveNeeds
}
// ShowSecrets returns the show secrets.
func (t *ApplyImpl) ShowSecrets() bool {
return t.ApplyOptions.ShowSecrets
}
// NoHooks skips hooks.
func (t *ApplyImpl) NoHooks() bool {
return t.ApplyOptions.NoHooks
}
// SkipCRDs returns the skip CRDs.
func (t *ApplyImpl) SkipCRDs() bool {
return t.ApplyOptions.SkipCRDsFlag.Value()
}
// IncludeCRDs returns the include CRDs.
func (t *ApplyImpl) IncludeCRDs() bool {
return t.ApplyOptions.IncludeCRDsFlag.Value()
}
// ShouldIncludeCRDs determines if CRDs should be included in the operation.
func (t *ApplyImpl) ShouldIncludeCRDs() bool {
return ShouldIncludeCRDs(t.IncludeCRDsFlag, t.SkipCRDsFlag)
}
// SkipCleanup returns the skip cleanup.
func (t *ApplyImpl) SkipCleanup() bool {
return t.ApplyOptions.SkipCleanup
}
// SkipDiffOnInstall returns the skip diff on install.
func (t *ApplyImpl) SkipDiffOnInstall() bool {
return t.ApplyOptions.SkipDiffOnInstall
}
// DiffArgs is the list of arguments to pass to helm-diff.
func (t *ApplyImpl) DiffArgs() string {
return t.ApplyOptions.DiffArgs
}
// SkipNeeds returns the skip needs.
func (t *ApplyImpl) SkipNeeds() bool {
if !t.IncludeNeeds() {
return t.ApplyOptions.SkipNeeds
}
return false
}
// Suppress returns the suppress.
func (t *ApplyImpl) Suppress() []string {
return t.ApplyOptions.Suppress
}
// SuppressDiff returns the suppress diff.
func (t *ApplyImpl) SuppressDiff() bool {
return t.ApplyOptions.SuppressDiff
}
// SuppressSecrets returns the suppress secrets.
func (t *ApplyImpl) SuppressSecrets() bool {
return t.ApplyOptions.SuppressSecrets
}
// Validate returns the validate.
func (t *ApplyImpl) Validate() bool {
return t.ApplyOptions.Validate
}
// Values returns the values.
func (t *ApplyImpl) Values() []string {
return t.ApplyOptions.Values
}
// Wait returns the wait.
func (t *ApplyImpl) Wait() bool {
return t.ApplyOptions.Wait
}
// WaitRetries returns the wait retries.
func (t *ApplyImpl) WaitRetries() int {
return t.ApplyOptions.WaitRetries
}
// WaitForJobs returns the wait for jobs.
func (t *ApplyImpl) WaitForJobs() bool {
return t.ApplyOptions.WaitForJobs
}
// ReuseValues returns the ReuseValues.
func (t *ApplyImpl) ReuseValues() bool {
if !t.ResetValues() {
return t.ApplyOptions.ReuseValues
}
return false
}
func (t *ApplyImpl) ResetValues() bool {
return t.ApplyOptions.ResetValues
}
// PostRenderer returns the PostRenderer.
func (t *ApplyImpl) PostRenderer() string {
return t.ApplyOptions.PostRenderer
}
// PostRendererArgs returns the PostRendererArgs.
func (t *ApplyImpl) PostRendererArgs() []string {
return t.ApplyOptions.PostRendererArgs
}
// SkipSchemaValidation returns the SkipSchemaValidation.
func (t *ApplyImpl) SkipSchemaValidation() bool {
return t.ApplyOptions.SkipSchemaValidation
}
// Cascade returns cascade flag
func (t *ApplyImpl) Cascade() string {
return t.ApplyOptions.Cascade
}
// SuppressOutputLineRegex returns the SuppressOutputLineRegex.
func (t *ApplyImpl) SuppressOutputLineRegex() []string {
return t.ApplyOptions.SuppressOutputLineRegex
}
// SyncArgs returns the SyncArgs.
func (t *ApplyImpl) SyncArgs() string {
return t.ApplyOptions.SyncArgs
}
// HideNotes returns the HideNotes.
func (t *ApplyImpl) HideNotes() bool {
return t.ApplyOptions.HideNotes
}
// TakeOwnership returns the TakeOwnership.
func (t *ApplyImpl) TakeOwnership() bool {
return t.ApplyOptions.TakeOwnership
}
func (t *ApplyImpl) SyncReleaseLabels() bool {
return t.ApplyOptions.SyncReleaseLabels
}

57
pkg/config/apply_test.go Normal file
View File

@ -0,0 +1,57 @@
package config
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestApplyOptions_HandleFlag(t *testing.T) {
options := NewApplyOptions()
// Test handling include-crds flag
includeCRDs := true
handled := options.HandleFlag("include-crds", &includeCRDs, true)
assert.True(t, handled, "include-crds flag should be handled")
assert.True(t, options.IncludeCRDsFlag.WasExplicitlySet())
assert.True(t, options.IncludeCRDsFlag.Value())
// Test that flag is handled even when not changed
handled = options.HandleFlag("include-crds", &includeCRDs, false)
assert.True(t, handled, "include-crds flag should be handled even when not changed")
// Test handling skip-crds flag
skipCRDs := true
handled = options.HandleFlag("skip-crds", &skipCRDs, true)
assert.True(t, options.SkipCRDsFlag.WasExplicitlySet())
assert.True(t, handled, "skip-crds flag should be handled")
assert.True(t, options.SkipCRDsFlag.WasExplicitlySet())
assert.True(t, options.SkipCRDsFlag.Value())
}
func TestApplyOptions_HandleFlag_UnknownFlag(t *testing.T) {
options := NewApplyOptions()
// Test handling a non-existent flag
skipCRDs := true
handled := options.HandleFlag("non-existent-flag", &skipCRDs, true)
assert.False(t, handled, "non-existent flag should not be handled")
}
func TestApplyOptions_HandleFlag_NotBool(t *testing.T) {
options := NewApplyOptions()
// Test handling include-crds flag
includeCRDs := true
handled := options.HandleFlag("include-crds", &includeCRDs, true)
assert.True(t, handled, "include-crds flag should be handled")
assert.True(t, options.IncludeCRDsFlag.Value())
// Test with incorrect value type
stringValue := "not-a-bool"
handled = options.HandleFlag("include-crds", &stringValue, true)
assert.True(t, handled, "include-crds flag should be handled even with incorrect type")
// Value should not change when type is incorrect
assert.True(t, options.IncludeCRDsFlag.Value())
}

View File

@ -10,22 +10,3 @@ type BuildOptions struct {
func NewBuildOptions() *BuildOptions {
return &BuildOptions{}
}
// BuildImpl is impl for applyOptions
type BuildImpl struct {
*GlobalImpl
*BuildOptions
}
// NewBuildImpl creates a new BuildImpl
func NewBuildImpl(g *GlobalImpl, b *BuildOptions) *BuildImpl {
return &BuildImpl{
GlobalImpl: g,
BuildOptions: b,
}
}
// EmbedValues returns the embed values.
func (b *BuildImpl) EmbedValues() bool {
return b.BuildOptions.EmbedValues
}

20
pkg/config/build_impl.go Normal file
View File

@ -0,0 +1,20 @@
package config
// BuildImpl is impl for BuildOptions
type BuildImpl struct {
*GlobalImpl
*BuildOptions
}
// NewBuildImpl creates a new BuildImpl
func NewBuildImpl(g *GlobalImpl, b *BuildOptions) *BuildImpl {
return &BuildImpl{
GlobalImpl: g,
BuildOptions: b,
}
}
// EmbedValues returns the embed values.
func (b *BuildImpl) EmbedValues() bool {
return b.BuildOptions.EmbedValues
}

View File

@ -7,17 +7,3 @@ type CacheOptions struct{}
func NewCacheOptions() *CacheOptions {
return &CacheOptions{}
}
// CacheImpl is impl for applyOptions
type CacheImpl struct {
*GlobalImpl
*CacheOptions
}
// NewCacheImpl creates a new CacheImpl
func NewCacheImpl(g *GlobalImpl, b *CacheOptions) *CacheImpl {
return &CacheImpl{
GlobalImpl: g,
CacheOptions: b,
}
}

15
pkg/config/cache_impl.go Normal file
View File

@ -0,0 +1,15 @@
package config
// CacheImpl is impl for CacheOptions
type CacheImpl struct {
*GlobalImpl
*CacheOptions
}
// NewCacheImpl creates a new CacheImpl
func NewCacheImpl(g *GlobalImpl, b *CacheOptions) *CacheImpl {
return &CacheImpl{
GlobalImpl: g,
CacheOptions: b,
}
}

View File

@ -12,32 +12,3 @@ type DepsOptions struct {
func NewDepsOptions() *DepsOptions {
return &DepsOptions{}
}
// DepsImpl is impl for applyOptions
type DepsImpl struct {
*GlobalImpl
*DepsOptions
}
// NewDepsImpl creates a new DepsImpl
func NewDepsImpl(g *GlobalImpl, b *DepsOptions) *DepsImpl {
return &DepsImpl{
GlobalImpl: g,
DepsOptions: b,
}
}
// SkipRepos returns the skip deps
func (d *DepsImpl) SkipRepos() bool {
return d.DepsOptions.SkipRepos
}
// IncludeTransitiveNeeds returns the includeTransitiveNeeds
func (d *DepsImpl) IncludeTransitiveNeeds() bool {
return false
}
// Concurrency returns the concurrency
func (c *DepsImpl) Concurrency() int {
return c.DepsOptions.Concurrency
}

30
pkg/config/deps_impl.go Normal file
View File

@ -0,0 +1,30 @@
package config
// DepsImpl is impl for DepsOptions
type DepsImpl struct {
*GlobalImpl
*DepsOptions
}
// NewDepsImpl creates a new DepsImpl
func NewDepsImpl(g *GlobalImpl, b *DepsOptions) *DepsImpl {
return &DepsImpl{
GlobalImpl: g,
DepsOptions: b,
}
}
// SkipRepos returns the skip deps
func (d *DepsImpl) SkipRepos() bool {
return d.DepsOptions.SkipRepos
}
// IncludeTransitiveNeeds returns the includeTransitiveNeeds
func (d *DepsImpl) IncludeTransitiveNeeds() bool {
return false
}
// Concurrency returns the concurrency
func (c *DepsImpl) Concurrency() int {
return c.DepsOptions.Concurrency
}

View File

@ -18,42 +18,3 @@ type DestroyOptions struct {
func NewDestroyOptions() *DestroyOptions {
return &DestroyOptions{}
}
// DestroyImpl is impl for applyOptions
type DestroyImpl struct {
*GlobalImpl
*DestroyOptions
}
// NewDestroyImpl creates a new DestroyImpl
func NewDestroyImpl(g *GlobalImpl, b *DestroyOptions) *DestroyImpl {
return &DestroyImpl{
GlobalImpl: g,
DestroyOptions: b,
}
}
// Concurrency returns the concurrency
func (c *DestroyImpl) Concurrency() int {
return c.DestroyOptions.Concurrency
}
// SkipCharts returns skipCharts flag
func (c *DestroyImpl) SkipCharts() bool {
return c.DestroyOptions.SkipCharts
}
// Cascade returns cascade flag
func (c *DestroyImpl) Cascade() string {
return c.DestroyOptions.Cascade
}
// DeleteWait returns the wait flag
func (c *DestroyImpl) DeleteWait() bool {
return c.DestroyOptions.DeleteWait
}
// DeleteTimeout returns the timeout flag
func (c *DestroyImpl) DeleteTimeout() int {
return c.DestroyOptions.DeleteTimeout
}

View File

@ -0,0 +1,40 @@
package config
// DestroyImpl is impl for DestroyOptions
type DestroyImpl struct {
*GlobalImpl
*DestroyOptions
}
// NewDestroyImpl creates a new DestroyImpl
func NewDestroyImpl(g *GlobalImpl, b *DestroyOptions) *DestroyImpl {
return &DestroyImpl{
GlobalImpl: g,
DestroyOptions: b,
}
}
// Concurrency returns the concurrency
func (c *DestroyImpl) Concurrency() int {
return c.DestroyOptions.Concurrency
}
// SkipCharts returns skipCharts flag
func (c *DestroyImpl) SkipCharts() bool {
return c.DestroyOptions.SkipCharts
}
// Cascade returns cascade flag
func (c *DestroyImpl) Cascade() string {
return c.DestroyOptions.Cascade
}
// DeleteWait returns the wait flag
func (c *DestroyImpl) DeleteWait() bool {
return c.DestroyOptions.DeleteWait
}
// DeleteTimeout returns the timeout flag
func (c *DestroyImpl) DeleteTimeout() int {
return c.DestroyOptions.DeleteTimeout
}

View File

@ -1,6 +1,9 @@
package config
import "github.com/helmfile/helmfile/pkg/common"
import (
"github.com/helmfile/helmfile/pkg/common"
"github.com/helmfile/helmfile/pkg/flags"
)
// DiffOptions is the options for the build command
type DiffOptions struct {
@ -59,172 +62,27 @@ type DiffOptions struct {
// NewDiffOptions creates a new Apply
func NewDiffOptions() *DiffOptions {
newOptions := &DiffOptions{
IncludeCRDsFlag: common.NewBoolFlag(false),
SkipCRDsFlag: common.NewBoolFlag(false),
}
newOptions := &DiffOptions{}
newOptions.Initialize()
return newOptions
}
// DiffImpl is impl for applyOptions
type DiffImpl struct {
*GlobalImpl
*DiffOptions
func (o *DiffOptions) Initialize() {
flags.EnsureBoolFlag(&o.IncludeCRDsFlag, false)
flags.EnsureBoolFlag(&o.SkipCRDsFlag, false) // not exposed as cli flag but needed for ShouldIncludeCRDs() until skip-crds is removed
}
// NewDiffImpl creates a new DiffImpl
func NewDiffImpl(g *GlobalImpl, t *DiffOptions) *DiffImpl {
return &DiffImpl{
GlobalImpl: g,
DiffOptions: t,
}
}
// Concurrency returns the concurrency
func (t *DiffImpl) Concurrency() int {
return t.DiffOptions.Concurrency
}
// IncludeNeeds returns the include needs
func (t *DiffImpl) IncludeNeeds() bool {
return t.DiffOptions.IncludeNeeds || t.IncludeTransitiveNeeds()
}
// IncludeTransitiveNeeds returns the include transitive needs
func (t *DiffImpl) IncludeTransitiveNeeds() bool {
return t.DiffOptions.IncludeTransitiveNeeds
}
// Set returns the Set
func (t *DiffImpl) Set() []string {
return t.DiffOptions.Set
}
// SkipNeeds returns the skip needs
func (t *DiffImpl) SkipNeeds() bool {
if !t.IncludeNeeds() {
return t.DiffOptions.SkipNeeds
func (o *DiffOptions) HandleFlag(name string, value interface{}, changed bool) bool {
switch name {
case "include-crds":
if changed {
if boolVal, ok := value.(*bool); ok {
o.IncludeCRDsFlag.Set(*boolVal)
}
}
return true
}
return false
}
// Validate returns the validate
func (t *DiffImpl) Validate() bool {
return t.DiffOptions.Validate
}
// Values returns the values
func (t *DiffImpl) Values() []string {
return t.DiffOptions.Values
}
// Context returns the context
func (t *DiffImpl) Context() int {
return t.DiffOptions.Context
}
// DetailedExitCode returns the detailed exit code
func (t *DiffImpl) DetailedExitcode() bool {
return t.DiffOptions.DetailedExitcode
}
// StripTrailingCR is true if trailing carriage returns should be stripped during diffing
func (a *DiffImpl) StripTrailingCR() bool {
return a.DiffOptions.StripTrailingCR
}
// Output returns the output
func (t *DiffImpl) DiffOutput() string {
return t.Output
}
// IncludeTests returns the include tests
func (t *DiffImpl) IncludeTests() bool {
return t.DiffOptions.IncludeTests
}
// ShowSecrets returns the show secrets
func (t *DiffImpl) ShowSecrets() bool {
return t.DiffOptions.ShowSecrets
}
// NoHooks skips hooks.
func (t *DiffImpl) NoHooks() bool {
return t.DiffOptions.NoHooks
}
// SkipCRDs returns the skip crds
func (t *DiffImpl) SkipCRDs() bool {
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
func (t *DiffImpl) SkipDiffOnInstall() bool {
return t.DiffOptions.SkipDiffOnInstall
}
// DiffArgs returns the list of arguments to pass to helm-diff.
func (t *DiffImpl) DiffArgs() string {
return t.DiffOptions.DiffArgs
}
// Suppress returns the suppress
func (t *DiffImpl) Suppress() []string {
return t.DiffOptions.Suppress
}
// SuppressDiff returns the suppress diff
func (t *DiffImpl) SuppressDiff() bool {
return false
}
// SuppressSecrets returns the suppress secrets
func (t *DiffImpl) SuppressSecrets() bool {
return t.DiffOptions.SuppressSecrets
}
// ReuseValues returns the ReuseValues.
func (t *DiffImpl) ReuseValues() bool {
if !t.ResetValues() {
return t.DiffOptions.ReuseValues
}
return false
}
func (t *DiffImpl) ResetValues() bool {
return t.DiffOptions.ResetValues
}
// PostRenderer returns the PostRenderer.
func (t *DiffImpl) PostRenderer() string {
return t.DiffOptions.PostRenderer
}
// PostRendererArgs returns the PostRendererArgs.
func (t *DiffImpl) PostRendererArgs() []string {
return t.DiffOptions.PostRendererArgs
}
// SuppressOutputLineRegex returns the SuppressOutputLineRegex.
func (t *DiffImpl) SuppressOutputLineRegex() []string {
return t.DiffOptions.SuppressOutputLineRegex
}
func (t *DiffImpl) SkipSchemaValidation() bool {
return t.DiffOptions.SkipSchemaValidation
}

160
pkg/config/diff_impl.go Normal file
View File

@ -0,0 +1,160 @@
package config
// DiffImpl is impl for DiffOptions
type DiffImpl struct {
*GlobalImpl
*DiffOptions
}
// NewDiffImpl creates a new DiffImpl
func NewDiffImpl(g *GlobalImpl, t *DiffOptions) *DiffImpl {
return &DiffImpl{
GlobalImpl: g,
DiffOptions: t,
}
}
// Concurrency returns the concurrency
func (t *DiffImpl) Concurrency() int {
return t.DiffOptions.Concurrency
}
// IncludeNeeds returns the include needs
func (t *DiffImpl) IncludeNeeds() bool {
return t.DiffOptions.IncludeNeeds || t.IncludeTransitiveNeeds()
}
// IncludeTransitiveNeeds returns the include transitive needs
func (t *DiffImpl) IncludeTransitiveNeeds() bool {
return t.DiffOptions.IncludeTransitiveNeeds
}
// Set returns the Set
func (t *DiffImpl) Set() []string {
return t.DiffOptions.Set
}
// SkipNeeds returns the skip needs
func (t *DiffImpl) SkipNeeds() bool {
if !t.IncludeNeeds() {
return t.DiffOptions.SkipNeeds
}
return false
}
// Validate returns the validate
func (t *DiffImpl) Validate() bool {
return t.DiffOptions.Validate
}
// Values returns the values
func (t *DiffImpl) Values() []string {
return t.DiffOptions.Values
}
// Context returns the context
func (t *DiffImpl) Context() int {
return t.DiffOptions.Context
}
// DetailedExitCode returns the detailed exit code
func (t *DiffImpl) DetailedExitcode() bool {
return t.DiffOptions.DetailedExitcode
}
// StripTrailingCR is true if trailing carriage returns should be stripped during diffing
func (a *DiffImpl) StripTrailingCR() bool {
return a.DiffOptions.StripTrailingCR
}
// Output returns the output
func (t *DiffImpl) DiffOutput() string {
return t.Output
}
// IncludeTests returns the include tests
func (t *DiffImpl) IncludeTests() bool {
return t.DiffOptions.IncludeTests
}
// ShowSecrets returns the show secrets
func (t *DiffImpl) ShowSecrets() bool {
return t.DiffOptions.ShowSecrets
}
// NoHooks skips hooks.
func (t *DiffImpl) NoHooks() bool {
return t.DiffOptions.NoHooks
}
// SkipCRDs returns the skip crds
func (t *DiffImpl) SkipCRDs() bool {
return t.DiffOptions.SkipCRDsFlag.Value()
}
// IncludeCRDs returns the include crds
func (t *DiffImpl) IncludeCRDs() bool {
return t.DiffOptions.IncludeCRDsFlag.Value()
}
// ShouldIncludeCRDs determines if CRDs should be included in the operation.
func (t *DiffImpl) ShouldIncludeCRDs() bool {
return ShouldIncludeCRDs(t.IncludeCRDsFlag, t.SkipCRDsFlag)
}
// SkipDiffOnInstall returns the skip diff on install
func (t *DiffImpl) SkipDiffOnInstall() bool {
return t.DiffOptions.SkipDiffOnInstall
}
// DiffArgs returns the list of arguments to pass to helm-diff.
func (t *DiffImpl) DiffArgs() string {
return t.DiffOptions.DiffArgs
}
// Suppress returns the suppress
func (t *DiffImpl) Suppress() []string {
return t.DiffOptions.Suppress
}
// SuppressDiff returns the suppress diff
func (t *DiffImpl) SuppressDiff() bool {
return false
}
// SuppressSecrets returns the suppress secrets
func (t *DiffImpl) SuppressSecrets() bool {
return t.DiffOptions.SuppressSecrets
}
// ReuseValues returns the ReuseValues.
func (t *DiffImpl) ReuseValues() bool {
if !t.ResetValues() {
return t.DiffOptions.ReuseValues
}
return false
}
func (t *DiffImpl) ResetValues() bool {
return t.DiffOptions.ResetValues
}
// PostRenderer returns the PostRenderer.
func (t *DiffImpl) PostRenderer() string {
return t.DiffOptions.PostRenderer
}
// PostRendererArgs returns the PostRendererArgs.
func (t *DiffImpl) PostRendererArgs() []string {
return t.DiffOptions.PostRendererArgs
}
// SuppressOutputLineRegex returns the SuppressOutputLineRegex.
func (t *DiffImpl) SuppressOutputLineRegex() []string {
return t.DiffOptions.SuppressOutputLineRegex
}
func (t *DiffImpl) SkipSchemaValidation() bool {
return t.DiffOptions.SkipSchemaValidation
}

17
pkg/config/diff_test.go Normal file
View File

@ -0,0 +1,17 @@
package config
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestDiffOptions_HandleFlag(t *testing.T) {
options := NewDiffOptions()
// Test handling include-crds flag
includeCRDs := true
handled := options.HandleFlag("include-crds", &includeCRDs, true)
assert.True(t, handled, "include-crds flag should be handled")
assert.True(t, options.IncludeCRDsFlag.Value())
}

View File

@ -14,32 +14,3 @@ type FetchOptions struct {
func NewFetchOptions() *FetchOptions {
return &FetchOptions{}
}
// FetchImpl is impl for applyOptions
type FetchImpl struct {
*GlobalImpl
*FetchOptions
}
// NewFetchImpl creates a new FetchImpl
func NewFetchImpl(g *GlobalImpl, b *FetchOptions) *FetchImpl {
return &FetchImpl{
GlobalImpl: g,
FetchOptions: b,
}
}
// Concurrency returns the concurrency
func (c *FetchImpl) Concurrency() int {
return c.FetchOptions.Concurrency
}
// OutputDir returns the args
func (c *FetchImpl) OutputDir() string {
return c.FetchOptions.OutputDir
}
// OutputDirTemplate returns the go template to generate the path of output directory
func (c *FetchImpl) OutputDirTemplate() string {
return c.FetchOptions.OutputDirTemplate
}

30
pkg/config/fetch_impl.go Normal file
View File

@ -0,0 +1,30 @@
package config
// FetchImpl is impl for FechtOptions
type FetchImpl struct {
*GlobalImpl
*FetchOptions
}
// NewFetchImpl creates a new FetchImpl
func NewFetchImpl(g *GlobalImpl, b *FetchOptions) *FetchImpl {
return &FetchImpl{
GlobalImpl: g,
FetchOptions: b,
}
}
// Concurrency returns the concurrency
func (c *FetchImpl) Concurrency() int {
return c.FetchOptions.Concurrency
}
// OutputDir returns the args
func (c *FetchImpl) OutputDir() string {
return c.FetchOptions.OutputDir
}
// OutputDirTemplate returns the go template to generate the path of output directory
func (c *FetchImpl) OutputDirTemplate() string {
return c.FetchOptions.OutputDirTemplate
}

17
pkg/config/flag_utils.go Normal file
View File

@ -0,0 +1,17 @@
package config
import "github.com/helmfile/helmfile/pkg/common"
// ShouldIncludeCRDs determines if CRDs should be included in the operation.
// It returns true only when:
// - includeCRDs flag is explicitly provided on the command line and set to true
// - AND skipCRDs flag is not provided on the command line
//
// This ensures that CRDs are only included when explicitly requested and not
// contradicted by the skipCRDs flag.
func ShouldIncludeCRDs(includeCRDsFlag, skipCRDsFlag common.BoolFlag) bool {
includeCRDsExplicit := includeCRDsFlag.WasExplicitlySet() && includeCRDsFlag.Value()
skipCRDsProvided := skipCRDsFlag.WasExplicitlySet()
return includeCRDsExplicit && !skipCRDsProvided
}

View File

@ -1,17 +1,9 @@
package config
import (
"errors"
"fmt"
"io"
"os"
"go.uber.org/zap"
"golang.org/x/term"
"github.com/helmfile/helmfile/pkg/envvar"
"github.com/helmfile/helmfile/pkg/maputil"
"github.com/helmfile/helmfile/pkg/state"
)
// GlobalOptions is the global configuration for the Helmfile CLI.
@ -87,179 +79,3 @@ type GlobalImpl struct {
*GlobalOptions
set map[string]any
}
// NewGlobalImpl creates a new GlobalImpl.
func NewGlobalImpl(opts *GlobalOptions) *GlobalImpl {
return &GlobalImpl{
GlobalOptions: opts,
set: make(map[string]any),
}
}
// Setset sets the set
func (g *GlobalImpl) SetSet(set map[string]any) {
g.set = maputil.MergeMaps(g.set, set)
}
// HelmBinary returns the path to the Helm binary.
func (g *GlobalImpl) HelmBinary() string {
return g.GlobalOptions.HelmBinary
}
// KustomizeBinary returns the path to the Kustomize binary.
func (g *GlobalImpl) KustomizeBinary() string {
return g.GlobalOptions.KustomizeBinary
}
// Kubeconfig returns the path to the kubeconfig file to use.
func (g *GlobalImpl) Kubeconfig() string {
return g.GlobalOptions.Kubeconfig
}
// KubeContext returns the name of the kubectl context to use.
func (g *GlobalImpl) KubeContext() string {
return g.GlobalOptions.KubeContext
}
// Namespace returns the namespace to use.
func (g *GlobalImpl) Namespace() string {
return g.GlobalOptions.Namespace
}
// Chart returns the chart to use.
func (g *GlobalImpl) Chart() string {
return g.GlobalOptions.Chart
}
// FileOrDir returns the path to the Helmfile.
func (g *GlobalImpl) FileOrDir() string {
file := g.File
if file == "" {
file = os.Getenv(envvar.FilePath)
}
return file
}
// Selectors returns the selectors to use.
func (g *GlobalImpl) Selectors() []string {
return g.Selector
}
// StateValuesSet returns the set
func (g *GlobalImpl) StateValuesSet() map[string]any {
return g.set
}
// StateValuesSet returns the set
func (g *GlobalImpl) RawStateValuesSet() []string {
return g.GlobalOptions.StateValuesSet
}
// RawStateValuesSetString returns the set
func (g *GlobalImpl) RawStateValuesSetString() []string {
return g.StateValuesSetString
}
// StateValuesFiles returns the state values files
func (g *GlobalImpl) StateValuesFiles() []string {
return g.StateValuesFile
}
// EnableLiveOutput return when to pipe the stdout and stderr from Helm live to the helmfile stdout
func (g *GlobalImpl) EnableLiveOutput() bool {
return g.GlobalOptions.EnableLiveOutput
}
// SkipDeps return if running "helm repo update" and "helm dependency build" should be skipped
func (g *GlobalImpl) SkipDeps() bool {
return g.GlobalOptions.SkipDeps
}
// SkipRefresh return if running "helm repo update"
func (g *GlobalImpl) SkipRefresh() bool {
return g.GlobalOptions.SkipRefresh
}
// StripArgsValuesOnExitError return if the ARGS output on exit error should be suppressed
func (g *GlobalImpl) StripArgsValuesOnExitError() bool {
return g.GlobalOptions.StripArgsValuesOnExitError
}
// DisableForceUpdate return when to disable forcing updates to repos upon adding
func (g *GlobalImpl) DisableForceUpdate() bool {
return g.GlobalOptions.DisableForceUpdate
}
// Logger returns the logger
func (g *GlobalImpl) Logger() *zap.SugaredLogger {
return g.logger
}
func (g *GlobalImpl) Color() bool {
if c := g.GlobalOptions.Color; c {
return c
}
if g.GlobalOptions.NoColor {
return false
}
// We replicate the helm-diff behavior in helmfile
// because when helmfile calls helm-diff, helm-diff has no access to term and therefore
// we can't rely on helm-diff's ability to auto-detect term for color output.
// See https://github.com/roboll/helmfile/issues/2043
terminal := term.IsTerminal(int(os.Stdout.Fd()))
// https://github.com/databus23/helm-diff/issues/281
dumb := os.Getenv("TERM") == "dumb"
return terminal && !dumb
}
// NoColor returns the no color flag
func (g *GlobalImpl) NoColor() bool {
return g.GlobalOptions.NoColor
}
// Env returns the environment to use.
func (g *GlobalImpl) Env() string {
var env string
switch {
case g.Environment != "":
env = g.Environment
case os.Getenv("HELMFILE_ENVIRONMENT") != "":
env = os.Getenv("HELMFILE_ENVIRONMENT")
default:
env = state.DefaultEnv
}
return env
}
// ValidateConfig validates the global options.
func (g *GlobalImpl) ValidateConfig() error {
if g.NoColor() && g.Color() {
return errors.New("--color and --no-color cannot be specified at the same time")
}
return nil
}
// Interactive returns the Interactive
func (g *GlobalImpl) Interactive() bool {
if g.GlobalOptions.Interactive {
return true
}
return os.Getenv(envvar.Interactive) == "true"
}
// Args returns the args to use for helm
func (g *GlobalImpl) Args() string {
args := g.GlobalOptions.Args
enableHelmDebug := g.Debug
if enableHelmDebug {
args = fmt.Sprintf("%s %s", args, "--debug")
}
return args
}

190
pkg/config/global_impl.go Normal file
View File

@ -0,0 +1,190 @@
package config
import (
"errors"
"fmt"
"os"
"go.uber.org/zap"
"golang.org/x/term"
"github.com/helmfile/helmfile/pkg/envvar"
"github.com/helmfile/helmfile/pkg/maputil"
"github.com/helmfile/helmfile/pkg/state"
)
// NewGlobalImpl creates a new GlobalImpl.
func NewGlobalImpl(opts *GlobalOptions) *GlobalImpl {
return &GlobalImpl{
GlobalOptions: opts,
set: make(map[string]any),
}
}
// Setset sets the set
func (g *GlobalImpl) SetSet(set map[string]any) {
g.set = maputil.MergeMaps(g.set, set)
}
// HelmBinary returns the path to the Helm binary.
func (g *GlobalImpl) HelmBinary() string {
return g.GlobalOptions.HelmBinary
}
// KustomizeBinary returns the path to the Kustomize binary.
func (g *GlobalImpl) KustomizeBinary() string {
return g.GlobalOptions.KustomizeBinary
}
// Kubeconfig returns the path to the kubeconfig file to use.
func (g *GlobalImpl) Kubeconfig() string {
return g.GlobalOptions.Kubeconfig
}
// KubeContext returns the name of the kubectl context to use.
func (g *GlobalImpl) KubeContext() string {
return g.GlobalOptions.KubeContext
}
// Namespace returns the namespace to use.
func (g *GlobalImpl) Namespace() string {
return g.GlobalOptions.Namespace
}
// Chart returns the chart to use.
func (g *GlobalImpl) Chart() string {
return g.GlobalOptions.Chart
}
// FileOrDir returns the path to the Helmfile.
func (g *GlobalImpl) FileOrDir() string {
file := g.File
if file == "" {
file = os.Getenv(envvar.FilePath)
}
return file
}
// Selectors returns the selectors to use.
func (g *GlobalImpl) Selectors() []string {
return g.Selector
}
// StateValuesSet returns the set
func (g *GlobalImpl) StateValuesSet() map[string]any {
return g.set
}
// StateValuesSet returns the set
func (g *GlobalImpl) RawStateValuesSet() []string {
return g.GlobalOptions.StateValuesSet
}
// RawStateValuesSetString returns the set
func (g *GlobalImpl) RawStateValuesSetString() []string {
return g.StateValuesSetString
}
// StateValuesFiles returns the state values files
func (g *GlobalImpl) StateValuesFiles() []string {
return g.StateValuesFile
}
// EnableLiveOutput return when to pipe the stdout and stderr from Helm live to the helmfile stdout
func (g *GlobalImpl) EnableLiveOutput() bool {
return g.GlobalOptions.EnableLiveOutput
}
// SkipDeps return if running "helm repo update" and "helm dependency build" should be skipped
func (g *GlobalImpl) SkipDeps() bool {
return g.GlobalOptions.SkipDeps
}
// SkipRefresh return if running "helm repo update"
func (g *GlobalImpl) SkipRefresh() bool {
return g.GlobalOptions.SkipRefresh
}
// StripArgsValuesOnExitError return if the ARGS output on exit error should be suppressed
func (g *GlobalImpl) StripArgsValuesOnExitError() bool {
return g.GlobalOptions.StripArgsValuesOnExitError
}
// DisableForceUpdate return when to disable forcing updates to repos upon adding
func (g *GlobalImpl) DisableForceUpdate() bool {
return g.GlobalOptions.DisableForceUpdate
}
// Logger returns the logger
func (g *GlobalImpl) Logger() *zap.SugaredLogger {
return g.logger
}
func (g *GlobalImpl) Color() bool {
if c := g.GlobalOptions.Color; c {
return c
}
if g.GlobalOptions.NoColor {
return false
}
// We replicate the helm-diff behavior in helmfile
// because when helmfile calls helm-diff, helm-diff has no access to term and therefore
// we can't rely on helm-diff's ability to auto-detect term for color output.
// See https://github.com/roboll/helmfile/issues/2043
terminal := term.IsTerminal(int(os.Stdout.Fd()))
// https://github.com/databus23/helm-diff/issues/281
dumb := os.Getenv("TERM") == "dumb"
return terminal && !dumb
}
// NoColor returns the no color flag
func (g *GlobalImpl) NoColor() bool {
return g.GlobalOptions.NoColor
}
// Env returns the environment to use.
func (g *GlobalImpl) Env() string {
var env string
switch {
case g.Environment != "":
env = g.Environment
case os.Getenv("HELMFILE_ENVIRONMENT") != "":
env = os.Getenv("HELMFILE_ENVIRONMENT")
default:
env = state.DefaultEnv
}
return env
}
// ValidateConfig validates the global options.
func (g *GlobalImpl) ValidateConfig() error {
if g.NoColor() && g.Color() {
return errors.New("--color and --no-color cannot be specified at the same time")
}
return nil
}
// Interactive returns the Interactive
func (g *GlobalImpl) Interactive() bool {
if g.GlobalOptions.Interactive {
return true
}
return os.Getenv(envvar.Interactive) == "true"
}
// Args returns the args to use for helm
func (g *GlobalImpl) Args() string {
args := g.GlobalOptions.Args
enableHelmDebug := g.Debug
if enableHelmDebug {
args = fmt.Sprintf("%s %s", args, "--debug")
}
return args
}

View File

@ -9,22 +9,3 @@ type InitOptions struct {
func NewInitOptions() *InitOptions {
return &InitOptions{}
}
// InitImpl is impl for InitOptions
type InitImpl struct {
*GlobalImpl
*InitOptions
}
// NewInitImpl creates a new InitImpl
func NewInitImpl(g *GlobalImpl, b *InitOptions) *InitImpl {
return &InitImpl{
GlobalImpl: g,
InitOptions: b,
}
}
// Force returns the Force.
func (b *InitImpl) Force() bool {
return b.InitOptions.Force
}

20
pkg/config/init_impl.go Normal file
View File

@ -0,0 +1,20 @@
package config
// InitImpl is impl for InitOptions
type InitImpl struct {
*GlobalImpl
*InitOptions
}
// NewInitImpl creates a new InitImpl
func NewInitImpl(g *GlobalImpl, b *InitOptions) *InitImpl {
return &InitImpl{
GlobalImpl: g,
InitOptions: b,
}
}
// Force returns the Force.
func (b *InitImpl) Force() bool {
return b.InitOptions.Force
}

54
pkg/config/linit_impl.go Normal file
View File

@ -0,0 +1,54 @@
package config
// LintImpl is impl for LintOptions
type LintImpl struct {
*GlobalImpl
*LintOptions
}
// NewLintImpl creates a new LintImpl
func NewLintImpl(g *GlobalImpl, b *LintOptions) *LintImpl {
return &LintImpl{
GlobalImpl: g,
LintOptions: b,
}
}
// Concurrency returns the concurrency
func (l *LintImpl) Concurrency() int {
return l.LintOptions.Concurrency
}
// Set returns the Set
func (l *LintImpl) Set() []string {
return l.LintOptions.Set
}
// Values returns the Values
func (l *LintImpl) Values() []string {
return l.LintOptions.Values
}
// SkipCleanUp returns the skip clean up
func (l *LintImpl) SkipCleanup() bool {
return false
}
// IncludeNeeds returns the include needs
func (l *LintImpl) IncludeNeeds() bool {
return l.LintOptions.IncludeNeeds || l.IncludeTransitiveNeeds()
}
// IncludeTransitiveNeeds returns the include transitive needs
func (l *LintImpl) IncludeTransitiveNeeds() bool {
return l.LintOptions.IncludeTransitiveNeeds
}
// SkipNeeds returns the skip needs
func (l *LintImpl) SkipNeeds() bool {
if !l.IncludeNeeds() {
return l.LintOptions.SkipNeeds
}
return false
}

View File

@ -21,56 +21,3 @@ type LintOptions struct {
func NewLintOptions() *LintOptions {
return &LintOptions{}
}
// LintImpl is impl for applyOptions
type LintImpl struct {
*GlobalImpl
*LintOptions
}
// NewLintImpl creates a new LintImpl
func NewLintImpl(g *GlobalImpl, b *LintOptions) *LintImpl {
return &LintImpl{
GlobalImpl: g,
LintOptions: b,
}
}
// Concurrency returns the concurrency
func (l *LintImpl) Concurrency() int {
return l.LintOptions.Concurrency
}
// Set returns the Set
func (l *LintImpl) Set() []string {
return l.LintOptions.Set
}
// Values returns the Values
func (l *LintImpl) Values() []string {
return l.LintOptions.Values
}
// SkipCleanUp returns the skip clean up
func (l *LintImpl) SkipCleanup() bool {
return false
}
// IncludeNeeds returns the include needs
func (l *LintImpl) IncludeNeeds() bool {
return l.LintOptions.IncludeNeeds || l.IncludeTransitiveNeeds()
}
// IncludeTransitiveNeeds returns the include transitive needs
func (l *LintImpl) IncludeTransitiveNeeds() bool {
return l.LintOptions.IncludeTransitiveNeeds
}
// SkipNeeds returns the skip needs
func (l *LintImpl) SkipNeeds() bool {
if !l.IncludeNeeds() {
return l.LintOptions.SkipNeeds
}
return false
}

View File

@ -14,27 +14,3 @@ type ListOptions struct {
func NewListOptions() *ListOptions {
return &ListOptions{}
}
// ListImpl is impl for applyOptions
type ListImpl struct {
*GlobalImpl
*ListOptions
}
// NewListImpl creates a new ListImpl
func NewListImpl(g *GlobalImpl, b *ListOptions) *ListImpl {
return &ListImpl{
GlobalImpl: g,
ListOptions: b,
}
}
// Output returns the output
func (c *ListImpl) Output() string {
return c.ListOptions.Output
}
// SkipCharts returns skipCharts flag
func (c *ListImpl) SkipCharts() bool {
return c.ListOptions.SkipCharts
}

25
pkg/config/list_impl.go Normal file
View File

@ -0,0 +1,25 @@
package config
// ListImpl is impl for applyOptions
type ListImpl struct {
*GlobalImpl
*ListOptions
}
// NewListImpl creates a new ListImpl
func NewListImpl(g *GlobalImpl, b *ListOptions) *ListImpl {
return &ListImpl{
GlobalImpl: g,
ListOptions: b,
}
}
// Output returns the output
func (c *ListImpl) Output() string {
return c.ListOptions.Output
}
// SkipCharts returns skipCharts flag
func (c *ListImpl) SkipCharts() bool {
return c.ListOptions.SkipCharts
}

View File

@ -1,65 +1,13 @@
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...
}
// Options is the base interface for all command options
type Options interface {
// Initialize sets default values for options
Initialize()
}
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...
}
// FlagHandler handles flag values from command line
type FlagHandler interface {
// HandleFlag processes a flag value
HandleFlag(name string, value interface{}, changed bool)
}

View File

@ -0,0 +1,61 @@
package config
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestDiffOptions_Initialize(t *testing.T) {
options := &DiffOptions{}
options.Initialize()
// Verify initialization
assert.False(t, options.DetailedExitcode)
assert.False(t, options.StripTrailingCR)
assert.False(t, options.IncludeTests)
assert.False(t, options.SuppressSecrets)
assert.False(t, options.ShowSecrets)
assert.False(t, options.NoHooks)
assert.False(t, options.IncludeCRDsFlag.Value())
assert.False(t, options.SkipCRDsFlag.Value())
}
func TestApplyOptions_Initialize(t *testing.T) {
options := &ApplyOptions{}
options.Initialize()
// Verify initialization
assert.False(t, options.DetailedExitcode)
assert.False(t, options.StripTrailingCR)
assert.False(t, options.IncludeTests)
assert.False(t, options.SuppressSecrets)
assert.False(t, options.ShowSecrets)
assert.False(t, options.NoHooks)
assert.False(t, options.SkipNeeds)
assert.False(t, options.IncludeCRDsFlag.Value())
assert.False(t, options.SkipCRDsFlag.Value())
}
func TestSyncOptions_Initialize(t *testing.T) {
options := &SyncOptions{}
options.Initialize()
// Verify initialization
assert.False(t, options.Validate)
assert.False(t, options.SkipNeeds)
assert.False(t, options.IncludeCRDsFlag.Value())
assert.False(t, options.SkipCRDsFlag.Value())
}
func TestTemplateOptions_Initialize(t *testing.T) {
options := &TemplateOptions{}
options.Initialize()
// Verify initialization
assert.False(t, options.SkipNeeds)
assert.False(t, options.SkipTests)
assert.False(t, options.NoHooks)
assert.False(t, options.IncludeCRDsFlag.Value())
assert.False(t, options.SkipCRDsFlag.Value())
}

View File

@ -7,22 +7,3 @@ type ReposOptions struct{}
func NewReposOptions() *ReposOptions {
return &ReposOptions{}
}
// ReposImpl is impl for applyOptions
type ReposImpl struct {
*GlobalImpl
*ReposOptions
}
// NewReposImpl creates a new ReposImpl
func NewReposImpl(g *GlobalImpl, b *ReposOptions) *ReposImpl {
return &ReposImpl{
GlobalImpl: g,
ReposOptions: b,
}
}
// IncludeTransitiveNeeds returns the include transitive needs
func (r *ReposImpl) IncludeTransitiveNeeds() bool {
return false
}

20
pkg/config/repos_impl.go Normal file
View File

@ -0,0 +1,20 @@
package config
// ReposImpl is impl for applyOptions
type ReposImpl struct {
*GlobalImpl
*ReposOptions
}
// NewReposImpl creates a new ReposImpl
func NewReposImpl(g *GlobalImpl, b *ReposOptions) *ReposImpl {
return &ReposImpl{
GlobalImpl: g,
ReposOptions: b,
}
}
// IncludeTransitiveNeeds returns the include transitive needs
func (r *ReposImpl) IncludeTransitiveNeeds() bool {
return false
}

View File

@ -8,17 +8,3 @@ type ShowDAGOptions struct {
func NewShowDAGOptions() *ShowDAGOptions {
return &ShowDAGOptions{}
}
// ShowDAGImpl is impl for applyOptions
type ShowDAGImpl struct {
*GlobalImpl
*ShowDAGOptions
}
// NewShowDAGImpl creates a new ShowDAGImpl
func NewShowDAGImpl(g *GlobalImpl, b *ShowDAGOptions) *ShowDAGImpl {
return &ShowDAGImpl{
GlobalImpl: g,
ShowDAGOptions: b,
}
}

View File

@ -0,0 +1,15 @@
package config
// ShowDAGImpl is impl for applyOptions
type ShowDAGImpl struct {
*GlobalImpl
*ShowDAGOptions
}
// NewShowDAGImpl creates a new ShowDAGImpl
func NewShowDAGImpl(g *GlobalImpl, b *ShowDAGOptions) *ShowDAGImpl {
return &ShowDAGImpl{
GlobalImpl: g,
ShowDAGOptions: b,
}
}

View File

@ -10,27 +10,3 @@ type StatusOptions struct {
func NewStatusOptions() *StatusOptions {
return &StatusOptions{}
}
// StatusImpl is impl for applyOptions
type StatusImpl struct {
*GlobalImpl
*StatusOptions
}
// NewStatusImpl creates a new StatusImpl
func NewStatusImpl(g *GlobalImpl, b *StatusOptions) *StatusImpl {
return &StatusImpl{
GlobalImpl: g,
StatusOptions: b,
}
}
// IncludeTransitiveNeeds returns the include transitive needs
func (s *StatusImpl) IncludeTransitiveNeeds() bool {
return false
}
// Concurrency returns the concurrency
func (s *StatusImpl) Concurrency() int {
return s.StatusOptions.Concurrency
}

25
pkg/config/status_impl.go Normal file
View File

@ -0,0 +1,25 @@
package config
// StatusImpl is impl for applyOptions
type StatusImpl struct {
*GlobalImpl
*StatusOptions
}
// NewStatusImpl creates a new StatusImpl
func NewStatusImpl(g *GlobalImpl, b *StatusOptions) *StatusImpl {
return &StatusImpl{
GlobalImpl: g,
StatusOptions: b,
}
}
// IncludeTransitiveNeeds returns the include transitive needs
func (s *StatusImpl) IncludeTransitiveNeeds() bool {
return false
}
// Concurrency returns the concurrency
func (s *StatusImpl) Concurrency() int {
return s.StatusOptions.Concurrency
}

View File

@ -1,6 +1,9 @@
package config
import "github.com/helmfile/helmfile/pkg/common"
import (
"github.com/helmfile/helmfile/pkg/common"
"github.com/helmfile/helmfile/pkg/flags"
)
// SyncOptions is the options for the build command
type SyncOptions struct {
@ -50,148 +53,36 @@ type SyncOptions struct {
SyncReleaseLabels bool
}
// NewSyncOptions creates a new Apply
// NewSyncOptions creates a new SyncOption
func NewSyncOptions() *SyncOptions {
newOptions := &SyncOptions{
IncludeCRDsFlag: common.NewBoolFlag(false),
SkipCRDsFlag: common.NewBoolFlag(false),
}
newOptions := &SyncOptions{}
newOptions.Initialize()
return newOptions
}
// SyncImpl is impl for applyOptions
type SyncImpl struct {
*GlobalImpl
*SyncOptions
func (o *SyncOptions) Initialize() {
flags.EnsureBoolFlag(&o.IncludeCRDsFlag, false)
flags.EnsureBoolFlag(&o.SkipCRDsFlag, false)
}
// NewSyncImpl creates a new SyncImpl
func NewSyncImpl(g *GlobalImpl, t *SyncOptions) *SyncImpl {
return &SyncImpl{
GlobalImpl: g,
SyncOptions: t,
}
}
// Concurrency returns the concurrency
func (t *SyncImpl) Concurrency() int {
return t.SyncOptions.Concurrency
}
// IncludeNeeds returns the include needs
func (t *SyncImpl) IncludeNeeds() bool {
return t.SyncOptions.IncludeNeeds || t.IncludeTransitiveNeeds()
}
// IncludeTransitiveNeeds returns the include transitive needs
func (t *SyncImpl) IncludeTransitiveNeeds() bool {
return t.SyncOptions.IncludeTransitiveNeeds
}
// Set returns the Set
func (t *SyncImpl) Set() []string {
return t.SyncOptions.Set
}
// SkipNeeds returns the skip needs
func (t *SyncImpl) SkipNeeds() bool {
if !t.IncludeNeeds() {
return t.SyncOptions.SkipNeeds
func (o *SyncOptions) HandleFlag(name string, value interface{}, changed bool) bool {
switch name {
case "include-crds":
if changed {
if boolVal, ok := value.(*bool); ok {
o.IncludeCRDsFlag.Set(*boolVal)
}
}
return true
case "skip-crds":
if changed {
if boolVal, ok := value.(*bool); ok {
o.SkipCRDsFlag.Set(*boolVal)
}
}
return true
}
return false
}
// Validate returns the validate
func (t *SyncImpl) Validate() bool {
return t.SyncOptions.Validate
}
// Values returns the values
func (t *SyncImpl) Values() []string {
return t.SyncOptions.Values
}
// SkipCRDs returns the skip crds
func (t *SyncImpl) SkipCRDs() bool {
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
func (t *SyncImpl) Wait() bool {
return t.SyncOptions.Wait
}
// WaitRetries returns the wait retries
func (t *SyncImpl) WaitRetries() int {
return t.SyncOptions.WaitRetries
}
// WaitForJobs returns the wait for jobs
func (t *SyncImpl) WaitForJobs() bool {
return t.SyncOptions.WaitForJobs
}
// ReuseValues returns the ReuseValues.
func (t *SyncImpl) ReuseValues() bool {
if !t.ResetValues() {
return t.SyncOptions.ReuseValues
}
return false
}
func (t *SyncImpl) ResetValues() bool {
return t.SyncOptions.ResetValues
}
// PostRenderer returns the PostRenderer.
func (t *SyncImpl) PostRenderer() string {
return t.SyncOptions.PostRenderer
}
// PostRendererArgs returns the PostRendererArgs.
func (t *SyncImpl) PostRendererArgs() []string {
return t.SyncOptions.PostRendererArgs
}
// SkipSchemaValidation returns the SkipSchemaValidation.
func (t *SyncImpl) SkipSchemaValidation() bool {
return t.SyncOptions.SkipSchemaValidation
}
// Cascade returns cascade flag
func (t *SyncImpl) Cascade() string {
return t.SyncOptions.Cascade
}
// SyncArgs returns the sync args
func (t *SyncImpl) SyncArgs() string {
return t.SyncOptions.SyncArgs
}
// HideNotes returns the hide notes
func (t *SyncImpl) HideNotes() bool {
return t.SyncOptions.HideNotes
}
// TakeOwnership returns the take ownership
func (t *SyncImpl) TakeOwnership() bool {
return t.SyncOptions.TakeOwnership
}
func (t *SyncImpl) SyncReleaseLabels() bool {
return t.SyncOptions.SyncReleaseLabels
}

134
pkg/config/sync_impl.go Normal file
View File

@ -0,0 +1,134 @@
package config
// SyncImpl is impl for SyncOptions
type SyncImpl struct {
*GlobalImpl
*SyncOptions
}
// NewSyncImpl creates a new SyncImpl
func NewSyncImpl(g *GlobalImpl, t *SyncOptions) *SyncImpl {
return &SyncImpl{
GlobalImpl: g,
SyncOptions: t,
}
}
// Concurrency returns the concurrency
func (t *SyncImpl) Concurrency() int {
return t.SyncOptions.Concurrency
}
// IncludeNeeds returns the include needs
func (t *SyncImpl) IncludeNeeds() bool {
return t.SyncOptions.IncludeNeeds || t.IncludeTransitiveNeeds()
}
// IncludeTransitiveNeeds returns the include transitive needs
func (t *SyncImpl) IncludeTransitiveNeeds() bool {
return t.SyncOptions.IncludeTransitiveNeeds
}
// Set returns the Set
func (t *SyncImpl) Set() []string {
return t.SyncOptions.Set
}
// SkipNeeds returns the skip needs
func (t *SyncImpl) SkipNeeds() bool {
if !t.IncludeNeeds() {
return t.SyncOptions.SkipNeeds
}
return false
}
// Validate returns the validate
func (t *SyncImpl) Validate() bool {
return t.SyncOptions.Validate
}
// Values returns the values
func (t *SyncImpl) Values() []string {
return t.SyncOptions.Values
}
// SkipCRDs returns the skip crds
func (t *SyncImpl) SkipCRDs() bool {
return t.SyncOptions.SkipCRDsFlag.Value()
}
// IncludeCRDs returns the include crds
func (t *SyncImpl) IncludeCRDs() bool {
return t.SyncOptions.IncludeCRDsFlag.Value()
}
// ShouldIncludeCRDs determines if CRDs should be included in the operation.
func (t *SyncImpl) ShouldIncludeCRDs() bool {
return ShouldIncludeCRDs(t.IncludeCRDsFlag, t.SkipCRDsFlag)
}
// Wait returns the wait
func (t *SyncImpl) Wait() bool {
return t.SyncOptions.Wait
}
// WaitRetries returns the wait retries
func (t *SyncImpl) WaitRetries() int {
return t.SyncOptions.WaitRetries
}
// WaitForJobs returns the wait for jobs
func (t *SyncImpl) WaitForJobs() bool {
return t.SyncOptions.WaitForJobs
}
// ReuseValues returns the ReuseValues.
func (t *SyncImpl) ReuseValues() bool {
if !t.ResetValues() {
return t.SyncOptions.ReuseValues
}
return false
}
func (t *SyncImpl) ResetValues() bool {
return t.SyncOptions.ResetValues
}
// PostRenderer returns the PostRenderer.
func (t *SyncImpl) PostRenderer() string {
return t.SyncOptions.PostRenderer
}
// PostRendererArgs returns the PostRendererArgs.
func (t *SyncImpl) PostRendererArgs() []string {
return t.SyncOptions.PostRendererArgs
}
// SkipSchemaValidation returns the SkipSchemaValidation.
func (t *SyncImpl) SkipSchemaValidation() bool {
return t.SyncOptions.SkipSchemaValidation
}
// Cascade returns cascade flag
func (t *SyncImpl) Cascade() string {
return t.SyncOptions.Cascade
}
// SyncArgs returns the sync args
func (t *SyncImpl) SyncArgs() string {
return t.SyncOptions.SyncArgs
}
// HideNotes returns the hide notes
func (t *SyncImpl) HideNotes() bool {
return t.SyncOptions.HideNotes
}
// TakeOwnership returns the take ownership
func (t *SyncImpl) TakeOwnership() bool {
return t.SyncOptions.TakeOwnership
}
func (t *SyncImpl) SyncReleaseLabels() bool {
return t.SyncOptions.SyncReleaseLabels
}

23
pkg/config/sync_test.go Normal file
View File

@ -0,0 +1,23 @@
package config
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestSyncOptions_HandleFlag(t *testing.T) {
options := NewSyncOptions()
// Test handling include-crds flag
includeCRDs := true
handled := options.HandleFlag("include-crds", &includeCRDs, true)
assert.True(t, handled, "include-crds flag should be handled")
assert.True(t, options.IncludeCRDsFlag.Value())
// Test handling skip-crds flag
skipCRDs := true
handled = options.HandleFlag("skip-crds", &skipCRDs, true)
assert.True(t, handled, "skip-crds flag should be handled")
assert.True(t, options.SkipCRDsFlag.Value())
}

View File

@ -1,11 +1,8 @@
package config
import (
"fmt"
"os"
"strings"
"github.com/helmfile/helmfile/pkg/common"
"github.com/helmfile/helmfile/pkg/flags"
)
// TemplateOptions is the options for the build command
@ -51,132 +48,28 @@ type TemplateOptions struct {
ShowOnly []string
}
// NewTemplateOptions creates a new Apply
// NewTemplateOptions creates a new TemplateOption
func NewTemplateOptions() *TemplateOptions {
newOptions := &TemplateOptions{
SkipCRDsFlag: common.NewBoolFlag(false),
IncludeCRDsFlag: common.NewBoolFlag(false),
}
return newOptions
options := &TemplateOptions{}
options.Initialize()
return options
}
// TemplateImpl is impl for applyOptions
type TemplateImpl struct {
*GlobalImpl
*TemplateOptions
func (o *TemplateOptions) Initialize() {
flags.EnsureBoolFlag(&o.IncludeCRDsFlag, false)
flags.EnsureBoolFlag(&o.SkipCRDsFlag, false) // not exposed as cli flag but needed for ShouldIncludeCRDs() until skip-crds is removed
}
// NewTemplateImpl creates a new TemplateImpl
func NewTemplateImpl(g *GlobalImpl, t *TemplateOptions) *TemplateImpl {
return &TemplateImpl{
GlobalImpl: g,
TemplateOptions: t,
}
}
// Concurrency returns the concurrency
func (t *TemplateImpl) Concurrency() int {
return t.TemplateOptions.Concurrency
}
// SkipCRDs returns the skip crds
func (t *TemplateImpl) SkipCRDs() bool {
return t.TemplateOptions.SkipCRDsFlag.Value()
}
// IncludeCRDs returns the include crds
func (t *TemplateImpl) IncludeCRDs() bool {
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
func (t *TemplateImpl) NoHooks() bool {
return t.TemplateOptions.NoHooks
}
// IncludeNeeds returns the include needs
func (t *TemplateImpl) IncludeNeeds() bool {
return t.TemplateOptions.IncludeNeeds || t.IncludeTransitiveNeeds()
}
// IncludeTransitiveNeeds returns the include transitive needs
func (t *TemplateImpl) IncludeTransitiveNeeds() bool {
return t.TemplateOptions.IncludeTransitiveNeeds
}
// OutputDir returns the output dir
func (t *TemplateImpl) OutputDir() string {
return strings.TrimRight(t.TemplateOptions.OutputDir, fmt.Sprintf("%c", os.PathSeparator))
}
// OutputDirTemplate returns the output dir template
func (t *TemplateImpl) OutputDirTemplate() string {
return t.TemplateOptions.OutputDirTemplate
}
// Set returns the Set
func (t *TemplateImpl) Set() []string {
return t.TemplateOptions.Set
}
// SkipCleanup returns the skip cleanup
func (t *TemplateImpl) SkipCleanup() bool {
return t.TemplateOptions.SkipCleanup
}
// SkipNeeds returns the skip needs
func (t *TemplateImpl) SkipNeeds() bool {
if !t.IncludeNeeds() {
return t.TemplateOptions.SkipNeeds
func (o *TemplateOptions) HandleFlag(name string, value interface{}, changed bool) bool {
switch name {
case "include-crds":
if changed {
if boolVal, ok := value.(*bool); ok {
o.IncludeCRDsFlag.Set(*boolVal)
}
}
return true
}
return false
}
// SkipTests returns the skip tests
func (t *TemplateImpl) SkipTests() bool {
return t.TemplateOptions.SkipTests
}
// Validate returns the validate
func (t *TemplateImpl) Validate() bool {
return t.TemplateOptions.Validate
}
// Values returns the values
func (t *TemplateImpl) Values() []string {
return t.TemplateOptions.Values
}
// PostRenderer returns the PostRenderer.
func (t *TemplateImpl) PostRenderer() string {
return t.TemplateOptions.PostRenderer
}
// PostRendererArgs returns the PostRendererArgs.
func (t *TemplateImpl) PostRendererArgs() []string {
return t.TemplateOptions.PostRendererArgs
}
// SkipSchemaValidation returns the SkipSchemaValidation.
func (t *TemplateImpl) SkipSchemaValidation() bool {
return t.TemplateOptions.SkipSchemaValidation
}
// KubeVersion returns the the KubeVersion.
func (t *TemplateImpl) KubeVersion() string {
return t.TemplateOptions.KubeVersion
}
// ShowOnly returns the ShowOnly.
func (t *TemplateImpl) ShowOnly() []string {
return t.TemplateOptions.ShowOnly
}

125
pkg/config/template_impl.go Normal file
View File

@ -0,0 +1,125 @@
package config
import (
"fmt"
"os"
"strings"
)
// TemplateImpl is impl for applyOptions
type TemplateImpl struct {
*GlobalImpl
*TemplateOptions
}
// NewTemplateImpl creates a new TemplateImpl
func NewTemplateImpl(g *GlobalImpl, t *TemplateOptions) *TemplateImpl {
return &TemplateImpl{
GlobalImpl: g,
TemplateOptions: t,
}
}
// Concurrency returns the concurrency
func (t *TemplateImpl) Concurrency() int {
return t.TemplateOptions.Concurrency
}
// SkipCRDs returns the skip crds
func (t *TemplateImpl) SkipCRDs() bool {
return t.TemplateOptions.SkipCRDsFlag.Value()
}
// IncludeCRDs returns the include crds
func (t *TemplateImpl) IncludeCRDs() bool {
return t.TemplateOptions.IncludeCRDsFlag.Value()
}
// ShouldIncludeCRDs determines if CRDs should be included in the operation.
func (t *TemplateImpl) ShouldIncludeCRDs() bool {
return ShouldIncludeCRDs(t.IncludeCRDsFlag, t.SkipCRDsFlag)
}
// NoHooks returns the no hooks
func (t *TemplateImpl) NoHooks() bool {
return t.TemplateOptions.NoHooks
}
// IncludeNeeds returns the include needs
func (t *TemplateImpl) IncludeNeeds() bool {
return t.TemplateOptions.IncludeNeeds || t.IncludeTransitiveNeeds()
}
// IncludeTransitiveNeeds returns the include transitive needs
func (t *TemplateImpl) IncludeTransitiveNeeds() bool {
return t.TemplateOptions.IncludeTransitiveNeeds
}
// OutputDir returns the output dir
func (t *TemplateImpl) OutputDir() string {
return strings.TrimRight(t.TemplateOptions.OutputDir, fmt.Sprintf("%c", os.PathSeparator))
}
// OutputDirTemplate returns the output dir template
func (t *TemplateImpl) OutputDirTemplate() string {
return t.TemplateOptions.OutputDirTemplate
}
// Set returns the Set
func (t *TemplateImpl) Set() []string {
return t.TemplateOptions.Set
}
// SkipCleanup returns the skip cleanup
func (t *TemplateImpl) SkipCleanup() bool {
return t.TemplateOptions.SkipCleanup
}
// SkipNeeds returns the skip needs
func (t *TemplateImpl) SkipNeeds() bool {
if !t.IncludeNeeds() {
return t.TemplateOptions.SkipNeeds
}
return false
}
// SkipTests returns the skip tests
func (t *TemplateImpl) SkipTests() bool {
return t.TemplateOptions.SkipTests
}
// Validate returns the validate
func (t *TemplateImpl) Validate() bool {
return t.TemplateOptions.Validate
}
// Values returns the values
func (t *TemplateImpl) Values() []string {
return t.TemplateOptions.Values
}
// PostRenderer returns the PostRenderer.
func (t *TemplateImpl) PostRenderer() string {
return t.TemplateOptions.PostRenderer
}
// PostRendererArgs returns the PostRendererArgs.
func (t *TemplateImpl) PostRendererArgs() []string {
return t.TemplateOptions.PostRendererArgs
}
// SkipSchemaValidation returns the SkipSchemaValidation.
func (t *TemplateImpl) SkipSchemaValidation() bool {
return t.TemplateOptions.SkipSchemaValidation
}
// KubeVersion returns the the KubeVersion.
func (t *TemplateImpl) KubeVersion() string {
return t.TemplateOptions.KubeVersion
}
// ShowOnly returns the ShowOnly.
func (t *TemplateImpl) ShowOnly() []string {
return t.TemplateOptions.ShowOnly
}

View File

@ -0,0 +1,17 @@
package config
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestTemplateOptions_HandleFlag(t *testing.T) {
options := NewTemplateOptions()
// Test handling include-crds flag
includeCRDs := true
handled := options.HandleFlag("include-crds", &includeCRDs, true)
assert.True(t, handled, "include-crds flag should be handled")
assert.True(t, options.IncludeCRDsFlag.Value())
}

View File

@ -1,11 +1,5 @@
package config
import (
"github.com/spf13/cobra"
"github.com/helmfile/helmfile/pkg/state"
)
// TestOptions is the options for the build command
type TestOptions struct {
// Concurrency is the maximum number of concurrent helm processes to run, 0 is unlimited
@ -22,41 +16,3 @@ type TestOptions struct {
func NewTestOptions() *TestOptions {
return &TestOptions{}
}
// TestImpl is impl for applyOptions
type TestImpl struct {
*GlobalImpl
*TestOptions
Cmd *cobra.Command
}
// NewTestImpl creates a new TestImpl
func NewTestImpl(g *GlobalImpl, t *TestOptions) *TestImpl {
return &TestImpl{
GlobalImpl: g,
TestOptions: t,
}
}
// Concurrency returns the concurrency
func (t *TestImpl) Concurrency() int {
return t.TestOptions.Concurrency
}
// Cleanup returns the cleanup
func (t *TestImpl) Cleanup() bool {
return t.TestOptions.Cleanup
}
// Logs returns the logs
func (t *TestImpl) Logs() bool {
return t.TestOptions.Logs
}
// Timeout returns the timeout
func (t *TestImpl) Timeout() int {
if !t.Cmd.Flags().Changed("timeout") {
return state.EmptyTimeout
}
return t.TestOptions.Timeout
}

45
pkg/config/test_impl.go Normal file
View File

@ -0,0 +1,45 @@
package config
import (
"github.com/spf13/cobra"
"github.com/helmfile/helmfile/pkg/state"
)
// TestImpl is impl for applyOptions
type TestImpl struct {
*GlobalImpl
*TestOptions
Cmd *cobra.Command
}
// NewTestImpl creates a new TestImpl
func NewTestImpl(g *GlobalImpl, t *TestOptions) *TestImpl {
return &TestImpl{
GlobalImpl: g,
TestOptions: t,
}
}
// Concurrency returns the concurrency
func (t *TestImpl) Concurrency() int {
return t.TestOptions.Concurrency
}
// Cleanup returns the cleanup
func (t *TestImpl) Cleanup() bool {
return t.TestOptions.Cleanup
}
// Logs returns the logs
func (t *TestImpl) Logs() bool {
return t.TestOptions.Logs
}
// Timeout returns the timeout
func (t *TestImpl) Timeout() int {
if !t.Cmd.Flags().Changed("timeout") {
return state.EmptyTimeout
}
return t.TestOptions.Timeout
}

View File

@ -16,47 +16,3 @@ type WriteValuesOptions struct {
func NewWriteValuesOptions() *WriteValuesOptions {
return &WriteValuesOptions{}
}
// WriteValuesImpl is impl for applyOptions
type WriteValuesImpl struct {
*GlobalImpl
*WriteValuesOptions
}
// NewWriteValuesImpl creates a new WriteValuesImpl
func NewWriteValuesImpl(g *GlobalImpl, b *WriteValuesOptions) *WriteValuesImpl {
return &WriteValuesImpl{
GlobalImpl: g,
WriteValuesOptions: b,
}
}
// Concurrency returns the concurrency
func (c *WriteValuesImpl) Concurrency() int {
return c.WriteValuesOptions.Concurrency
}
// Set returns the Set
func (c *WriteValuesImpl) Set() []string {
return c.WriteValuesOptions.Set
}
// Values returns the Values
func (c *WriteValuesImpl) Values() []string {
return c.WriteValuesOptions.Values
}
// SkipCleanUp returns the skip clean up
func (c *WriteValuesImpl) SkipCleanup() bool {
return false
}
// IncludeTransitiveNeeds returns the include transitive needs
func (c *WriteValuesImpl) IncludeTransitiveNeeds() bool {
return false
}
// OutputFileTemplate returns the output file template
func (c *WriteValuesImpl) OutputFileTemplate() string {
return c.WriteValuesOptions.OutputFileTemplate
}

View File

@ -0,0 +1,45 @@
package config
// WriteValuesImpl is impl for applyOptions
type WriteValuesImpl struct {
*GlobalImpl
*WriteValuesOptions
}
// NewWriteValuesImpl creates a new WriteValuesImpl
func NewWriteValuesImpl(g *GlobalImpl, b *WriteValuesOptions) *WriteValuesImpl {
return &WriteValuesImpl{
GlobalImpl: g,
WriteValuesOptions: b,
}
}
// Concurrency returns the concurrency
func (c *WriteValuesImpl) Concurrency() int {
return c.WriteValuesOptions.Concurrency
}
// Set returns the Set
func (c *WriteValuesImpl) Set() []string {
return c.WriteValuesOptions.Set
}
// Values returns the Values
func (c *WriteValuesImpl) Values() []string {
return c.WriteValuesOptions.Values
}
// SkipCleanUp returns the skip clean up
func (c *WriteValuesImpl) SkipCleanup() bool {
return false
}
// IncludeTransitiveNeeds returns the include transitive needs
func (c *WriteValuesImpl) IncludeTransitiveNeeds() bool {
return false
}
// OutputFileTemplate returns the output file template
func (c *WriteValuesImpl) OutputFileTemplate() string {
return c.WriteValuesOptions.OutputFileTemplate
}