fc94326b0e
P00 — Re-architecture Foundation (deprecation/migration/test-infra/persona/docs). Deprecation sweep (REQ-068, REQ-072, REQ-089): - Add // Deprecated: doc comments to internal/daemon (R-001), internal/transport (REQ-073), internal/security/ca.go+csr.go (D-101/REQ-076), internal/engine/ dispatcher.go+peer.go (CLI-side scheduler), internal/cli/daemon.go. - orca daemon emits slog.Warn deprecation banner on every run (ungated); fires R-001 + v0.10-P05 drain-and-stop + v0.10-P14 deletion. - orca cert and orca node join (mTLS path) emit deprecation warnings; proxmox SSH path (the v0.9 replacement) does not warn. - Add --no-deprecation-warnings global flag on root command (PersistentPreRunE) for orca upgrade migrations. - 12 new daemon/cert/node deprecation tests in internal/cli/daemon_test.go (cli coverage 81.9%, warnDeprecated 100%). - Add DEPRECATED banners to v0.8 sections of ARCHITECTURE.md (verified the v0.9 supersession section + Supersession Table from prior turn are present). Bash tooling gate (grill C-06, C-15, C-16, C-17, C-18): - scripts/tests/test_helper.bash + example_test.bash — bats framework + helpers. - scripts/lib/orca-log.sh — slog-compatible JSON logging to syslog (C-17). - scripts/orca-verify-render.sh — render-contract validator skeleton (C-16). - scripts/tests/orca-log_test.bash + orca-verify-render_test.bash — 20 bats tests total (happy + failure paths per C-15). - .shellcheckrc — project shellcheck config. - Makefile: test-bash + lint-bash targets (graceful skip if tools missing); wired into test + lint targets. - internal/emit/contract.go + contract_test.go — versioned JSON render contract (orca.emit/v1) between Go emitters and bash appliers (C-16). - .ciagent/BASH_CAPABILITY_MAP_v0.9.md — maps shipped internal/transport capabilities to bash-side equivalents or accepted drops (C-18). - D-186 recorded in PROJECT.md: bash exempt from Go coverage gate; compensating control is bats + shellcheck + shfmt (C-06). verify-reqs: 90 requirements consistent. Build/test/lint/fmt all green. 20 bats tests pass. Go tests pass. No v0.8 code deleted — only marked deprecated (deletion deferred to v0.10-P14 per REQ-090 dual-write window). ---ci--- project: orca phase: P00 milestone: v0.9 status: execute ---/ci---
234 lines
7.5 KiB
Go
234 lines
7.5 KiB
Go
package cli
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"log/slog"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestDaemonPprofFlag(t *testing.T) {
|
|
f := daemonCmd.Flags().Lookup("pprof")
|
|
if f == nil {
|
|
t.Fatal("--pprof flag not registered on daemonCmd")
|
|
}
|
|
if f.DefValue != "" {
|
|
t.Errorf("--pprof default = %q, want empty", f.DefValue)
|
|
}
|
|
}
|
|
|
|
// captureSlog swaps slog.Default() for a text handler writing to buf,
|
|
// returning a buffer and a restore func. Tests use this to observe
|
|
// warnDeprecated output (which uses the package-level slog.Default).
|
|
func captureSlog(t *testing.T) (*bytes.Buffer, func()) {
|
|
t.Helper()
|
|
var buf bytes.Buffer
|
|
prev := slog.Default()
|
|
logger := slog.New(slog.NewTextHandler(&buf, &slog.HandlerOptions{Level: slog.LevelWarn}))
|
|
slog.SetDefault(logger)
|
|
return &buf, func() { slog.SetDefault(prev) }
|
|
}
|
|
|
|
// runDaemonHermetic invokes daemonCmd.RunE with a context that is
|
|
// already cancelled and an unbindable --addr, so the long-running
|
|
// server start short-circuits and RunE returns quickly without
|
|
// touching the network. It returns whatever RunE returned and the
|
|
// captured slog buffer.
|
|
func runDaemonHermetic(t *testing.T, suppressWarnings bool) (string, error) {
|
|
t.Helper()
|
|
_, cleanup := initTestEnv(t)
|
|
defer cleanup()
|
|
resetRootFlags(t)
|
|
|
|
buf, restore := captureSlog(t)
|
|
defer restore()
|
|
|
|
if suppressWarnings {
|
|
_ = rootCmd.PersistentFlags().Set("no-deprecation-warnings", "true")
|
|
}
|
|
|
|
daemonAddr = "127.0.0.1:99999" // unbindable: port outside uint16 range → ListenAndServe fails fast
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
cancel() // already-done context: the select returns via <-ctx.Done() immediately
|
|
|
|
cmd := daemonCmd
|
|
cmd.SetOut(&bytes.Buffer{})
|
|
cmd.SetErr(&bytes.Buffer{})
|
|
cmd.SetArgs(nil)
|
|
cmd.SetContext(ctx)
|
|
|
|
err := cmd.RunE(cmd, nil)
|
|
return buf.String(), err
|
|
}
|
|
|
|
// TestDaemonEmitsDeprecationWarning verifies REQ-068: `orca daemon`
|
|
// emits a slog.Warn deprecation banner on every run.
|
|
func TestDaemonEmitsDeprecationWarning(t *testing.T) {
|
|
out, _ := runDaemonHermetic(t, false)
|
|
if !strings.Contains(out, "orca daemon is deprecated in v0.9") {
|
|
t.Errorf("expected deprecation warning in slog output, got:\n%s", out)
|
|
}
|
|
if !strings.Contains(out, "R-001") {
|
|
t.Errorf("deprecation warning should reference R-001, got:\n%s", out)
|
|
}
|
|
}
|
|
|
|
// TestDaemonDeprecationWarningSuppressed verifies that
|
|
// --no-deprecation-warnings suppresses the deprecation banner (for
|
|
// `orca upgrade` migrations).
|
|
func TestDaemonDeprecationWarningSuppressed(t *testing.T) {
|
|
out, _ := runDaemonHermetic(t, true)
|
|
if strings.Contains(out, "deprecated in v0.9") {
|
|
t.Errorf("--no-deprecation-warnings should suppress the deprecation warning, got:\n%s", out)
|
|
}
|
|
}
|
|
|
|
// TestDaemonStillRuns verifies deprecation ≠ removal: the daemon
|
|
// command's RunE is still wired and callable. We don't assert on the
|
|
// error value (the hermetic short-circuit may return nil or a
|
|
// shutdown-related error), only that the command did not fail *because*
|
|
// of the deprecation notice.
|
|
func TestDaemonStillRuns(t *testing.T) {
|
|
_, err := runDaemonHermetic(t, false)
|
|
if err != nil && strings.Contains(err.Error(), "deprecated") {
|
|
t.Errorf("daemon must not error due to deprecation, got: %v", err)
|
|
}
|
|
}
|
|
|
|
// TestWarnDeprecatedGate verifies the package-level helper that gates
|
|
// deprecation warnings on the --no-deprecation-warnings flag.
|
|
func TestWarnDeprecatedGate(t *testing.T) {
|
|
t.Run("emits by default", func(t *testing.T) {
|
|
buf, restore := captureSlog(t)
|
|
defer restore()
|
|
noDeprecationWarnings = false
|
|
warnDeprecated("test-deprecation-marker")
|
|
if !strings.Contains(buf.String(), "test-deprecation-marker") {
|
|
t.Errorf("expected warning emitted, got: %s", buf.String())
|
|
}
|
|
})
|
|
t.Run("suppressed when flag set", func(t *testing.T) {
|
|
buf, restore := captureSlog(t)
|
|
defer restore()
|
|
noDeprecationWarnings = true
|
|
defer func() { noDeprecationWarnings = false }()
|
|
warnDeprecated("should-not-appear")
|
|
if strings.Contains(buf.String(), "should-not-appear") {
|
|
t.Errorf("expected no warning when --no-deprecation-warnings set, got: %s", buf.String())
|
|
}
|
|
})
|
|
}
|
|
|
|
// TestNoDeprecationWarningsFlagRegistered verifies the
|
|
// --no-deprecation-warnings persistent flag exists on rootCmd.
|
|
func TestNoDeprecationWarningsFlagRegistered(t *testing.T) {
|
|
f := rootCmd.PersistentFlags().Lookup("no-deprecation-warnings")
|
|
if f == nil {
|
|
t.Fatal("--no-deprecation-warnings persistent flag not registered on rootCmd")
|
|
}
|
|
if f.DefValue != "false" {
|
|
t.Errorf("--no-deprecation-warnings default = %q, want false", f.DefValue)
|
|
}
|
|
}
|
|
|
|
// TestCertEmitsDeprecationWarning verifies REQ-068: `orca cert`
|
|
// subcommands emit a deprecation banner.
|
|
func TestCertEmitsDeprecationWarning(t *testing.T) {
|
|
_, cleanup := initTestEnv(t)
|
|
defer cleanup()
|
|
resetRootFlags(t)
|
|
|
|
buf, restore := captureSlog(t)
|
|
defer restore()
|
|
|
|
var out bytes.Buffer
|
|
rootCmd.SetOut(&out)
|
|
rootCmd.SetErr(&out)
|
|
rootCmd.SetArgs([]string{"cert", "fingerprint", "--which", "ca"})
|
|
_ = rootCmd.Execute()
|
|
|
|
logged := buf.String()
|
|
if !strings.Contains(logged, "orca cert is deprecated in v0.9") {
|
|
t.Errorf("expected cert deprecation warning, got:\n%s", logged)
|
|
}
|
|
if !strings.Contains(logged, "step-ca") {
|
|
t.Errorf("deprecation warning should mention step-ca, got:\n%s", logged)
|
|
}
|
|
}
|
|
|
|
// TestCertDeprecationWarningSuppressed verifies --no-deprecation-warnings
|
|
// suppresses the cert deprecation banner.
|
|
func TestCertDeprecationWarningSuppressed(t *testing.T) {
|
|
_, cleanup := initTestEnv(t)
|
|
defer cleanup()
|
|
resetRootFlags(t)
|
|
_ = rootCmd.PersistentFlags().Set("no-deprecation-warnings", "true")
|
|
|
|
buf, restore := captureSlog(t)
|
|
defer restore()
|
|
|
|
var out bytes.Buffer
|
|
rootCmd.SetOut(&out)
|
|
rootCmd.SetErr(&out)
|
|
rootCmd.SetArgs([]string{"cert", "fingerprint", "--which", "ca"})
|
|
_ = rootCmd.Execute()
|
|
|
|
if strings.Contains(buf.String(), "orca cert is deprecated") {
|
|
t.Errorf("--no-deprecation-warnings should suppress cert warning, got:\n%s", buf.String())
|
|
}
|
|
}
|
|
|
|
// TestNodeJoinMTLSEmitsDeprecationWarning verifies REQ-068: the mTLS
|
|
// join path (`orca node join` without --type proxmox) warns that the
|
|
// mTLS join path is deprecated.
|
|
func TestNodeJoinMTLSEmitsDeprecationWarning(t *testing.T) {
|
|
_, cleanup := initTestEnv(t)
|
|
defer cleanup()
|
|
resetRootFlags(t)
|
|
|
|
buf, restore := captureSlog(t)
|
|
defer restore()
|
|
|
|
var out bytes.Buffer
|
|
rootCmd.SetOut(&out)
|
|
rootCmd.SetErr(&out)
|
|
rootCmd.SetArgs([]string{"node", "join", "--name", "dep-warning", "--addr", "10.0.0.55:8443"})
|
|
if err := rootCmd.Execute(); err != nil {
|
|
t.Fatalf("node join: %v", err)
|
|
}
|
|
|
|
logged := buf.String()
|
|
if !strings.Contains(logged, "mTLS join path is deprecated") {
|
|
t.Errorf("expected mTLS join deprecation warning, got:\n%s", logged)
|
|
}
|
|
if !strings.Contains(logged, "R-001") {
|
|
t.Errorf("deprecation warning should reference R-001, got:\n%s", logged)
|
|
}
|
|
}
|
|
|
|
// TestNodeJoinProxmoxNoMTLSDeprecationWarning verifies the deprecation
|
|
// warning does NOT fire for the proxmox SSH path (that path is the
|
|
// v0.9 replacement, not the deprecated mTLS path).
|
|
func TestNodeJoinProxmoxNoMTLSDeprecationWarning(t *testing.T) {
|
|
_, cleanup := initTestEnv(t)
|
|
defer cleanup()
|
|
resetRootFlags(t)
|
|
|
|
buf, restore := captureSlog(t)
|
|
defer restore()
|
|
|
|
var out bytes.Buffer
|
|
rootCmd.SetOut(&out)
|
|
rootCmd.SetErr(&out)
|
|
// proxmox path errors on missing --host before reaching the warning,
|
|
// and never calls joinLocal, so no mTLS deprecation warning fires.
|
|
rootCmd.SetArgs([]string{"node", "join", "--type", "proxmox", "--password", "x"})
|
|
_ = rootCmd.Execute()
|
|
|
|
if strings.Contains(buf.String(), "mTLS join path is deprecated") {
|
|
t.Errorf("proxmox path must not emit mTLS deprecation warning, got:\n%s", buf.String())
|
|
}
|
|
}
|