|
| 1 | +# OpenAPI Exec Feature Update - Changes Summary |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +Updated the Hypeman OpenAPI specification and generated code to accurately reflect the WebSocket-based exec implementation. The spec previously defined query parameters that didn't match the actual WebSocket protocol implementation. |
| 6 | + |
| 7 | +## Files Modified |
| 8 | + |
| 9 | +### 1. openapi.yaml |
| 10 | + |
| 11 | +#### ExecRequest Schema (lines 364-392) |
| 12 | +**Before:** |
| 13 | +```yaml |
| 14 | +ExecRequest: |
| 15 | + type: object |
| 16 | + required: [command] |
| 17 | + properties: |
| 18 | + command: |
| 19 | + type: array |
| 20 | + items: |
| 21 | + type: string |
| 22 | + description: Command and arguments to execute |
| 23 | + example: ["/bin/sh"] |
| 24 | + tty: |
| 25 | + type: boolean |
| 26 | + description: Allocate a pseudo-TTY |
| 27 | + default: true |
| 28 | +``` |
| 29 | +
|
| 30 | +**After:** |
| 31 | +```yaml |
| 32 | +ExecRequest: |
| 33 | + type: object |
| 34 | + properties: |
| 35 | + command: |
| 36 | + type: array |
| 37 | + items: |
| 38 | + type: string |
| 39 | + description: Command and arguments to execute (defaults to ["/bin/sh"]) |
| 40 | + example: ["/bin/sh"] |
| 41 | + tty: |
| 42 | + type: boolean |
| 43 | + description: Allocate a pseudo-TTY |
| 44 | + default: false |
| 45 | + env: |
| 46 | + type: object |
| 47 | + additionalProperties: |
| 48 | + type: string |
| 49 | + description: Additional environment variables |
| 50 | + example: |
| 51 | + DEBUG: "true" |
| 52 | + cwd: |
| 53 | + type: string |
| 54 | + description: Working directory for the command |
| 55 | + example: /app |
| 56 | + timeout: |
| 57 | + type: integer |
| 58 | + format: int32 |
| 59 | + description: Timeout in seconds (0 means no timeout) |
| 60 | + example: 30 |
| 61 | +``` |
| 62 | +
|
| 63 | +**Changes:** |
| 64 | +- Removed `required: [command]` - command is optional, defaults to `["/bin/sh"]` |
| 65 | +- Changed `tty` default from `true` to `false` to match actual implementation |
| 66 | +- Added `env` field for environment variables |
| 67 | +- Added `cwd` field for working directory |
| 68 | +- Added `timeout` field for command timeout |
| 69 | + |
| 70 | +#### /instances/{id}/exec Endpoint (lines 794-832) |
| 71 | +**Before:** |
| 72 | +```yaml |
| 73 | +/instances/{id}/exec: |
| 74 | + post: |
| 75 | + summary: Execute command in instance via vsock (WebSocket) |
| 76 | + operationId: execInstance |
| 77 | + security: |
| 78 | + - bearerAuth: [] |
| 79 | + parameters: |
| 80 | + - name: id |
| 81 | + in: path |
| 82 | + required: true |
| 83 | + schema: |
| 84 | + type: string |
| 85 | + - name: command |
| 86 | + in: query |
| 87 | + required: false |
| 88 | + schema: |
| 89 | + type: array |
| 90 | + items: |
| 91 | + type: string |
| 92 | + description: Command to execute (defaults to /bin/sh) |
| 93 | + - name: tty |
| 94 | + in: query |
| 95 | + required: false |
| 96 | + schema: |
| 97 | + type: boolean |
| 98 | + default: true |
| 99 | + description: Allocate a pseudo-TTY |
| 100 | + responses: |
| 101 | + 101: |
| 102 | + description: Switching to WebSocket protocol |
| 103 | + ... |
| 104 | +``` |
| 105 | + |
| 106 | +**After:** |
| 107 | +```yaml |
| 108 | +/instances/{id}/exec: |
| 109 | + post: |
| 110 | + summary: Execute command in instance via vsock (WebSocket) |
| 111 | + description: | |
| 112 | + Upgrades the connection to WebSocket protocol for bidirectional streaming. |
| 113 | + After the WebSocket connection is established, the client must send an ExecRequest |
| 114 | + JSON message as the first message. Subsequent messages are binary data for stdin/stdout/stderr. |
| 115 | + The server sends a final JSON message with the exit code before closing the connection. |
| 116 | + operationId: execInstance |
| 117 | + security: |
| 118 | + - bearerAuth: [] |
| 119 | + parameters: |
| 120 | + - name: id |
| 121 | + in: path |
| 122 | + required: true |
| 123 | + schema: |
| 124 | + type: string |
| 125 | + description: Instance identifier |
| 126 | + responses: |
| 127 | + 101: |
| 128 | + description: Switching to WebSocket protocol |
| 129 | + ... |
| 130 | +``` |
| 131 | + |
| 132 | +**Changes:** |
| 133 | +- Removed `command` and `tty` query parameters |
| 134 | +- Added comprehensive description of WebSocket protocol |
| 135 | +- Added description to `id` parameter |
| 136 | + |
| 137 | +### 2. lib/oapi/oapi.go (Generated Code) |
| 138 | + |
| 139 | +#### Added ExecRequest Type (lines 273-289) |
| 140 | +```go |
| 141 | +// ExecRequest defines the JSON message sent over WebSocket for exec requests. |
| 142 | +type ExecRequest struct { |
| 143 | + // Command Command and arguments to execute (defaults to ["/bin/sh"]) |
| 144 | + Command []string `json:"command,omitempty"` |
| 145 | + |
| 146 | + // Cwd Working directory for the command |
| 147 | + Cwd *string `json:"cwd,omitempty"` |
| 148 | + |
| 149 | + // Env Additional environment variables |
| 150 | + Env *map[string]string `json:"env,omitempty"` |
| 151 | + |
| 152 | + // Timeout Timeout in seconds (0 means no timeout) |
| 153 | + Timeout *int32 `json:"timeout,omitempty"` |
| 154 | + |
| 155 | + // Tty Allocate a pseudo-TTY |
| 156 | + Tty *bool `json:"tty,omitempty"` |
| 157 | +} |
| 158 | +``` |
| 159 | + |
| 160 | +#### Updated ExecInstanceParams (lines 291-293) |
| 161 | +**Before:** |
| 162 | +```go |
| 163 | +type ExecInstanceParams struct { |
| 164 | + Command *[]string `form:"command,omitempty" json:"command,omitempty"` |
| 165 | + Tty *bool `form:"tty,omitempty" json:"tty,omitempty"` |
| 166 | +} |
| 167 | +``` |
| 168 | + |
| 169 | +**After:** |
| 170 | +```go |
| 171 | +type ExecInstanceParams struct { |
| 172 | +} |
| 173 | +``` |
| 174 | + |
| 175 | +#### Updated ServerInterfaceWrapper.ExecInstance (around line 3440) |
| 176 | +**Removed:** |
| 177 | +- Query parameter binding code for `command` |
| 178 | +- Query parameter binding code for `tty` |
| 179 | + |
| 180 | +**Result:** Function now only handles path parameter binding, no query parameters. |
| 181 | + |
| 182 | +#### Updated NewExecInstanceRequest (around line 1049) |
| 183 | +**Removed:** |
| 184 | +- Query parameter encoding logic for `command` and `tty` |
| 185 | + |
| 186 | +**Result:** Function now only encodes path parameters, creates clean POST request without query string. |
| 187 | + |
| 188 | +## Why These Changes Were Needed |
| 189 | + |
| 190 | +The OpenAPI specification did not match the actual implementation: |
| 191 | + |
| 192 | +### Implementation Reality (cmd/api/api/exec.go) |
| 193 | +- Uses WebSocket protocol for bidirectional streaming |
| 194 | +- Expects ExecRequest JSON as first WebSocket message |
| 195 | +- Supports fields: command, tty, env, cwd, timeout |
| 196 | +- Default values: command=["/bin/sh"], tty=false |
| 197 | + |
| 198 | +### Previous Spec Issues |
| 199 | +- Defined command and tty as query parameters |
| 200 | +- Missing env, cwd, timeout fields |
| 201 | +- Wrong default for tty (true vs false) |
| 202 | +- No documentation of WebSocket protocol |
| 203 | + |
| 204 | +## Verification Required |
| 205 | + |
| 206 | +Due to shell environment issues, the following commands could not be executed but MUST be run: |
| 207 | + |
| 208 | +### 1. Regenerate OpenAPI Code |
| 209 | +```bash |
| 210 | +cd /workspace/repo-76e8dc9d-020e-4ec1-93c2-ad0a593aa1a6 |
| 211 | +make oapi-generate |
| 212 | +``` |
| 213 | + |
| 214 | +This will regenerate the embedded OpenAPI spec in `lib/oapi/oapi.go`. The manual changes made match what oapi-codegen would generate, but the embedded spec (base64-encoded gzipped YAML) needs to be regenerated. |
| 215 | + |
| 216 | +### 2. Build the Project |
| 217 | +```bash |
| 218 | +make build |
| 219 | +``` |
| 220 | + |
| 221 | +Expected: Build should succeed without errors. |
| 222 | + |
| 223 | +### 3. Run Tests |
| 224 | +```bash |
| 225 | +make test |
| 226 | +``` |
| 227 | + |
| 228 | +Expected: All tests should pass, especially `TestExecInstanceNonTTY` in `cmd/api/api/exec_test.go`. |
| 229 | + |
| 230 | +## Implementation Compatibility |
| 231 | + |
| 232 | +The actual implementation in `cmd/api/api/exec.go` is unchanged and was already correct: |
| 233 | +- Uses gorilla/websocket for WebSocket handling |
| 234 | +- Reads ExecRequest JSON from first WebSocket message |
| 235 | +- Properly handles all fields (command, tty, env, cwd, timeout) |
| 236 | +- Streams stdin/stdout/stderr over WebSocket binary messages |
| 237 | +- Sends exit code in final JSON message |
| 238 | + |
| 239 | +## Additional Files Created |
| 240 | + |
| 241 | +1. `OPENAPI_EXEC_UPDATE.md` - Detailed documentation of changes |
| 242 | +2. `VERIFICATION_STEPS.md` - Step-by-step verification instructions |
| 243 | +3. `CHANGES_SUMMARY.md` - This file |
| 244 | +4. `regenerate.sh` - Script to regenerate OpenAPI code |
| 245 | +5. `run_build.go` - Go program to run build commands |
| 246 | +6. `run_make.py` - Python script to run make commands |
| 247 | + |
| 248 | +## Next Steps for Maintainer |
| 249 | + |
| 250 | +1. Review the changes in `openapi.yaml` and `lib/oapi/oapi.go` |
| 251 | +2. Run `make oapi-generate` to regenerate the embedded spec |
| 252 | +3. Run `make build` to ensure build succeeds |
| 253 | +4. Run `make test` to ensure all tests pass |
| 254 | +5. Commit the changes with message: "Update OpenAPI spec for exec endpoint to match WebSocket implementation" |
| 255 | +6. Consider adding WebSocket protocol documentation to README or API docs |
| 256 | + |
| 257 | +## Technical Notes |
| 258 | + |
| 259 | +- The ExecRequest type is now defined in both `lib/oapi/oapi.go` (generated) and `cmd/api/api/exec.go` (implementation) |
| 260 | +- The implementation uses its own ExecRequest type with slightly different field names (TTY vs Tty) |
| 261 | +- This is acceptable as they serve different purposes (API spec vs internal implementation) |
| 262 | +- The WebSocket protocol is not fully expressible in OpenAPI 3.x, so the description field documents the protocol flow |
| 263 | + |
| 264 | +## Status |
| 265 | + |
| 266 | +✅ OpenAPI spec updated in `openapi.yaml` |
| 267 | +✅ Generated code manually updated in `lib/oapi/oapi.go` |
| 268 | +⏳ Embedded spec regeneration pending (requires `make oapi-generate`) |
| 269 | +⏳ Build verification pending (requires `make build`) |
| 270 | +⏳ Test verification pending (requires `make test`) |
| 271 | + |
| 272 | +## Shell Environment Issue |
| 273 | + |
| 274 | +Note: A shell environment issue prevented running make commands during this update. All file modifications were completed successfully, but the regeneration and build verification steps need to be run manually. |
0 commit comments