tests: Add/Fix tests for new flag and fix docker wait, make fmt issue
Signed-off-by: yxxhero <aiopsclub@163.com>
This commit is contained in:
parent
1c59d0a539
commit
acaaa34d69
|
|
@ -9,6 +9,7 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/helmfile/helmfile/pkg/common"
|
||||
"github.com/helmfile/helmfile/pkg/exectest"
|
||||
"github.com/helmfile/helmfile/pkg/filesystem"
|
||||
"github.com/helmfile/helmfile/pkg/helmexec"
|
||||
|
|
@ -416,3 +417,138 @@ releases:
|
|||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestDiffWithIncludeCRDs(t *testing.T) {
|
||||
type fields struct {
|
||||
includeCRDs common.BoolFlag
|
||||
skipCRDs common.BoolFlag
|
||||
}
|
||||
|
||||
type testcase struct {
|
||||
fields fields
|
||||
ns string
|
||||
error string
|
||||
selectors []string
|
||||
diffed []exectest.Release
|
||||
}
|
||||
|
||||
check := func(t *testing.T, tc testcase) {
|
||||
t.Helper()
|
||||
|
||||
wantDiffs := tc.diffed
|
||||
|
||||
var helm = &exectest.Helm{
|
||||
FailOnUnexpectedList: true,
|
||||
FailOnUnexpectedDiff: true,
|
||||
DiffMutex: &sync.Mutex{},
|
||||
ChartsMutex: &sync.Mutex{},
|
||||
ReleasesMutex: &sync.Mutex{},
|
||||
Helm3: true,
|
||||
}
|
||||
|
||||
bs := runWithLogCapture(t, "debug", func(t *testing.T, logger *zap.SugaredLogger) {
|
||||
t.Helper()
|
||||
|
||||
valsRuntime, err := vals.New(vals.Options{CacheSize: 32})
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error creating vals runtime: %v", err)
|
||||
}
|
||||
|
||||
files := map[string]string{
|
||||
"/path/to/helmfile.yaml": `
|
||||
releases:
|
||||
- name: include-crds
|
||||
chart: incubator/raw
|
||||
namespace: default
|
||||
`,
|
||||
}
|
||||
|
||||
app := appWithFs(&App{
|
||||
OverrideHelmBinary: DefaultHelmBinary,
|
||||
fs: filesystem.DefaultFileSystem(),
|
||||
OverrideKubeContext: "default",
|
||||
Env: "default",
|
||||
Logger: logger,
|
||||
helms: map[helmKey]helmexec.Interface{
|
||||
createHelmKey("helm", "default"): helm,
|
||||
},
|
||||
valsRuntime: valsRuntime,
|
||||
}, files)
|
||||
|
||||
if tc.ns != "" {
|
||||
app.Namespace = tc.ns
|
||||
}
|
||||
|
||||
if tc.selectors != nil {
|
||||
app.Selectors = tc.selectors
|
||||
}
|
||||
|
||||
diffConfig := NewApplyConfigWithDefaults(&applyConfig{
|
||||
// if we check log output, concurrency must be 1. otherwise the test becomes non-deterministic.
|
||||
concurrency: 1,
|
||||
logger: logger,
|
||||
includeCRDs: tc.fields.includeCRDs,
|
||||
skipCRDs: tc.fields.skipCRDs,
|
||||
})
|
||||
diffErr := app.Diff(diffConfig)
|
||||
|
||||
var gotErr string
|
||||
if diffErr != nil {
|
||||
gotErr = diffErr.Error()
|
||||
}
|
||||
|
||||
if d := cmp.Diff(tc.error, gotErr); d != "" {
|
||||
t.Fatalf("unexpected error: want (-), got (+): %s", d)
|
||||
}
|
||||
|
||||
require.Equal(t, wantDiffs, helm.Diffed)
|
||||
})
|
||||
|
||||
testhelper.RequireLog(t, "app_diff_test", bs)
|
||||
}
|
||||
|
||||
t.Run("include-crds", func(t *testing.T) {
|
||||
includeCRDs := common.NewBoolFlag(false)
|
||||
includeCRDs.Set(true)
|
||||
|
||||
check(t, testcase{
|
||||
fields: fields{
|
||||
skipCRDs: common.NewBoolFlag(false),
|
||||
includeCRDs: includeCRDs,
|
||||
},
|
||||
diffed: []exectest.Release{
|
||||
{Name: "include-crds", Flags: []string{"--kube-context", "default", "--namespace", "default", "--reset-values", "--include-crds"}},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("include-or-skip-crds-unset", func(t *testing.T) {
|
||||
includeCRDs := common.NewBoolFlag(false)
|
||||
includeCRDs.Set(true)
|
||||
|
||||
check(t, testcase{
|
||||
fields: fields{
|
||||
skipCRDs: common.NewBoolFlag(false),
|
||||
includeCRDs: common.NewBoolFlag(false),
|
||||
},
|
||||
diffed: []exectest.Release{
|
||||
{Name: "include-crds", Flags: []string{"--kube-context", "default", "--namespace", "default", "--reset-values"}},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("skip-crds", func(t *testing.T) {
|
||||
skipCRDs := common.NewBoolFlag(false)
|
||||
skipCRDs.Set(true)
|
||||
|
||||
check(t, testcase{
|
||||
fields: fields{
|
||||
skipCRDs: skipCRDs,
|
||||
includeCRDs: common.NewBoolFlag(false),
|
||||
},
|
||||
diffed: []exectest.Release{
|
||||
{Name: "include-crds", Flags: []string{"--kube-context", "default", "--namespace", "default", "--reset-values", "--skip-crds"}},
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2172,11 +2172,18 @@ func (c configImpl) IncludeCRDs() bool {
|
|||
return c.includeCRDs.Value()
|
||||
}
|
||||
|
||||
// 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 (c configImpl) ShouldIncludeCRDs() bool {
|
||||
includeCRDsExplicit := c.includeCRDs.WasExplicitlySet() && c.includeCRDs.Value()
|
||||
skipCRDsExplicit := c.skipCRDs.WasExplicitlySet() && !c.skipCRDs.Value()
|
||||
skipCRDsNotProvided := !c.skipCRDs.WasExplicitlySet()
|
||||
|
||||
return includeCRDsExplicit || skipCRDsExplicit
|
||||
return includeCRDsExplicit && skipCRDsNotProvided
|
||||
}
|
||||
|
||||
func (c configImpl) SkipRefresh() bool {
|
||||
|
|
@ -2324,203 +2331,210 @@ func NewApplyConfigWithDefaults(existing *applyConfig) *applyConfig {
|
|||
return existing
|
||||
}
|
||||
|
||||
func (a applyConfig) Args() string {
|
||||
return a.args
|
||||
func (c applyConfig) Args() string {
|
||||
return c.args
|
||||
}
|
||||
|
||||
func (a applyConfig) Cascade() string {
|
||||
return a.cascade
|
||||
func (c applyConfig) Cascade() string {
|
||||
return c.cascade
|
||||
}
|
||||
|
||||
func (a applyConfig) Wait() bool {
|
||||
return a.wait
|
||||
func (c applyConfig) Wait() bool {
|
||||
return c.wait
|
||||
}
|
||||
|
||||
func (a applyConfig) WaitRetries() int {
|
||||
return a.waitRetries
|
||||
func (c applyConfig) WaitRetries() int {
|
||||
return c.waitRetries
|
||||
}
|
||||
|
||||
func (a applyConfig) WaitForJobs() bool {
|
||||
return a.waitForJobs
|
||||
func (c applyConfig) WaitForJobs() bool {
|
||||
return c.waitForJobs
|
||||
}
|
||||
|
||||
func (a applyConfig) Values() []string {
|
||||
return a.values
|
||||
func (c applyConfig) Values() []string {
|
||||
return c.values
|
||||
}
|
||||
|
||||
func (a applyConfig) Set() []string {
|
||||
return a.set
|
||||
func (c applyConfig) Set() []string {
|
||||
return c.set
|
||||
}
|
||||
|
||||
func (a applyConfig) Validate() bool {
|
||||
return a.validate
|
||||
func (c applyConfig) Validate() bool {
|
||||
return c.validate
|
||||
}
|
||||
|
||||
func (a applyConfig) SkipCleanup() bool {
|
||||
return a.skipCleanup
|
||||
func (c applyConfig) SkipCleanup() bool {
|
||||
return c.skipCleanup
|
||||
}
|
||||
|
||||
func (a applyConfig) SkipCRDs() bool {
|
||||
return a.skipCRDs.Value()
|
||||
func (c applyConfig) SkipCRDs() bool {
|
||||
return c.skipCRDs.Value()
|
||||
}
|
||||
|
||||
func (a applyConfig) IncludeCRDs() bool {
|
||||
return a.includeCRDs.Value()
|
||||
func (c applyConfig) IncludeCRDs() bool {
|
||||
return c.includeCRDs.Value()
|
||||
}
|
||||
|
||||
// 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 (c applyConfig) ShouldIncludeCRDs() bool {
|
||||
includeCRDsExplicit := c.includeCRDs.WasExplicitlySet() && c.includeCRDs.Value()
|
||||
skipCRDsExplicit := c.skipCRDs.WasExplicitlySet() && !c.skipCRDs.Value()
|
||||
skipCRDsNotProvided := !c.skipCRDs.WasExplicitlySet()
|
||||
|
||||
return includeCRDsExplicit || skipCRDsExplicit
|
||||
return includeCRDsExplicit && skipCRDsNotProvided
|
||||
}
|
||||
|
||||
func (a applyConfig) SkipDeps() bool {
|
||||
return a.skipDeps
|
||||
func (c applyConfig) SkipDeps() bool {
|
||||
return c.skipDeps
|
||||
}
|
||||
|
||||
func (a applyConfig) SkipRefresh() bool {
|
||||
return a.skipRefresh
|
||||
func (c applyConfig) SkipRefresh() bool {
|
||||
return c.skipRefresh
|
||||
}
|
||||
|
||||
func (a applyConfig) SkipNeeds() bool {
|
||||
return a.skipNeeds
|
||||
func (c applyConfig) SkipNeeds() bool {
|
||||
return c.skipNeeds
|
||||
}
|
||||
|
||||
func (a applyConfig) IncludeNeeds() bool {
|
||||
return a.includeNeeds || a.IncludeTransitiveNeeds()
|
||||
func (c applyConfig) IncludeNeeds() bool {
|
||||
return c.includeNeeds || c.IncludeTransitiveNeeds()
|
||||
}
|
||||
|
||||
func (a applyConfig) IncludeTransitiveNeeds() bool {
|
||||
return a.includeTransitiveNeeds
|
||||
func (c applyConfig) IncludeTransitiveNeeds() bool {
|
||||
return c.includeTransitiveNeeds
|
||||
}
|
||||
|
||||
func (a applyConfig) IncludeTests() bool {
|
||||
return a.includeTests
|
||||
func (c applyConfig) IncludeTests() bool {
|
||||
return c.includeTests
|
||||
}
|
||||
|
||||
func (a applyConfig) Suppress() []string {
|
||||
return a.suppress
|
||||
func (c applyConfig) Suppress() []string {
|
||||
return c.suppress
|
||||
}
|
||||
|
||||
func (a applyConfig) SuppressSecrets() bool {
|
||||
return a.suppressSecrets
|
||||
func (c applyConfig) SuppressSecrets() bool {
|
||||
return c.suppressSecrets
|
||||
}
|
||||
|
||||
func (a applyConfig) ShowSecrets() bool {
|
||||
return a.showSecrets
|
||||
func (c applyConfig) ShowSecrets() bool {
|
||||
return c.showSecrets
|
||||
}
|
||||
|
||||
func (a applyConfig) NoHooks() bool {
|
||||
return a.noHooks
|
||||
func (c applyConfig) NoHooks() bool {
|
||||
return c.noHooks
|
||||
}
|
||||
|
||||
func (a applyConfig) SuppressDiff() bool {
|
||||
return a.suppressDiff
|
||||
func (c applyConfig) SuppressDiff() bool {
|
||||
return c.suppressDiff
|
||||
}
|
||||
|
||||
func (a applyConfig) Color() bool {
|
||||
return a.color
|
||||
func (c applyConfig) Color() bool {
|
||||
return c.color
|
||||
}
|
||||
|
||||
func (a applyConfig) NoColor() bool {
|
||||
return a.noColor
|
||||
func (c applyConfig) NoColor() bool {
|
||||
return c.noColor
|
||||
}
|
||||
|
||||
func (a applyConfig) Context() int {
|
||||
return a.context
|
||||
func (c applyConfig) Context() int {
|
||||
return c.context
|
||||
}
|
||||
|
||||
func (a applyConfig) DiffOutput() string {
|
||||
return a.diffOutput
|
||||
func (c applyConfig) DiffOutput() string {
|
||||
return c.diffOutput
|
||||
}
|
||||
|
||||
func (a applyConfig) Concurrency() int {
|
||||
return a.concurrency
|
||||
func (c applyConfig) Concurrency() int {
|
||||
return c.concurrency
|
||||
}
|
||||
|
||||
func (a applyConfig) DetailedExitcode() bool {
|
||||
return a.detailedExitcode
|
||||
func (c applyConfig) DetailedExitcode() bool {
|
||||
return c.detailedExitcode
|
||||
}
|
||||
|
||||
func (a applyConfig) StripTrailingCR() bool {
|
||||
return a.stripTrailingCR
|
||||
func (c applyConfig) StripTrailingCR() bool {
|
||||
return c.stripTrailingCR
|
||||
}
|
||||
|
||||
func (a applyConfig) Interactive() bool {
|
||||
return a.interactive
|
||||
func (c applyConfig) Interactive() bool {
|
||||
return c.interactive
|
||||
}
|
||||
|
||||
func (a applyConfig) Logger() *zap.SugaredLogger {
|
||||
return a.logger
|
||||
func (c applyConfig) Logger() *zap.SugaredLogger {
|
||||
return c.logger
|
||||
}
|
||||
|
||||
func (a applyConfig) SkipDiffOnInstall() bool {
|
||||
return a.skipDiffOnInstall
|
||||
func (c applyConfig) SkipDiffOnInstall() bool {
|
||||
return c.skipDiffOnInstall
|
||||
}
|
||||
|
||||
func (a applyConfig) SyncArgs() string {
|
||||
return a.syncArgs
|
||||
func (c applyConfig) SyncArgs() string {
|
||||
return c.syncArgs
|
||||
}
|
||||
|
||||
func (a applyConfig) DiffArgs() string {
|
||||
return a.diffArgs
|
||||
func (c applyConfig) DiffArgs() string {
|
||||
return c.diffArgs
|
||||
}
|
||||
|
||||
// helmfile-template-only flags
|
||||
func (a applyConfig) SkipTests() bool {
|
||||
return a.skipTests
|
||||
func (c applyConfig) SkipTests() bool {
|
||||
return c.skipTests
|
||||
}
|
||||
|
||||
func (a applyConfig) OutputDir() string {
|
||||
return a.outputDir
|
||||
func (c applyConfig) OutputDir() string {
|
||||
return c.outputDir
|
||||
}
|
||||
func (a applyConfig) OutputDirTemplate() string {
|
||||
return a.outputDirTemplate
|
||||
func (c applyConfig) OutputDirTemplate() string {
|
||||
return c.outputDirTemplate
|
||||
}
|
||||
|
||||
func (a applyConfig) ReuseValues() bool {
|
||||
return a.reuseValues
|
||||
func (c applyConfig) ReuseValues() bool {
|
||||
return c.reuseValues
|
||||
}
|
||||
|
||||
func (a applyConfig) ResetValues() bool {
|
||||
return !a.reuseValues
|
||||
func (c applyConfig) ResetValues() bool {
|
||||
return !c.reuseValues
|
||||
}
|
||||
|
||||
func (a applyConfig) PostRenderer() string {
|
||||
return a.postRenderer
|
||||
func (c applyConfig) PostRenderer() string {
|
||||
return c.postRenderer
|
||||
}
|
||||
|
||||
func (a applyConfig) PostRendererArgs() []string {
|
||||
return a.postRendererArgs
|
||||
func (c applyConfig) PostRendererArgs() []string {
|
||||
return c.postRendererArgs
|
||||
}
|
||||
|
||||
func (a applyConfig) SuppressOutputLineRegex() []string {
|
||||
return a.suppressOutputLineRegex
|
||||
func (c applyConfig) SuppressOutputLineRegex() []string {
|
||||
return c.suppressOutputLineRegex
|
||||
}
|
||||
|
||||
func (a applyConfig) KubeVersion() string {
|
||||
return a.kubeVersion
|
||||
func (c applyConfig) KubeVersion() string {
|
||||
return c.kubeVersion
|
||||
}
|
||||
|
||||
func (a applyConfig) SkipSchemaValidation() bool {
|
||||
return a.skipSchemaValidation
|
||||
func (c applyConfig) SkipSchemaValidation() bool {
|
||||
return c.skipSchemaValidation
|
||||
}
|
||||
|
||||
func (a applyConfig) ShowOnly() []string {
|
||||
return a.showOnly
|
||||
func (c applyConfig) ShowOnly() []string {
|
||||
return c.showOnly
|
||||
}
|
||||
|
||||
func (a applyConfig) HideNotes() bool {
|
||||
return a.hideNotes
|
||||
func (c applyConfig) HideNotes() bool {
|
||||
return c.hideNotes
|
||||
}
|
||||
|
||||
func (a applyConfig) TakeOwnership() bool {
|
||||
return a.takeOwnership
|
||||
func (c applyConfig) TakeOwnership() bool {
|
||||
return c.takeOwnership
|
||||
}
|
||||
|
||||
func (a applyConfig) SyncReleaseLabels() bool {
|
||||
return a.syncReleaseLabels
|
||||
func (c applyConfig) SyncReleaseLabels() bool {
|
||||
return c.syncReleaseLabels
|
||||
}
|
||||
|
||||
type depsConfig struct {
|
||||
|
|
@ -2528,19 +2542,19 @@ type depsConfig struct {
|
|||
includeTransitiveNeeds bool
|
||||
}
|
||||
|
||||
func (d depsConfig) SkipRepos() bool {
|
||||
return d.skipRepos
|
||||
func (c depsConfig) SkipRepos() bool {
|
||||
return c.skipRepos
|
||||
}
|
||||
|
||||
func (d depsConfig) IncludeTransitiveNeeds() bool {
|
||||
return d.includeTransitiveNeeds
|
||||
func (c depsConfig) IncludeTransitiveNeeds() bool {
|
||||
return c.includeTransitiveNeeds
|
||||
}
|
||||
|
||||
func (d depsConfig) Args() string {
|
||||
func (c depsConfig) Args() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (d depsConfig) Concurrency() int {
|
||||
func (c depsConfig) Concurrency() int {
|
||||
return 2
|
||||
}
|
||||
|
||||
|
|
@ -4077,10 +4091,10 @@ releases:
|
|||
assert.NoError(t, err)
|
||||
|
||||
expected := "NAME NAMESPACE ENABLED INSTALLED LABELS CHART VERSION\n" +
|
||||
"myrelease1 testNamespace true false chart:mychart1,common:label,id:myrelease1,name:myrelease1,namespace:testNamespace mychart1\t \n" +
|
||||
"myrelease2 testNamespace false true chart:mychart1,common:label,name:myrelease2,namespace:testNamespace mychart1\t \n" +
|
||||
"myrelease3 testNamespace true true chart:mychart1,name:myrelease3,namespace:testNamespace mychart1\t \n" +
|
||||
"myrelease4 testNamespace true true chart:mychart1,id:myrelease1,name:myrelease4,namespace:testNamespace mychart1\t \n"
|
||||
"myrelease1 testNamespace true false chart:mychart1,common:label,id:myrelease1,name:myrelease1,namespace:testNamespace mychart1\t \n" +
|
||||
"myrelease2 testNamespace false true chart:mychart1,common:label,name:myrelease2,namespace:testNamespace mychart1\t \n" +
|
||||
"myrelease3 testNamespace true true chart:mychart1,name:myrelease3,namespace:testNamespace mychart1\t \n" +
|
||||
"myrelease4 testNamespace true true chart:mychart1,id:myrelease1,name:myrelease4,namespace:testNamespace mychart1\t \n"
|
||||
|
||||
assert.Equal(t, expected, out)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,151 +75,158 @@ func NewDiffConfigWithDefaults(existing *diffConfig) *diffConfig {
|
|||
return existing
|
||||
}
|
||||
|
||||
func (a diffConfig) Args() string {
|
||||
return a.args
|
||||
func (c diffConfig) Args() string {
|
||||
return c.args
|
||||
}
|
||||
|
||||
func (a diffConfig) DiffArgs() string {
|
||||
return a.diffArgs
|
||||
func (c diffConfig) DiffArgs() string {
|
||||
return c.diffArgs
|
||||
}
|
||||
|
||||
func (a diffConfig) Values() []string {
|
||||
return a.values
|
||||
func (c diffConfig) Values() []string {
|
||||
return c.values
|
||||
}
|
||||
|
||||
func (a diffConfig) Set() []string {
|
||||
return a.set
|
||||
func (c diffConfig) Set() []string {
|
||||
return c.set
|
||||
}
|
||||
|
||||
func (a diffConfig) Validate() bool {
|
||||
return a.validate
|
||||
func (c diffConfig) Validate() bool {
|
||||
return c.validate
|
||||
}
|
||||
|
||||
func (a diffConfig) SkipCRDs() bool {
|
||||
return a.skipCRDs.Value()
|
||||
func (c diffConfig) SkipCRDs() bool {
|
||||
return c.skipCRDs.Value()
|
||||
}
|
||||
|
||||
func (a diffConfig) IncludeCRDs() bool {
|
||||
return a.includeCRDs.Value()
|
||||
func (c diffConfig) IncludeCRDs() bool {
|
||||
return c.includeCRDs.Value()
|
||||
}
|
||||
|
||||
func (a diffConfig) ShouldIncludeCRDs() bool {
|
||||
includeCRDsExplicit := a.includeCRDs.WasExplicitlySet() && a.includeCRDs.Value()
|
||||
skipCRDsExplicit := a.skipCRDs.WasExplicitlySet() && !a.skipCRDs.Value()
|
||||
// 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 (c diffConfig) ShouldIncludeCRDs() bool {
|
||||
includeCRDsExplicit := c.includeCRDs.WasExplicitlySet() && c.includeCRDs.Value()
|
||||
skipCRDsNotProvided := !c.skipCRDs.WasExplicitlySet()
|
||||
|
||||
return includeCRDsExplicit || skipCRDsExplicit
|
||||
return includeCRDsExplicit && skipCRDsNotProvided
|
||||
}
|
||||
|
||||
func (a diffConfig) SkipDeps() bool {
|
||||
return a.skipDeps
|
||||
func (c diffConfig) SkipDeps() bool {
|
||||
return c.skipDeps
|
||||
}
|
||||
|
||||
func (a diffConfig) SkipRefresh() bool {
|
||||
return a.skipRefresh
|
||||
func (c diffConfig) SkipRefresh() bool {
|
||||
return c.skipRefresh
|
||||
}
|
||||
|
||||
func (a diffConfig) IncludeTests() bool {
|
||||
return a.includeTests
|
||||
func (c diffConfig) IncludeTests() bool {
|
||||
return c.includeTests
|
||||
}
|
||||
|
||||
func (a diffConfig) SkipNeeds() bool {
|
||||
return a.skipNeeds
|
||||
func (c diffConfig) SkipNeeds() bool {
|
||||
return c.skipNeeds
|
||||
}
|
||||
|
||||
func (a diffConfig) IncludeNeeds() bool {
|
||||
return a.includeNeeds || a.IncludeTransitiveNeeds()
|
||||
func (c diffConfig) IncludeNeeds() bool {
|
||||
return c.includeNeeds || c.IncludeTransitiveNeeds()
|
||||
}
|
||||
|
||||
func (a diffConfig) IncludeTransitiveNeeds() bool {
|
||||
return a.includeTransitiveNeeds
|
||||
func (c diffConfig) IncludeTransitiveNeeds() bool {
|
||||
return c.includeTransitiveNeeds
|
||||
}
|
||||
|
||||
func (a diffConfig) Suppress() []string {
|
||||
return a.suppress
|
||||
func (c diffConfig) Suppress() []string {
|
||||
return c.suppress
|
||||
}
|
||||
|
||||
func (a diffConfig) SuppressSecrets() bool {
|
||||
return a.suppressSecrets
|
||||
func (c diffConfig) SuppressSecrets() bool {
|
||||
return c.suppressSecrets
|
||||
}
|
||||
|
||||
func (a diffConfig) ShowSecrets() bool {
|
||||
return a.showSecrets
|
||||
func (c diffConfig) ShowSecrets() bool {
|
||||
return c.showSecrets
|
||||
}
|
||||
|
||||
func (a diffConfig) NoHooks() bool {
|
||||
return a.noHooks
|
||||
func (c diffConfig) NoHooks() bool {
|
||||
return c.noHooks
|
||||
}
|
||||
|
||||
func (a diffConfig) SuppressDiff() bool {
|
||||
return a.suppressDiff
|
||||
func (c diffConfig) SuppressDiff() bool {
|
||||
return c.suppressDiff
|
||||
}
|
||||
|
||||
func (a diffConfig) Color() bool {
|
||||
func (c diffConfig) Color() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (a diffConfig) NoColor() bool {
|
||||
return a.noColor
|
||||
func (c diffConfig) NoColor() bool {
|
||||
return c.noColor
|
||||
}
|
||||
|
||||
func (a diffConfig) Context() int {
|
||||
return a.context
|
||||
func (c diffConfig) Context() int {
|
||||
return c.context
|
||||
}
|
||||
|
||||
func (a diffConfig) DiffOutput() string {
|
||||
return a.diffOutput
|
||||
func (c diffConfig) DiffOutput() string {
|
||||
return c.diffOutput
|
||||
}
|
||||
|
||||
func (a diffConfig) Concurrency() int {
|
||||
return a.concurrency
|
||||
func (c diffConfig) Concurrency() int {
|
||||
return c.concurrency
|
||||
}
|
||||
|
||||
func (a diffConfig) DetailedExitcode() bool {
|
||||
return a.detailedExitcode
|
||||
func (c diffConfig) DetailedExitcode() bool {
|
||||
return c.detailedExitcode
|
||||
}
|
||||
|
||||
func (a diffConfig) StripTrailingCR() bool {
|
||||
return a.stripTrailingCR
|
||||
func (c diffConfig) StripTrailingCR() bool {
|
||||
return c.stripTrailingCR
|
||||
}
|
||||
|
||||
func (a diffConfig) Interactive() bool {
|
||||
return a.interactive
|
||||
func (c diffConfig) Interactive() bool {
|
||||
return c.interactive
|
||||
}
|
||||
|
||||
func (a diffConfig) SkipDiffOnInstall() bool {
|
||||
return a.skipDiffOnInstall
|
||||
func (c diffConfig) SkipDiffOnInstall() bool {
|
||||
return c.skipDiffOnInstall
|
||||
}
|
||||
|
||||
func (a diffConfig) Logger() *zap.SugaredLogger {
|
||||
return a.logger
|
||||
func (c diffConfig) Logger() *zap.SugaredLogger {
|
||||
return c.logger
|
||||
}
|
||||
|
||||
func (a diffConfig) RetainValuesFiles() bool {
|
||||
return a.retainValuesFiles
|
||||
func (c diffConfig) RetainValuesFiles() bool {
|
||||
return c.retainValuesFiles
|
||||
}
|
||||
|
||||
func (a diffConfig) ReuseValues() bool {
|
||||
return a.reuseValues
|
||||
func (c diffConfig) ReuseValues() bool {
|
||||
return c.reuseValues
|
||||
}
|
||||
|
||||
func (a diffConfig) ResetValues() bool {
|
||||
return !a.reuseValues
|
||||
func (c diffConfig) ResetValues() bool {
|
||||
return !c.reuseValues
|
||||
}
|
||||
|
||||
func (a diffConfig) PostRenderer() string {
|
||||
func (c diffConfig) PostRenderer() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (a diffConfig) PostRendererArgs() []string {
|
||||
func (c diffConfig) PostRendererArgs() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a diffConfig) SkipSchemaValidation() bool {
|
||||
return a.skipSchemaValidation
|
||||
func (c diffConfig) SkipSchemaValidation() bool {
|
||||
return c.skipSchemaValidation
|
||||
}
|
||||
|
||||
func (a diffConfig) SuppressOutputLineRegex() []string {
|
||||
return a.suppressOutputLineRegex
|
||||
func (c diffConfig) SuppressOutputLineRegex() []string {
|
||||
return c.suppressOutputLineRegex
|
||||
}
|
||||
|
||||
func TestDiff(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
merged environment: &{default map[] map[]}
|
||||
1 release(s) found in helmfile.yaml
|
||||
|
||||
processing 1 groups of releases in this order:
|
||||
GROUP RELEASES
|
||||
1 default/default/include-crds
|
||||
|
||||
processing releases in group 1/1: default/default/include-crds
|
||||
changing working directory back to "/path/to"
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
merged environment: &{default map[] map[]}
|
||||
1 release(s) found in helmfile.yaml
|
||||
|
||||
processing 1 groups of releases in this order:
|
||||
GROUP RELEASES
|
||||
1 default/default/include-crds
|
||||
|
||||
processing releases in group 1/1: default/default/include-crds
|
||||
changing working directory back to "/path/to"
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
processing file "helmfile.yaml" in directory "."
|
||||
changing working directory to "/path/to"
|
||||
merged environment: &{default map[] map[]}
|
||||
1 release(s) found in helmfile.yaml
|
||||
|
||||
processing 1 groups of releases in this order:
|
||||
GROUP RELEASES
|
||||
1 default/default/include-crds
|
||||
|
||||
processing releases in group 1/1: default/default/include-crds
|
||||
changing working directory back to "/path/to"
|
||||
|
|
@ -7,6 +7,7 @@ import (
|
|||
|
||||
"github.com/helmfile/helmfile/pkg/helmexec"
|
||||
"github.com/helmfile/helmfile/pkg/testutil"
|
||||
"github.com/helmfile/helmfile/pkg/version"
|
||||
)
|
||||
|
||||
func TestAppendWaitForJobsFlags(t *testing.T) {
|
||||
|
|
@ -432,6 +433,74 @@ func TestAppendTakeOwnershipFlags(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestAppendCRDFlags(t *testing.T) {
|
||||
type args struct {
|
||||
flags []string
|
||||
helm helmexec.Interface
|
||||
helmSpec HelmSpec
|
||||
opt *DiffOpts
|
||||
expected []string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
}{
|
||||
{
|
||||
name: "no include-crds nor skip-crds provided",
|
||||
args: args{
|
||||
flags: []string{},
|
||||
helm: testutil.NewVersionHelmExec(version.HelmRequiredVersion),
|
||||
opt: &DiffOpts{},
|
||||
expected: []string{},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "include-crds set but no skip-crds",
|
||||
args: args{
|
||||
flags: []string{},
|
||||
helm: testutil.NewVersionHelmExec(version.HelmRequiredVersion),
|
||||
opt: &DiffOpts{
|
||||
SkipCRDs: false,
|
||||
IncludeCRDs: true,
|
||||
},
|
||||
expected: []string{"--include-crds"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "include-crds and skip-crds set",
|
||||
args: args{
|
||||
flags: []string{},
|
||||
helm: testutil.NewVersionHelmExec(version.HelmRequiredVersion),
|
||||
opt: &DiffOpts{
|
||||
SkipCRDs: true,
|
||||
IncludeCRDs: true,
|
||||
},
|
||||
expected: []string{"--skip-crds"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "include-crds not set but skip-crds is",
|
||||
args: args{
|
||||
flags: []string{},
|
||||
helm: testutil.NewVersionHelmExec(version.HelmRequiredVersion),
|
||||
opt: &DiffOpts{
|
||||
SkipCRDs: true,
|
||||
IncludeCRDs: false,
|
||||
},
|
||||
expected: []string{"--skip-crds"},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
st := &HelmState{}
|
||||
st.HelmDefaults = tt.args.helmSpec
|
||||
got := st.appendCRDFlags(tt.args.flags, tt.args.opt.SkipCRDs, tt.args.opt.IncludeCRDs)
|
||||
require.Equalf(t, tt.args.expected, got, "appendCRDFlags() = %v, want %v", got, tt.args.expected)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormatLabels(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
|
|
|
|||
|
|
@ -3477,44 +3477,44 @@ func TestCommonDiffFlags(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestCommonDiffFlags_IncludeCRDs(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
inputOpts *DiffOpts
|
||||
expected []string
|
||||
}{
|
||||
{
|
||||
name: "Include CRDs flag is set to true",
|
||||
inputOpts: &DiffOpts{
|
||||
IncludeCRDs: true,
|
||||
},
|
||||
expected: []string{"--reset-values", "--include-crds"},
|
||||
},
|
||||
{
|
||||
name: "Include CRDs flag is set to false",
|
||||
inputOpts: &DiffOpts{
|
||||
IncludeCRDs: false,
|
||||
},
|
||||
expected: []string{"--reset-values"},
|
||||
},
|
||||
{
|
||||
name: "Include CRDs flag not set in options",
|
||||
inputOpts: &DiffOpts{},
|
||||
expected: []string{"--reset-values"},
|
||||
},
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
inputOpts *DiffOpts
|
||||
expected []string
|
||||
}{
|
||||
{
|
||||
name: "Include CRDs flag is set to true",
|
||||
inputOpts: &DiffOpts{
|
||||
IncludeCRDs: true,
|
||||
},
|
||||
expected: []string{"--reset-values", "--include-crds"},
|
||||
},
|
||||
{
|
||||
name: "Include CRDs flag is set to false",
|
||||
inputOpts: &DiffOpts{
|
||||
IncludeCRDs: false,
|
||||
},
|
||||
expected: []string{"--reset-values"},
|
||||
},
|
||||
{
|
||||
name: "Include CRDs flag not set in options",
|
||||
inputOpts: &DiffOpts{},
|
||||
expected: []string{"--reset-values"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
state := &HelmState{}
|
||||
result := state.commonDiffFlags(false, false, false, []string{}, false, false, false, test.inputOpts)
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
state := &HelmState{}
|
||||
result := state.commonDiffFlags(false, false, false, []string{}, false, false, false, test.inputOpts)
|
||||
|
||||
// Check if the result contains the expected flags
|
||||
if !reflect.DeepEqual(result, test.expected) {
|
||||
t.Errorf("commonDiffFlags() with IncludeCRDs=%v = %v, want %v",
|
||||
test.inputOpts.IncludeCRDs, result, test.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
// Check if the result contains the expected flags
|
||||
if !reflect.DeepEqual(result, test.expected) {
|
||||
t.Errorf("commonDiffFlags() with IncludeCRDs=%v = %v, want %v",
|
||||
test.inputOpts.IncludeCRDs, result, test.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendChartDownloadFlags(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
# Helmfile Test Command Package
|
||||
|
||||
## Overview
|
||||
|
||||
The `testcommand` package provides utilities for testing Helmfile commands in a controlled environment. This package simplifies the creation and configuration of command objects for testing purposes, allowing developers to verify command behavior without executing the full application.
|
||||
|
||||
## Components
|
||||
|
||||
### CommandTestHelper
|
||||
|
||||
The core structure that encapsulates the components needed for testing commands:
|
||||
|
||||
- `Cmd`: The Cobra command instance
|
||||
- `Registry`: Flag registry for managing command flags
|
||||
- `Options`: Command-specific options
|
||||
|
||||
### Available Test Commands
|
||||
|
||||
The package provides helper functions to create test instances of the following Helmfile commands:
|
||||
|
||||
- **TestDiffCmd()**: Creates a test instance of the `diff` command
|
||||
- **TestApplyCmd()**: Creates a test instance of the `apply` command
|
||||
- **TestTemplateCmd()**: Creates a test instance of the `template` command
|
||||
- **TestSyncCmd()**: Creates a test instance of the `sync` command
|
||||
|
||||
## Usage
|
||||
|
||||
```go
|
||||
import (
|
||||
"testing"
|
||||
"github.com/helmfile/helmfile/pkg/testcommand"
|
||||
)
|
||||
|
||||
func TestMyDiffCommand(t *testing.T) {
|
||||
// Create a test diff command
|
||||
helper := testcommand.TestDiffCmd()
|
||||
|
||||
// Access the command components
|
||||
cmd := helper.Cmd
|
||||
options := helper.Options.(*config.DiffOptions)
|
||||
|
||||
// Set up test flags
|
||||
cmd.Flags().Set("concurrency", "5")
|
||||
|
||||
// Test command behavior
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
## Implementation Details
|
||||
|
||||
Each test command function:
|
||||
|
||||
1. Creates an options factory for the specific command
|
||||
2. Instantiates the command options
|
||||
3. Gets the flag registry
|
||||
4. Creates a Cobra command instance
|
||||
5. Registers the appropriate flags
|
||||
6. Returns a helper with all components
|
||||
|
||||
For the `diff` command, flag values are automatically transferred to the options object.
|
||||
|
||||
## Notes
|
||||
|
||||
This package is intended for testing purposes only and should not be used in production code.
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
package testcmd
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/helmfile/helmfile/pkg/config"
|
||||
"github.com/helmfile/helmfile/pkg/factory"
|
||||
"github.com/helmfile/helmfile/pkg/flags"
|
||||
)
|
||||
|
||||
// CommandTestHelper provides utilities for testing commands
|
||||
type CommandTestHelper struct {
|
||||
Cmd *cobra.Command
|
||||
Registry flags.FlagRegistry
|
||||
Options config.Options
|
||||
}
|
||||
|
||||
// TestDiffCmd creates a diff command for testing and returns a helper with its components
|
||||
func TestDiffCmd() *CommandTestHelper {
|
||||
// Create command components
|
||||
optionsFactory := factory.NewDiffOptionsFactory()
|
||||
options := optionsFactory.CreateOptions().(*config.DiffOptions)
|
||||
registry := optionsFactory.GetFlagRegistry()
|
||||
|
||||
// Create command manually
|
||||
cmd := &cobra.Command{
|
||||
Use: "diff",
|
||||
Short: "Diff releases defined in state file",
|
||||
}
|
||||
|
||||
// Register flags
|
||||
registry.RegisterFlags(cmd)
|
||||
|
||||
// Transfer flags to options
|
||||
registry.TransferFlags(cmd, options)
|
||||
|
||||
return &CommandTestHelper{
|
||||
Cmd: cmd,
|
||||
Registry: registry,
|
||||
Options: options,
|
||||
}
|
||||
}
|
||||
|
||||
// TestApplyCmd creates an apply command for testing and returns a helper with its components
|
||||
func TestApplyCmd() *CommandTestHelper {
|
||||
// Create command components
|
||||
optionsFactory := factory.NewApplyOptionsFactory()
|
||||
options := optionsFactory.CreateOptions().(*config.ApplyOptions)
|
||||
registry := optionsFactory.GetFlagRegistry()
|
||||
|
||||
// Create command manually
|
||||
cmd := &cobra.Command{
|
||||
Use: "apply",
|
||||
Short: "Apply all resources from state file only when there are changes",
|
||||
}
|
||||
|
||||
// Register flags
|
||||
registry.RegisterFlags(cmd)
|
||||
|
||||
return &CommandTestHelper{
|
||||
Cmd: cmd,
|
||||
Registry: registry,
|
||||
Options: options,
|
||||
}
|
||||
}
|
||||
|
||||
// TestTemplateCmd creates a template command for testing and returns a helper with its components
|
||||
func TestTemplateCmd() *CommandTestHelper {
|
||||
// Create command components
|
||||
optionsFactory := factory.NewTemplateOptionsFactory()
|
||||
options := optionsFactory.CreateOptions().(*config.TemplateOptions)
|
||||
registry := optionsFactory.GetFlagRegistry()
|
||||
|
||||
// Create command manually
|
||||
cmd := &cobra.Command{
|
||||
Use: "template",
|
||||
Short: "Template releases defined in state file",
|
||||
}
|
||||
|
||||
// Register flags
|
||||
registry.RegisterFlags(cmd)
|
||||
|
||||
return &CommandTestHelper{
|
||||
Cmd: cmd,
|
||||
Registry: registry,
|
||||
Options: options,
|
||||
}
|
||||
}
|
||||
|
||||
// TestSyncCmd creates a sync command for testing and returns a helper with its components
|
||||
func TestSyncCmd() *CommandTestHelper {
|
||||
// Create command components
|
||||
optionsFactory := factory.NewSyncOptionsFactory()
|
||||
options := optionsFactory.CreateOptions().(*config.SyncOptions)
|
||||
registry := optionsFactory.GetFlagRegistry()
|
||||
|
||||
// Create command manually
|
||||
cmd := &cobra.Command{
|
||||
Use: "sync",
|
||||
Short: "Sync all resources from state file",
|
||||
}
|
||||
|
||||
// Register flags
|
||||
registry.RegisterFlags(cmd)
|
||||
|
||||
return &CommandTestHelper{
|
||||
Cmd: cmd,
|
||||
Registry: registry,
|
||||
Options: options,
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
# Helmfile Test Utilities
|
||||
|
||||
This package provides testing utilities for the Helmfile project, making it easier to write unit tests for Helm-related functionality.
|
||||
|
||||
## Overview
|
||||
|
||||
The `testutil` package contains:
|
||||
|
||||
1. Mock implementations for Helm execution
|
||||
2. Utility functions for testing
|
||||
|
||||
## Components
|
||||
|
||||
### Mock Helm Executors
|
||||
|
||||
The package provides mock implementations of Helm executors that can be used in tests:
|
||||
|
||||
- `V3HelmExec`: A mock that can be configured to simulate Helm 3 behavior
|
||||
- `VersionHelmExec`: A mock that can be configured with a specific Helm version
|
||||
|
||||
```go
|
||||
// Create a mock for Helm 3
|
||||
helmExec := testutil.NewV3HelmExec(true)
|
||||
|
||||
// Create a mock for a specific Helm version
|
||||
versionExec := testutil.NewVersionHelmExec("3.8.0")
|
||||
```
|
||||
|
||||
These mocks implement the Helm executor interface but will panic if any unexpected methods are called, making them useful for strict testing scenarios.
|
||||
|
||||
### Utility Functions
|
||||
|
||||
#### CaptureStdout
|
||||
|
||||
Captures stdout output during the execution of a function:
|
||||
|
||||
```go
|
||||
output, err := testutil.CaptureStdout(func() {
|
||||
fmt.Println("Hello, world!")
|
||||
})
|
||||
// output will contain "Hello, world!\n"
|
||||
```
|
||||
|
||||
This is useful for testing functions that write to stdout.
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Testing with V3HelmExec
|
||||
|
||||
```go
|
||||
func TestMyFunction(t *testing.T) {
|
||||
// Create a mock Helm executor configured as Helm 3
|
||||
helmExec := testutil.NewV3HelmExec(true)
|
||||
|
||||
// Use in your test
|
||||
result := myFunctionThatChecksHelmVersion(helmExec)
|
||||
|
||||
// Assert that the result is as expected for Helm 3
|
||||
assert.True(t, result)
|
||||
}
|
||||
```
|
||||
|
||||
### Testing with VersionHelmExec
|
||||
|
||||
```go
|
||||
func TestVersionCompatibility(t *testing.T) {
|
||||
// Create a mock with specific version
|
||||
helmExec := testutil.NewVersionHelmExec("3.7.1")
|
||||
|
||||
// Test version comparison
|
||||
assert.True(t, helmExec.IsVersionAtLeast("3.7.0"))
|
||||
assert.False(t, helmExec.IsVersionAtLeast("3.8.0"))
|
||||
}
|
||||
```
|
||||
|
||||
### Capturing Output
|
||||
|
||||
```go
|
||||
func TestOutputFunction(t *testing.T) {
|
||||
output, err := testutil.CaptureStdout(func() {
|
||||
MyFunctionThatPrintsOutput()
|
||||
})
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Contains(t, output, "Expected output")
|
||||
}
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
When adding new test utilities, please ensure they are well-documented and include appropriate tests.
|
||||
Loading…
Reference in New Issue