mirror of
https://github.com/coder/coder.git
synced 2026-09-23 22:20:22 +08:00
Add workspace-side file collection to `coder support bundle` via repeatable --workspace-file flags. The agent resolves the requested paths or globs inside the remote workspace and streams back a tar with a manifest and the collected files; nothing is read from the machine running the command. - Add POST /api/v0/bundle-files to the agent's agentfiles package. - Expand env vars in the agent's environment; paths must then be absolute or start with ~/ (the agent user's home directory). - Support ** globs and tail oversized files. - Record requested patterns, per-path errors, truncation, and the applied limits in a manifest. - Unpack the archive into the bundle under agent/workspace_files/, recording dropped entries in collection_errors.txt. - Write a manifest-only archive marking collection as unsupported for agents that predate the endpoint. - Bound collection: 64 KB request body, 10000 files, 10 MiB per file, 100 MiB total including archive overhead, 110 MiB client-side read cap, 5 minute timeout. Closes #26020
69 lines
1.8 KiB
Go
69 lines
1.8 KiB
Go
package agentfiles
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"github.com/go-chi/chi/v5"
|
|
"github.com/spf13/afero"
|
|
|
|
"cdr.dev/slog/v3"
|
|
"github.com/coder/coder/v2/agent/agentgit"
|
|
"github.com/coder/coder/v2/agent/usershell"
|
|
"github.com/coder/coder/v2/codersdk/workspacesdk"
|
|
)
|
|
|
|
// API exposes file-related operations performed through the agent.
|
|
type API struct {
|
|
logger slog.Logger
|
|
filesystem afero.Fs
|
|
pathStore *agentgit.PathStore
|
|
envInfo usershell.EnvInfoer
|
|
bundleFilesLimits workspacesdk.BundleFilesLimits
|
|
}
|
|
|
|
// Option configures the API.
|
|
type Option func(*API)
|
|
|
|
// WithBundleFilesLimits overrides the bundle files collection limits.
|
|
func WithBundleFilesLimits(limits workspacesdk.BundleFilesLimits) Option {
|
|
return func(api *API) {
|
|
api.bundleFilesLimits = limits
|
|
}
|
|
}
|
|
|
|
// WithEnvInfo overrides how the agent user's home directory is resolved.
|
|
func WithEnvInfo(envInfo usershell.EnvInfoer) Option {
|
|
return func(api *API) {
|
|
api.envInfo = envInfo
|
|
}
|
|
}
|
|
|
|
func NewAPI(logger slog.Logger, filesystem afero.Fs, pathStore *agentgit.PathStore, opts ...Option) *API {
|
|
api := &API{
|
|
logger: logger,
|
|
filesystem: filesystem,
|
|
pathStore: pathStore,
|
|
envInfo: usershell.SystemEnvInfo{},
|
|
bundleFilesLimits: defaultBundleFilesLimits,
|
|
}
|
|
for _, opt := range opts {
|
|
opt(api)
|
|
}
|
|
return api
|
|
}
|
|
|
|
// Routes returns the HTTP handler for file-related routes.
|
|
func (api *API) Routes() http.Handler {
|
|
r := chi.NewRouter()
|
|
|
|
r.Post("/list-directory", api.HandleLS)
|
|
r.Get("/resolve-path", api.HandleResolvePath)
|
|
r.Get("/read-file", api.HandleReadFile)
|
|
r.Get("/read-file-lines", api.HandleReadFileLines)
|
|
r.Post("/write-file", api.HandleWriteFile)
|
|
r.Post("/edit-files", api.HandleEditFiles)
|
|
r.Post("/bundle-files", api.HandleBundleFiles)
|
|
|
|
return r
|
|
}
|