mirror of
https://github.com/helmfile/helmfile.git
synced 2026-10-04 20:31:29 +02:00
* feat: parallel kubedog tracking with progress printer and safety valves Rework kubedog integration so resource tracking runs in parallel with helm upgrade/install, giving live progress output and recovering from known helm/kubedog wedge conditions. Core: - kubedogTrackingHandle runs tracking in a background goroutine alongside the helm subprocess (startBackgroundKubedogTracking); helm output is buffered and replayed as a single block so it no longer interleaves with progress ticks. - Capture UID+generation baselines before handing off to helm so each tracker waits until the resource actually changes (freshness gate). Progress printer (pkg/kubedog/printer.go): - Styled, auto-sized progress table with a heartbeat flusher, child (pod) status roll-up, pre-ready pod-phase handling, multi-namespace support, and optional color. PreviewBreakdown summarizes kept/filtered resources. Safety valves (verify cluster state via the live API): - Tracker-race valve (always on): when helm succeeds but a dyntracker goroutine is wedged, poll the API and cancel the tracker so wait() returns success instead of blocking until --track-timeout. - Helm-stuck killer (opt-in via helmStuckGrace): if the cluster stays converged while helm v4's hook waiter is wedged, SIGINT the helm subprocess to recover. - Failure watchdog (pkg/kubedog/watchdog.go): surface failing pods that never made it into dyntracker's resource graph. Options: trackFailedLogs, helmStuckGrace, trackTimeout, color (Color/NoColor), and resource filtering (trackKinds/skipKinds/ trackResources). PersistentVolumeClaim support in resource classification. Signed-off-by: Roman Mykhailiuk <romanm@cybellum.com> * test: add unit tests for kubedog tracking Cover the progress printer, resource classification, the failure watchdog, helm-output trimming/dedup, the release hard-timeout helper, and the color/track option plumbing. Signed-off-by: Roman Mykhailiuk <romanm@cybellum.com> * test: update golden logs, e2e snapshots, and values-id fixtures Refresh pkg/app testapply/testdestroy golden logs, e2e template snapshots, and the TestGenerateID values-id golden hashes for the new kubedog progress output and the merged release struct layout. Signed-off-by: Roman Mykhailiuk <romanm@cybellum.com> * refactor: remove dead kubedog display code and dedupe tracker setup Deep-review pass on the parallel kubedog tracking changes: - Remove pkg/kubedog/display.go (308 lines) and display_test.go (453 lines). These rendered progress for the legacy per-kind trackers that this PR replaces; in the merged tree every function is unreferenced outside its own tests. The new progressPrinter (printer.go) supersedes them. TestMain (color.ForceColor for deterministic ANSI in tests) is preserved in a new main_test.go. - Dedupe trackWithKubedog: the post-helm fallback rebuilt the exact same tracker options as buildReleaseTracker. Reuse buildReleaseTracker instead, dropping ~40 lines of duplicated timeout/log/filter/tracker construction. No behavior change; build, go vet, golangci-lint, and the kubedog/state unit tests all pass. Signed-off-by: yxxhero <aiopsclub@163.com> * fix: stop waitForFreshness busy-looping the API after helm finishes Once upstreamDoneCh closes it is always ready, so the select in waitForFreshness stopped blocking on the ticker and re-ran probe() (a live GET) as fast as the round-trip allowed for the whole 3s grace window — hammering the API server once per tracked resource. Track a local view of the channel and nil it out on first delivery so the first hit records the timestamp (one fast retry, as intended) and all subsequent polls are ticker-throttled. Functional behavior is unchanged: return nil when fresh, errUpstreamDoneNoChange after grace. Signed-off-by: yxxhero <aiopsclub@163.com> * test: drop trailing blank line from helm4 OCI pull snapshots The trailing-newline trim in helmexec.info() removes the blank line helm prints after the OCI chart "Digest:" line. The helm3 (output.yaml) snapshots never captured that line, but the helm4 (output-helm4.yaml) snapshots for oci_chart_pull{,_direct,_once,_once2} and issue_473_oci_chart_url_fetch still expected it, so they failed under helm 4. Remove the blank line so the snapshots match the trimmed output. Signed-off-by: yxxhero <aiopsclub@163.com> * test: refresh diff-args integration goldens for styled release headers DisplayAffectedReleases now emits a styled "========== Updated Releases ==========" header (matching the app/e2e goldens already updated by this PR) and helmexec.info() trims the trailing blank after helm's install status. Update the diff-args apply-stderr{,-helm4} and apply-live- stderr{,-helm4} goldens accordingly so they match the actual stderr. Signed-off-by: yxxhero <aiopsclub@163.com> * test: drop trimmed blank line from v1-subhelmfile template golden The trailing-newline trim in helmexec.info() removes the blank line helm prints after '"incubator" has been added to your repositories'. Update the v1-subhelmfile-multi-bases-with-array-values result and result-live goldens so the template stdout comparison matches. Signed-off-by: yxxhero <aiopsclub@163.com> --------- Signed-off-by: Roman Mykhailiuk <romanm@cybellum.com> Signed-off-by: yxxhero <aiopsclub@163.com> Co-authored-by: Roman Mykhailiuk <romanm@cybellum.com>
359 lines
5.6 KiB
Go
359 lines
5.6 KiB
Go
package app
|
|
|
|
import "go.uber.org/zap"
|
|
|
|
type ConfigProvider interface {
|
|
Args() string
|
|
HelmBinary() string
|
|
KustomizeBinary() string
|
|
EnableLiveOutput() bool
|
|
StripArgsValuesOnExitError() bool
|
|
DisableForceUpdate() bool
|
|
EnforcePluginVerification() bool
|
|
HelmOCIPlainHTTP() bool
|
|
SkipDeps() bool
|
|
SkipRefresh() bool
|
|
SequentialHelmfiles() bool
|
|
|
|
FileOrDir() string
|
|
KubeContext() string
|
|
Namespace() string
|
|
Chart() string
|
|
Selectors() []string
|
|
StateValuesSet() map[string]any
|
|
StateValuesFiles() []string
|
|
Kubeconfig() string
|
|
Env() string
|
|
|
|
loggingConfig
|
|
}
|
|
|
|
type DepsConfigProvider interface {
|
|
Args() string
|
|
SkipRepos() bool
|
|
IncludeTransitiveNeeds() bool
|
|
|
|
concurrencyConfig
|
|
}
|
|
|
|
type ReposConfigProvider interface {
|
|
Args() string
|
|
IncludeTransitiveNeeds() bool
|
|
}
|
|
|
|
type ApplyConfigProvider interface {
|
|
Args() string
|
|
PostRenderer() string
|
|
PostRendererArgs() []string
|
|
SkipSchemaValidation() bool
|
|
Cascade() string
|
|
HideNotes() bool
|
|
TakeOwnership() bool
|
|
ServerSide() string
|
|
SuppressOutputLineRegex() []string
|
|
|
|
Values() []string
|
|
Set() []string
|
|
SkipCRDs() bool
|
|
SkipDeps() bool
|
|
SkipRefresh() bool
|
|
Wait() bool
|
|
WaitRetries() int
|
|
WaitForJobs() bool
|
|
Timeout() int
|
|
|
|
IncludeTests() bool
|
|
|
|
Suppress() []string
|
|
SuppressSecrets() bool
|
|
ShowSecrets() bool
|
|
NoHooks() bool
|
|
SuppressDiff() bool
|
|
|
|
DetailedExitcode() bool
|
|
StripTrailingCR() bool
|
|
|
|
Color() bool
|
|
NoColor() bool
|
|
Context() int
|
|
DiffOutput() string
|
|
|
|
Validate() bool
|
|
SkipCleanup() bool
|
|
SkipDiffOnInstall() bool
|
|
|
|
DiffArgs() string
|
|
SyncArgs() string
|
|
|
|
SyncReleaseLabels() bool
|
|
|
|
DAGConfig
|
|
|
|
TrackMode() string
|
|
TrackTimeout() int
|
|
TrackLogs() bool
|
|
TrackFailedLogs() bool
|
|
HelmStuckGrace() int
|
|
TrackFailOnError() bool
|
|
|
|
Description() string
|
|
|
|
concurrencyConfig
|
|
interactive
|
|
loggingConfig
|
|
valuesControlMode
|
|
}
|
|
|
|
type SyncConfigProvider interface {
|
|
Args() string
|
|
PostRenderer() string
|
|
SkipSchemaValidation() bool
|
|
PostRendererArgs() []string
|
|
HideNotes() bool
|
|
TakeOwnership() bool
|
|
ServerSide() string
|
|
Cascade() string
|
|
|
|
Values() []string
|
|
Set() []string
|
|
SkipCRDs() bool
|
|
SkipDeps() bool
|
|
SkipRefresh() bool
|
|
Wait() bool
|
|
WaitRetries() int
|
|
WaitForJobs() bool
|
|
Timeout() int
|
|
SyncArgs() string
|
|
|
|
Validate() bool
|
|
|
|
SkipNeeds() bool
|
|
IncludeNeeds() bool
|
|
IncludeTransitiveNeeds() bool
|
|
|
|
SyncReleaseLabels() bool
|
|
TrackMode() string
|
|
TrackTimeout() int
|
|
TrackLogs() bool
|
|
TrackFailedLogs() bool
|
|
HelmStuckGrace() int
|
|
TrackFailOnError() bool
|
|
|
|
Color() bool
|
|
NoColor() bool
|
|
|
|
Description() string
|
|
|
|
DAGConfig
|
|
|
|
concurrencyConfig
|
|
interactive
|
|
loggingConfig
|
|
valuesControlMode
|
|
}
|
|
|
|
type DiffConfigProvider interface {
|
|
Args() string
|
|
PostRenderer() string
|
|
PostRendererArgs() []string
|
|
SkipSchemaValidation() bool
|
|
SuppressOutputLineRegex() []string
|
|
|
|
Values() []string
|
|
Set() []string
|
|
Validate() bool
|
|
SkipCRDs() bool
|
|
SkipDeps() bool
|
|
SkipRefresh() bool
|
|
|
|
IncludeTests() bool
|
|
|
|
Suppress() []string
|
|
SuppressSecrets() bool
|
|
ShowSecrets() bool
|
|
NoHooks() bool
|
|
SuppressDiff() bool
|
|
SkipDiffOnInstall() bool
|
|
DiffArgs() string
|
|
|
|
DAGConfig
|
|
|
|
DetailedExitcode() bool
|
|
StripTrailingCR() bool
|
|
Color() bool
|
|
NoColor() bool
|
|
Context() int
|
|
DiffOutput() string
|
|
TakeOwnership() bool
|
|
ServerSide() string
|
|
|
|
concurrencyConfig
|
|
valuesControlMode
|
|
}
|
|
|
|
type DestroyConfigProvider interface {
|
|
Args() string
|
|
Cascade() string
|
|
|
|
SkipDeps() bool
|
|
SkipRefresh() bool
|
|
SkipCharts() bool
|
|
DeleteWait() bool
|
|
DeleteTimeout() int
|
|
NoColor() bool
|
|
|
|
interactive
|
|
loggingConfig
|
|
concurrencyConfig
|
|
}
|
|
|
|
type TestConfigProvider interface {
|
|
Args() string
|
|
|
|
SkipDeps() bool
|
|
SkipRefresh() bool
|
|
Timeout() int
|
|
Cleanup() bool
|
|
Logs() bool
|
|
|
|
concurrencyConfig
|
|
}
|
|
|
|
type LintConfigProvider interface {
|
|
Args() string
|
|
|
|
Values() []string
|
|
Set() []string
|
|
SkipDeps() bool
|
|
SkipRefresh() bool
|
|
SkipCleanup() bool
|
|
|
|
DAGConfig
|
|
|
|
concurrencyConfig
|
|
}
|
|
|
|
type UnittestConfigProvider interface {
|
|
Args() string
|
|
|
|
Values() []string
|
|
Set() []string
|
|
FailFast() bool
|
|
Color() bool
|
|
DebugPlugin() bool
|
|
SkipDeps() bool
|
|
SkipRefresh() bool
|
|
SkipCleanup() bool
|
|
|
|
DAGConfig
|
|
|
|
concurrencyConfig
|
|
}
|
|
|
|
type FetchConfigProvider interface {
|
|
SkipDeps() bool
|
|
SkipRefresh() bool
|
|
OutputDir() string
|
|
OutputDirTemplate() string
|
|
WriteOutput() bool
|
|
|
|
concurrencyConfig
|
|
}
|
|
|
|
type TemplateConfigProvider interface {
|
|
Args() string
|
|
PostRenderer() string
|
|
PostRendererArgs() []string
|
|
SkipSchemaValidation() bool
|
|
|
|
Values() []string
|
|
Set() []string
|
|
OutputDirTemplate() string
|
|
Validate() bool
|
|
SkipDeps() bool
|
|
SkipRefresh() bool
|
|
SkipCleanup() bool
|
|
SkipTests() bool
|
|
OutputDir() string
|
|
IncludeCRDs() bool
|
|
NoHooks() bool
|
|
KubeVersion() string
|
|
ShowOnly() []string
|
|
|
|
DAGConfig
|
|
|
|
concurrencyConfig
|
|
}
|
|
|
|
type DAGConfig interface {
|
|
SkipNeeds() bool
|
|
IncludeNeeds() bool
|
|
IncludeTransitiveNeeds() bool
|
|
EnforceNeedsAreInstalled() bool
|
|
}
|
|
|
|
type WriteValuesConfigProvider interface {
|
|
Values() []string
|
|
Set() []string
|
|
OutputFileTemplate() string
|
|
SkipDeps() bool
|
|
SkipRefresh() bool
|
|
SkipCleanup() bool
|
|
IncludeTransitiveNeeds() bool
|
|
|
|
concurrencyConfig
|
|
}
|
|
|
|
type StatusesConfigProvider interface {
|
|
Args() string
|
|
|
|
concurrencyConfig
|
|
}
|
|
|
|
type StateConfigProvider interface {
|
|
EmbedValues() bool
|
|
}
|
|
|
|
type DAGConfigProvider any
|
|
|
|
type concurrencyConfig interface {
|
|
Concurrency() int
|
|
}
|
|
|
|
type loggingConfig interface {
|
|
Logger() *zap.SugaredLogger
|
|
}
|
|
|
|
type interactive interface {
|
|
Interactive() bool
|
|
}
|
|
|
|
type ListConfigProvider interface {
|
|
Output() string
|
|
SkipCharts() bool
|
|
}
|
|
|
|
type CacheConfigProvider any
|
|
|
|
type InitConfigProvider interface {
|
|
Force() bool
|
|
}
|
|
|
|
type CreateConfigProvider interface {
|
|
Name() string
|
|
OutputDir() string
|
|
Force() bool
|
|
|
|
loggingConfig
|
|
}
|
|
|
|
type PrintEnvConfigProvider interface {
|
|
Output() string
|
|
}
|
|
|
|
// reset/reuse values helm cli flags handling for apply/sync/diff
|
|
type valuesControlMode interface {
|
|
ReuseValues() bool
|
|
ResetValues() bool
|
|
}
|