feat(commands): add doctor diagnostic command#192
Conversation
Inspired by cli-printing-press's `auth doctor`. New `jamf-cli doctor`
command prints resolved profile, env-var state, and a read-only HEAD
probe of the configured URL. Auth is bypassed (chainSkip) so it works
even when credentials are misconfigured — the case where it's most
useful.
Output:
- Version
- Config path + presence
- Active profile: name, source ("--profile flag" / "JAMF_PROFILE env"
/ "config default-profile" / "positional argument"), URL, auth
method, per-credential resolution status
- Env vars: 12 known JAMF_* / JAMFPROTECT_* / JAMFSCHOOL_* entries.
Secrets show first-4 fingerprint only; non-secret URLs/IDs show the
actual value.
- Connectivity: 5s HEAD probe with status code + latency
Default output format is JSON (consistent with the rest of the CLI).
Pass `-o table` (or any non-json/yaml format) for the human summary.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Addresses PR #192 review findings: (1) Resolve and display the *effective* URL the auth chain would use (--url > JAMF_URL > profile), not just the profile URL. New profileReport.EffectiveURL/URLSource fields and a per-credential EnvOverride flag call out the "shadowed by env var" failure mode the command exists to diagnose. Connectivity probe now hits the effective URL. (2) printDoctorHuman now takes io.Writer and routes through the formatter's writer, so 'doctor -o table --out-file r.txt' captures the human report instead of writing to stdout while leaving r.txt empty. New Formatter.Writer() accessor exposes the destination. (3) probeConnectivity sets a User-Agent header (some Jamf proxies/CDNs reject UA-less requests) and stops at the first redirect rather than following — for a reachability check, a 302 to /login is more informative than its target. (4) When no config file exists but JAMF_URL + a credential env var are set, the note says "operating in env-var mode" instead of misdirecting CI/CD users to 'pro setup'. (5) Documents the format-routing decision (json/yaml → formatter, everything else → human renderer) inline. Adds 6 new tests covering effective-URL resolution, env-var override flagging, no-config-with-env-vars detection, writer injection for human output, and User-Agent + redirect handling on the probe. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
# Conflicts: # internal/output/output.go
|
Approved — live tested against Verified:
Gap (non-blocking, file follow-up): Same for Ship — these are polish, not blockers. 🤖 Live-tested with Claude Code |
neilmartin83
left a comment
There was a problem hiding this comment.
Live-tested against platform-nmartin tenant. Profile resolution precedence, fingerprint redaction, missing-profile handling, HEAD-only unauthenticated probe, --compact/--select/--field interop, and unit tests all clean. Filed nit on missing tenant-id in profileReport (platform-auth gap) — non-blocking.
Summary
jamf-cli doctor [profile]command — prints config path, resolved active profile (and the signal that selected it), every JAMF_* / JAMFPROTECT_* / JAMFSCHOOL_* env var (secrets fingerprinted, never full values), per-profile credential resolution status, and a 5-second unauthenticated HEAD probe of the configured URLauth doctorchainSkip) so it works precisely when credentials are misconfigured — the case where it's most usefulWhy
When an agent or human hits 401, the question is "is the token missing, expired, or shadowed by a stale env var?". Today that takes
cat ~/.config/jamf-cli/config.yaml,env | grep JAMF, and a curl.jamf-cli doctoris one command.Example output (
-o tablefor the human view)JSON output via
-o json(the default) returns the same data as a structureddoctorReport.Security
fingerprint()returns first 4 chars +••••. Values shorter than 4 chars are fully redacted.~/.config/jamf-cli/config.yamland OS env vars only. No writes.Test plan
go test ./internal/commands/... -run 'Doctor|Fingerprint|ProbeEnvVars|ProbeProfileCredentials|ResolveProfileNameForDoctor'— 11 tests covering precedence, fingerprint redaction, env-var probing, missing-profile note, credential resolution success/failurego test ./...— full suite green (includingTestApplyRootGroups_AllCommandsGroupedafter addingdoctortorootGroupMap)make lint— 0 issuesjamf-cli doctor,jamf-cli doctor -o table,jamf-cli doctor missing-profileNotes
This is the fourth and last "cheap win" pulled from cli-printing-press. Independent of #189 / #190 / #191 — can land in any order.
🤖 Generated with Claude Code