Skip to content

fix: configure profile handling, global-flag validation & client connect timeout#21

Merged
vks-team merged 7 commits into
mainfrom
fix/configure-set-list-nil-panic
Jun 30, 2026
Merged

fix: configure profile handling, global-flag validation & client connect timeout#21
vks-team merged 7 commits into
mainfrom
fix/configure-set-list-nil-panic

Conversation

@vks-team

@vks-team vks-team commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Summary

A batch of correctness and AWS-parity fixes found while exercising grn. Started as a configure nil-panic fix and grew to cover global-flag validation, error output, and the connect-timeout flag.

Changes

configure — profile handling

  • Fix nil-pointer panic in configure set/configure list for a profile not yet in the credentials file (e.g. grn configure set region HCM-3 --profile prod-hcm-qc3). LoadConfig returned (nil, err) and the nil *Config was dereferenced.
  • LoadConfig now reads credentials and config files independently: a profile created via configure set (config file only, no credentials yet) loads its region/output/project_id correctly. A profile is considered to exist if present in either file (or via env credentials).
  • get/list report a missing profile with a clear profile '...' does not exist error and non-zero exit (like aws configure), instead of crashing or printing empty values. A fresh machine with no config files still lists unset defaults.

Global flags — validation & error output

  • Reject invalid --output/--color up front (PersistentPreRunE) with a "maybe you meant" suggestion (Levenshtein-nearest) and a non-zero exit, instead of silently falling back to JSON / default.
  • Concise errors: set SilenceErrors/SilenceUsage and print a single Error: ... line, instead of cobra's duplicated error plus a full usage dump.

Client

  • Honor --cli-connect-timeout: the flag was registered but never read, and the HTTP transport had no dial timeout, so an unreachable endpoint hung ~127s regardless. Now wired into the transport's net.Dialer (DialContext) + TLSHandshakeTimeout in both the VKS and vServer clients. A connect to an unreachable host with --cli-connect-timeout 1 now fails per-attempt in ~1s.

Docs

  • Clarify --unhealthy-range format in config-auto-healing help ("[min-max]", e.g. "[2-5]").

Testing

  • New tests: LoadConfig (config-only / neither-file / creds-only / no-files), configure set on a new profile, --output/--color validation + suggestion, client connect-timeout wiring.
  • go vet ./... clean; full go test ./... passes; verified end-to-end via the binary (incl. a real connect-timeout timing check: ~127s → ~11s with 4 retries, ~1s per connect).

Notes / follow-ups (not done, awaiting decision)

  • --cli-connect-timeout 1 fails in ~11s total because the client retries 3× with backoff (per-connect is correctly ~1s). Could make connect errors non-retryable or add a total request deadline if a faster hard fail is wanted.
  • --unhealthy-range is not validated client-side (server rejects malformed values).

🤖 Generated with Claude Code

tytv2 and others added 7 commits June 30, 2026 19:19
LoadConfig returns (nil, err) for a profile not present in the credentials
file. configure set and configure list discarded that error and dereferenced
the nil *Config, crashing with SIGSEGV (e.g. `grn configure set region HCM-3
--profile prod-hcm-qc3`). Fall back to empty defaults — matching the fix
already applied to interactive `configure` — so a value can be set or listed
for a brand-new profile. Adds regression tests.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A profile present only in the config file — e.g. just after
`configure set region --profile X` on a profile that has no credentials yet —
previously failed: LoadConfig returned early with an error when the credentials
section was missing, so region/output/project_id (which live in the config
file) were never read, and set/list saw a nil *Config.

LoadConfig now treats the two files independently: a profile "exists" if it has
a section in either file (or credentials via env vars). It only returns a
"profile does not exist" error when config files are present but the profile is
in neither — matching `aws configure`. Adds LoadConfig tests for the
config-only, neither-file, creds-only, and no-files cases.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
configure list now exits non-zero with "profile does not exist" when the
profile is absent from existing config files, instead of printing empty values.
A fresh machine with no config files still lists unset defaults, matching
`aws configure list`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
An unrecognized --output value (e.g. the typo 'tabel') previously fell through
formatter's default case to JSON and exited 0, so users got a different format
than intended with no warning. Add a root PersistentPreRunE that validates the
--output flag up front and fails fast with a non-zero exit, a "maybe you meant"
suggestion (Levenshtein-nearest valid format), and the list of valid formats —
matching `aws`/`gcloud`. Only validates the flag when explicitly set.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Extend up-front global-flag validation to --color (on/off/auto) using the same
"maybe you meant" suggestion as --output. Set SilenceErrors/SilenceUsage on the
root command and print a single "Error: ..." line in Execute, so failures no
longer emit cobra's duplicated error plus a full usage block — matching aws/gcloud.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The flag was registered but never read, and the HTTP transport used a bare
http.Transport with no dial timeout — so the connect/TLS phase was unbounded
and an unreachable endpoint hung for ~127s (4 attempts x the 30s read timeout)
regardless of --cli-connect-timeout.

NewGreenodeClient now takes connectTimeout and wires it into the transport's
net.Dialer (DialContext) and TLSHandshakeTimeout; both the VKS and vServer
client builders read --cli-connect-timeout and pass it through. A connect to an
unreachable host with --cli-connect-timeout 1 now fails per-attempt in ~1s
(dial i/o timeout) instead of 30s.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
config-auto-healing's --unhealthy-range help said only "Unhealthy range" with
no hint at the expected syntax. State the format ("[min-max]", e.g. "[2-5]")
matching the API spec, like --max-unhealthy already shows "30%".

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vks-team vks-team changed the title fix(configure): prevent nil-pointer panic on set/list for new profile fix: configure profile handling, global-flag validation & client connect timeout Jun 30, 2026
@vks-team vks-team merged commit 806b938 into main Jun 30, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant