Commit e4b8399
authored
feat: add hypeman cp for file copy to/from running VMs (#45)
* refactor: rename exec-agent to guest-agent and add cp support
This commit renames the exec-agent to guest-agent to better reflect its
expanding role as a general-purpose guest interaction service. Along with
the rename, this adds gRPC support for file copy operations:
- Rename lib/exec to lib/guest
- Rename lib/system/exec_agent to lib/system/guest_agent
- Add CopyToGuest and CopyFromGuest RPCs
- Add StatPath RPC for querying guest filesystem metadata
- Implement cp handlers with uid/gid preservation support
- Update all imports and references
The guest-agent continues to listen on vsock port 2222 and handle
command execution, with new file copy capabilities.
* feat: add WebSocket endpoint for cp operations
Add /instances/{id}/cp WebSocket endpoint to enable file copy operations
between the local filesystem and running VM instances. Also adds
/instances/{id}/stat HTTP endpoint for querying guest path metadata.
Features:
- Copy files and directories to/from running instances
- Streaming file transfer with chunked data
- Support for symlinks and directory hierarchies
- UID/GID preservation for archive mode
- Follow symlinks option
* api: add dedicated /instances/{id}/stat endpoint
Add a separate HTTP endpoint for querying filesystem path info in guests.
This replaces the overloaded 'direction: stat' option in the cp WebSocket
endpoint with a cleaner REST API.
- Add PathInfo schema with exists, is_dir, is_file, is_symlink, etc.
- Add GET /instances/{id}/stat endpoint with path and follow_links params
- Add stat method to stainless.yaml for SDK generation
The new endpoint:
- Uses simple HTTP GET instead of WebSocket overhead
- Enables autogenerated SDK methods (client.Instances.Stat())
- Mirrors the guest agent's separate StatPath RPC
- Is self-documenting via OpenAPI spec
* test: add integration tests for cp operations
Add comprehensive integration tests for file copy functionality:
- Test copying single files to instance
- Test copying directories recursively to instance
- Test copying files from instance
- Test copying directories from instance
- Verify file content, permissions, and metadata preservation
Also adds Reset() method to outputBuffer helper used in tests.
* fix(cp): preserve directory modification times during copy
The mtime was only being applied when currentFile != nil, which is only
true for regular files. For directories, currentFile is never set since
they are created with os.MkdirAll without opening a file handle.
This fix moves the mtime logic outside of the currentFile != nil block
so it applies to both files and directories.
* chore: remove accidentally committed guest_agent binary
Updated .gitignore to cover both guest-agent and guest_agent naming
patterns and removed the tracked binary from the repository.
* feat(metrics): add cp metrics and OTEL tracing
Added metrics for copy operations following the exec metrics pattern:
- hypeman_cp_sessions_total (labels: direction, status)
- hypeman_cp_duration_seconds
- hypeman_cp_bytes_total
Also added OTEL span in CpHandler since WebSocket connections bypass
the otelchi middleware for HTTP request tracing.
* refactor(guest-agent): split main.go into logical files
Reorganized the 732-line main.go into a cleaner structure:
- main.go: Server setup, listener, gRPC registration (minimal)
- exec.go: Exec-related methods (Exec, executeTTY, executeNoTTY, buildEnv)
- cp.go: Copy methods (CopyToGuest, CopyFromGuest, helpers)
- stat.go: StatPath method
This matches the lib/*/README.md pattern used in the server codebase
and makes the guest-agent more maintainable as it grows.1 parent 8328365 commit e4b8399
File tree
39 files changed
+4321
-1314
lines changed- cmd/api
- api
- lib
- devices
- exec
- guest
- instances
- oapi
- system
- guest_agent
39 files changed
+4321
-1314
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
20 | 20 | | |
21 | 21 | | |
22 | 22 | | |
| 23 | + | |
| 24 | + | |
23 | 25 | | |
24 | 26 | | |
25 | 27 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
127 | 127 | | |
128 | 128 | | |
129 | 129 | | |
130 | | - | |
| 130 | + | |
131 | 131 | | |
132 | 132 | | |
133 | 133 | | |
134 | 134 | | |
135 | 135 | | |
136 | 136 | | |
137 | 137 | | |
138 | | - | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
139 | 147 | | |
140 | 148 | | |
141 | 149 | | |
| |||
156 | 164 | | |
157 | 165 | | |
158 | 166 | | |
159 | | - | |
160 | | - | |
161 | | - | |
162 | | - | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
163 | 171 | | |
164 | 172 | | |
165 | | - | |
| 173 | + | |
166 | 174 | | |
167 | 175 | | |
168 | 176 | | |
169 | 177 | | |
170 | 178 | | |
171 | 179 | | |
172 | | - | |
| 180 | + | |
173 | 181 | | |
174 | 182 | | |
175 | 183 | | |
176 | 184 | | |
177 | 185 | | |
178 | 186 | | |
179 | | - | |
| 187 | + | |
180 | 188 | | |
181 | 189 | | |
182 | 190 | | |
| |||
194 | 202 | | |
195 | 203 | | |
196 | 204 | | |
197 | | - | |
| 205 | + | |
198 | 206 | | |
199 | 207 | | |
200 | 208 | | |
201 | | - | |
| 209 | + | |
202 | 210 | | |
0 commit comments