Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 8 additions & 17 deletions cmd/addon-operator/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
"github.com/flant/addon-operator/pkg/metrics"
"github.com/flant/addon-operator/pkg/utils/stdliblogtolog"
"github.com/flant/kube-client/klogtolog"
shapp "github.com/flant/shell-operator/pkg/app"
"github.com/flant/shell-operator/pkg/debug"
shmetrics "github.com/flant/shell-operator/pkg/metrics"
utils_signal "github.com/flant/shell-operator/pkg/utils/signal"
Expand Down Expand Up @@ -70,23 +69,15 @@ func main() {
app.BindFlags(cfg, rootCmd, startCmd)
rootCmd.AddCommand(startCmd)

// Propagate addon-operator's cfg.Debug.UnixSocket into shell-operator's
// package-level globals before registering shell-operator's debug
// sub-commands (queue, config, hook, raw). Those sub-commands bind their
// --debug-unix-socket flag to shapp.DebugUnixSocket and dial it via
// debug.DefaultClient(); without this bridge they would default to
// Propagate addon-operator's debug socket path into shell-operator's
// package-level DefaultSocketPath before registering shell-operator's
// debug sub-commands (queue, config, hook, raw — wired via
// debug.DefineDebugCommands). Those sub-commands bind their
// --debug-unix-socket flag to debug.DefaultSocketPath and dial it via
// debug.DefaultClient(); without this assignment they would default to
// /var/run/shell-operator/debug.socket while the addon-operator debug
// server actually listens on cfg.Debug.UnixSocket. This is the modern
// equivalent of the `shapp.DebugUnixSocket = DefaultDebugUnixSocket` line
// addon-operator v1.20.9 carried under a "TODO: rewrite shapp global
// variables to the addon-operator one" comment.
//
// NewAddonOperator runs an equivalent shapp.ApplyConfig call so library
// consumers (who skip this main.go path) also get the propagation. This
// one stays because shell-operator's debug.DefineDebugCommands binds
// flag defaults BEFORE rootCmd.Execute, i.e. before any start RunE
// invokes NewAddonOperator.
shapp.ApplyConfig(addon_operator.ShellOperatorConfig(cfg))
// server actually listens on cfg.Debug.UnixSocket.
debug.DefaultSocketPath = cfg.Debug.UnixSocket

debug.DefineDebugCommands(rootCmd)
app.DefineDebugCommands(rootCmd)
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ require (
github.com/dominikbraun/graph v0.23.0
github.com/ettle/strcase v0.2.0
github.com/flant/kube-client v1.7.0
github.com/flant/shell-operator v1.17.5
github.com/flant/shell-operator v1.17.5-0.20260529104211-591203012463
github.com/go-chi/chi/v5 v5.3.0
github.com/go-openapi/loads v0.23.1
github.com/go-openapi/spec v0.22.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,8 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/flant/kube-client v1.7.0 h1:+B0yZfQuVKnsyf51+pQckxeKA7SR9YOdhyR3GeQi57s=
github.com/flant/kube-client v1.7.0/go.mod h1:16bcsXO8C7i0rtKmrpbgmJpnQgqlUzfIOZs521WmKcE=
github.com/flant/shell-operator v1.17.5 h1:Zqi/ufpDVBtAL/d+h0OLbfwa6axp56SKJZzIU3Admjw=
github.com/flant/shell-operator v1.17.5/go.mod h1:0StUzFiEEqY60xEgIj7symIT8ePVFQKqnIy/vF0Mt4g=
github.com/flant/shell-operator v1.17.5-0.20260529104211-591203012463 h1:OUPwtZm8ihMkP3oj23vEcZz2sGwkhpJdJ6q9hL0sE2o=
github.com/flant/shell-operator v1.17.5-0.20260529104211-591203012463/go.mod h1:62zplAqBrOlrg0dhkJfR1qo1Eeu6rpUMO6YnOyS8ooo=
github.com/flopp/go-findfont v0.1.0 h1:lPn0BymDUtJo+ZkV01VS3661HL6F4qFlkhcJN55u6mU=
github.com/flopp/go-findfont v0.1.0/go.mod h1:wKKxRDjD024Rh7VMwoU90i6ikQRCr+JTHB5n4Ejkqvw=
github.com/fluxcd/flagger v1.36.1 h1:X2PumtNwZz9YSGaOtZLFm2zAKLgHhFkbNv8beg7ifyc=
Expand Down
47 changes: 24 additions & 23 deletions pkg/addon-operator/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/deckhouse/deckhouse/pkg/log"

"github.com/flant/addon-operator/pkg/app"
"github.com/flant/shell-operator/pkg/debug"
shapp "github.com/flant/shell-operator/pkg/app"
)

Expand Down Expand Up @@ -137,49 +138,49 @@ func TestShellOperatorConfig_NilIn(t *testing.T) {
}
}

// TestShellOperatorConfig_DrivesShappDebugUnixSocket pins the contract that
// TestShellOperatorConfig_DrivesDebugDefaultSocketPath pins the contract that
// makes addon-operator's debug socket reach shell-operator's package-level
// global. cmd/addon-operator/main.go relies on this chain
// (ShellOperatorConfig → shapp.ApplyConfig) to give shell-operator's debug
// sub-commands (queue, config, hook, raw — wired via
// debug.DefineDebugCommands) the correct --debug-unix-socket default and
// DefaultClient() socket path.
func TestShellOperatorConfig_DrivesShappDebugUnixSocket(t *testing.T) {
prev := shapp.DebugUnixSocket
t.Cleanup(func() { shapp.DebugUnixSocket = prev })
// DefaultSocketPath. cmd/addon-operator/main.go and NewAddonOperator both
// assign cfg.Debug.UnixSocket to debug.DefaultSocketPath so that
// debug.DefineDebugCommands sub-commands (queue, config, hook, raw) dial the
// correct socket via debug.DefaultClient().
func TestShellOperatorConfig_DrivesDebugDefaultSocketPath(t *testing.T) {
prev := debug.DefaultSocketPath
t.Cleanup(func() { debug.DefaultSocketPath = prev })

shapp.DebugUnixSocket = "/stale/shell-op/default.socket"
debug.DefaultSocketPath = "/stale/shell-op/default.socket"

cfg := app.NewConfig()
cfg.Debug.UnixSocket = "/run/addon-operator/debug.socket"

shapp.ApplyConfig(ShellOperatorConfig(cfg))
// Simulate what main.go and NewAddonOperator do.
debug.DefaultSocketPath = cfg.Debug.UnixSocket

if shapp.DebugUnixSocket != "/run/addon-operator/debug.socket" {
t.Errorf("shapp.DebugUnixSocket: got %q, want %q (must be driven by addon-operator cfg)",
shapp.DebugUnixSocket, "/run/addon-operator/debug.socket")
if debug.DefaultSocketPath != "/run/addon-operator/debug.socket" {
t.Errorf("debug.DefaultSocketPath: got %q, want %q (must be driven by addon-operator cfg)",
debug.DefaultSocketPath, "/run/addon-operator/debug.socket")
}
}

// TestNewAddonOperator_SyncsShappDebugUnixSocketFromConfig pins the
// TestNewAddonOperator_SyncsDebugDefaultSocketPathFromConfig pins the
// library-mode contract: a consumer that hands NewAddonOperator its own
// *app.Config via WithConfig — and therefore never runs
// cmd/addon-operator/main.go — must still get shell-operator's
// package-level DebugUnixSocket aligned with cfg.Debug.UnixSocket.
// package-level DefaultSocketPath aligned with cfg.Debug.UnixSocket.
//
// This is what lets a library consumer expose, for example,
// shell-operator's debug.DefineDebugCommands on its own root command and
// have those sub-commands dial the addon-operator socket instead of
// /var/run/shell-operator/debug.socket.
func TestNewAddonOperator_SyncsShappDebugUnixSocketFromConfig(t *testing.T) {
prevShapp := shapp.DebugUnixSocket
func TestNewAddonOperator_SyncsDebugDefaultSocketPathFromConfig(t *testing.T) {
prevDebug := debug.DefaultSocketPath
prevApp := app.DebugUnixSocket
t.Cleanup(func() {
shapp.DebugUnixSocket = prevShapp
debug.DefaultSocketPath = prevDebug
app.DebugUnixSocket = prevApp
})

shapp.DebugUnixSocket = "/stale/shell-op/default.socket"
debug.DefaultSocketPath = "/stale/shell-op/default.socket"
app.DebugUnixSocket = "/stale/addon-op/default.socket"

cfg := app.NewConfig()
Expand All @@ -194,9 +195,9 @@ func TestNewAddonOperator_SyncsShappDebugUnixSocketFromConfig(t *testing.T) {
t.Errorf("app.DebugUnixSocket: got %q, want %q (library consumer's cfg must reach addon-operator global)",
app.DebugUnixSocket, "/lib-consumer/debug.socket")
}
if shapp.DebugUnixSocket != "/lib-consumer/debug.socket" {
t.Errorf("shapp.DebugUnixSocket: got %q, want %q (library consumer's cfg must reach shell-operator global too)",
shapp.DebugUnixSocket, "/lib-consumer/debug.socket")
if debug.DefaultSocketPath != "/lib-consumer/debug.socket" {
t.Errorf("debug.DefaultSocketPath: got %q, want %q (library consumer's cfg must reach shell-operator global too)",
debug.DefaultSocketPath, "/lib-consumer/debug.socket")
}
}

Expand Down
37 changes: 20 additions & 17 deletions pkg/addon-operator/operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,10 +157,9 @@ func resolveConfig(cfg *app.Config, logger *log.Logger) *app.Config {
// two config shapes meet, so the addon-operator config remains the only
// source of truth that drives shell-operator too.
//
// Exported so binaries / library consumers can hand the projection to
// shapp.ApplyConfig before registering shell-operator's debug sub-commands
// (debug.DefineDebugCommands), making the legacy shapp.DebugUnixSocket global
// observe the addon-operator socket path.
// Used by AddonOperator.AssembleCommonOperatorFromConfig to configure the
// embedded shell-operator engine with the right listen address, kube client
// settings, metric prefix, etc.
//
// Mappings:
// - App.HooksDir ← App.GlobalHooksDir (addon-operator's global
Expand Down Expand Up @@ -244,17 +243,11 @@ func NewAddonOperator(ctx context.Context, metricsStorage, hookMetricStorage met
// bridges the typed Config to the legacy globals.
app.ApplyConfig(ao.config)

// Library consumers reach this constructor with their own *app.Config
// (via WithConfig) and never run cmd/addon-operator/main.go, so the
// shapp.ApplyConfig bridge in main.go does not fire for them. Replicate
// it here so that any shell-operator code path that still reads its
// package-level globals (e.g. shapp.DebugUnixSocket consulted by
// shell-operator's debug.DefineDebugCommands or debug.DefaultClient())
// observes the addon-operator-supplied values, not shell-operator's
// hardcoded defaults. The function is nil-safe and idempotent, so it is
// also harmless to call from the binary path where main.go already
// invoked it once.
shapp.ApplyConfig(ShellOperatorConfig(ao.config))
// Propagate the addon-operator debug socket path to shell-operator's
// package-level DefaultSocketPath so that debug.DefineDebugCommands
// (queued by main.go before rootCmd.Execute) connects to the same
// socket that addon-operator's debug server listens on.
debug.DefaultSocketPath = ao.config.Debug.UnixSocket

ao.DefaultNamespace = app.Namespace

Expand All @@ -275,7 +268,11 @@ func NewAddonOperator(ctx context.Context, metricsStorage, hookMetricStorage met
)
}

so := shell_operator.NewShellOperator(cctx, metricsStorage, hookMetricStorage, shell_operator.WithLogger(ao.Logger.Named("shell-operator")))
so := shell_operator.NewBareShellOperator(cctx,
shell_operator.WithMetricStorage(metricsStorage),
shell_operator.WithHookMetricStorage(hookMetricStorage),
shell_operator.WithLogger(ao.Logger.Named("shell-operator")),
)

// initialize logging before Assemble
rc := runtimeConfig.NewConfig(ao.Logger)
Expand Down Expand Up @@ -464,7 +461,13 @@ func (op *AddonOperator) Start(ctx context.Context) error {

func (op *AddonOperator) Stop() {
op.KubeConfigManager.Stop()
op.engine.Shutdown()

shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 30*time.Second)
defer shutdownCancel()

if err := op.engine.Shutdown(shutdownCtx); err != nil {
op.Logger.Error("shutdown error", log.Err(err))
}

if op.cancel != nil {
op.cancel()
Expand Down
6 changes: 4 additions & 2 deletions pkg/app/debug-cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ import (
// global) so the addon-operator-side sub-commands defined in
// DefineDebugCommands stay self-contained.
//
// Note that shapp.DebugUnixSocket is also kept in sync with this value by
// cmd/addon-operator/main.go (via shapp.ApplyConfig(ShellOperatorConfig(cfg)))
// Note that debug.DefaultSocketPath is also kept in sync with this value by
// cmd/addon-operator/main.go so that shell-operator's own debug sub-commands
// (queue, config, hook, raw — wired via debug.DefineDebugCommands) dial the
// same path.
// so that shell-operator's own debug sub-commands (queue, config, hook, raw)
// — wired in by debug.DefineDebugCommands — dial the same path.
func debugClient() (*sh_debug.Client, error) {
Expand Down
Loading