Commit 98e4664
committed
feat(cli): complete CLI with full CRUD operations (NVIDIA#563) (NVIDIA#621)
* docs: add CLI CRUD and verbosity design document
Design for issue NVIDIA#563 covering:
- New CLI commands (describe, get, ssh, scp, update)
- Global verbosity flags (-q, -v, -d)
- Output formatting infrastructure
- Implementation tasks and testing strategy
Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
* docs: add CLI CRUD implementation plan
Detailed task-by-task implementation plan for:
- Global verbosity flags (-q, -v, -d)
- Unit tests for all new CLI commands
- Output formatter tests
11 tasks with TDD approach and commit checkpoints.
Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
* feat(logger): add verbosity levels with Debug and Trace methods
Add Verbosity type with four levels (Quiet, Normal, Verbose, Debug) to
control log output. Info, Check, and Warning methods now respect
verbosity settings, while Error always prints. New Debug and Trace
methods provide additional logging granularity for troubleshooting.
Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
* feat(cli): add global verbosity flags (-q, --verbose, -d)
Add global flags for controlling output verbosity:
- --quiet, -q: Suppress non-error output
- --verbose: Enable verbose output
- --debug, -d: Enable debug-level logging (also reads DEBUG env var)
Flag precedence: --debug > --verbose > --quiet
Note: -v was not used for --verbose to avoid conflict with built-in --version flag.
Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
* refactor(cli): rename list --quiet to --ids-only
Rename the --quiet flag to --ids-only to avoid conflict with the new
global --quiet flag that controls verbosity. The --ids-only flag now
only outputs instance IDs, one per line.
Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
* test(output): add unit tests for output formatting package
Add comprehensive unit tests for the pkg/output package covering:
- ValidFormats() and IsValidFormat() validation functions
- NewFormatter() with empty, valid, and invalid format inputs
- Formatter.Format() accessor method
- PrintJSON() with struct, map, and slice data types
- PrintYAML() with struct, map, and nested struct data
- Print() dispatch logic for JSON, YAML, and table formats
- PrintTable() with mock TableData interface
- TablePrinter fluent interface (Header, Row, Flush)
- SetWriter() for output redirection
- Error message quality for invalid formats
Achieves 97.9% code coverage.
Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
* feat(output): add output formatting package with table/JSON/YAML support
Adds pkg/output with Formatter, TablePrinter, and TableData interface
for consistent output formatting across all CLI commands.
Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
* feat(cli): add output formatting to status command
Adds -o flag (json/yaml/table) to holodeck status with structured
output types for JSON/YAML serialization.
Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
* feat(cli): add describe, get, ssh, scp, update commands with tests
New commands for issue NVIDIA#563:
- describe: detailed instance introspection with JSON/YAML output
- get kubeconfig: download kubeconfig from instance
- get ssh-config: generate SSH config entry
- ssh: SSH into instance or run remote commands
- scp: copy files to/from instance via SFTP
- update: update instance configuration (add components, labels)
All commands include unit tests for core logic.
Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
* test(list): update tests for --ids-only flag rename
Updates list_test.go to use --ids-only instead of the old --quiet/-q
flag which was renamed to avoid conflict with the global -q flag.
Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
* fix(cli): fix nil map panic and SSH command quoting
C1: Add nil check for env.Labels before writing provisioned label
in update --reprovision. Previously panicked when no --label flags
were provided and the cached environment had no labels.
C2: Replace incorrect containsSpace+fmt.Sprintf("%q") quoting with
simple strings.Join. SSH session.Run always passes through the
remote shell, so Go-style quoting was wrong. Document this behavior.
Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
* refactor(cli): extract shared utilities and fix review issues
- Extract getHostURL and connectSSH into cmd/cli/common package,
eliminating duplication across ssh, scp, and get commands (I1)
- Use path instead of filepath for remote SFTP paths to ensure
correct POSIX separators on all platforms (I2)
- Log warnings for skipped files during recursive remote copy (I3)
- Use c.IsSet() for flags with defaults to prevent overwriting
existing config with default values (I4)
Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
* fix(ci): resolve lint issues, update go.mod, and remove plan docs
- Fix gofmt, gosec, staticcheck, unconvert, and errcheck lint issues
- Promote gopkg.in/yaml.v3 from indirect to direct dependency
- Remove planning documents (development artifacts)
Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
* fix(security): correct misleading host key comments (CWE-322)
Address CodeQL alert NVIDIA#6 (go/insecure-hostkeycallback) by replacing
the inaccurate comment about "no pre-established host keys". The env
file requires SSH authentication keys (client-to-server), but server
host keys are a separate concern — they are generated at instance boot
with no trusted distribution channel to the client.
The security trade-off is now explicitly documented with CWE reference.
Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
* refactor(cli): use common.GetHostURL in update runProvision (S4)
Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
* fix(cli): consolidate update command cache file writes (C2)
Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
* feat(cli): add -q as alias for --ids-only for backwards compatibility (S1)
Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
* refactor(cli): extract SSH retry constants in ConnectSSH (S2)
Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
* docs(cli): document SSH remote command quoting behavior (S3)
Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
* fix(logger): warnings always print regardless of verbosity (M1)
Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
* refactor(cli): consolidate GetHostURL tests into common package (M3)
Move duplicate GetHostURL tests from cmd/cli/get/ and cmd/cli/ssh/
into cmd/cli/common/host_test.go. Merge overlapping test cases and
add a new TestGetHostURL_Cluster_FallbackToFirstNode case that covers
the fallback path when no control-plane node exists.
Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
* fix(logger): make Verbosity thread-safe with atomic.Int32 (M6)
Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
* fix(logger): add nolint directive for gosec G115 in SetVerbosity
Verbosity is an iota (0-3) so the int->int32 cast cannot overflow.
Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
---------
Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>1 parent 565199a commit 98e4664
File tree
19 files changed
+4229
-135
lines changed- cmd/cli
- common
- describe
- get
- list
- scp
- ssh
- status
- update
- internal/logger
- pkg/output
19 files changed
+4229
-135
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
0 commit comments