97b88a703c
orca ns inherit <name> --parent (cycle detection), ns set-constraint <key>=value>. Deprecation warnings on orca cert ca-init/gen/renew (step-ca replaces) and .hcl jobspec (R-013). --no-deprecation-warnings suppresses all. ---ci--- project: orca phase: 13 milestone: v0.11 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: deprecated
|
|
// `orca cert ca-init` subcommand emits 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", "ca-init", "--cn", "test-ca"})
|
|
_ = rootCmd.Execute()
|
|
|
|
logged := buf.String()
|
|
if !strings.Contains(logged, "orca cert ca-init is deprecated") {
|
|
t.Errorf("expected cert ca-init 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", "ca-init", "--cn", "test-ca"})
|
|
_ = rootCmd.Execute()
|
|
|
|
if strings.Contains(buf.String(), "orca cert ca-init 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())
|
|
}
|
|
}
|