mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat(coderd): add support for external agents to API's and provisioner (#19286)
This pull request introduces support for external workspace management, allowing users to register and manage workspaces that are provisioned and managed outside of the Coder. Depends on: https://github.com/coder/terraform-provider-coder/pull/424 * GET /api/v2/init-script - Gets the agent initialization script * By default, it returns a script for Linux (amd64), but with query parameters (os and arch) you can get the init script for different platforms * GET /api/v2/workspaces/{workspace}/external-agent/{agent}/credentials - Gets credentials for an external agent **(enterprise)** * Updated queries to filter workspaces/templates by the has_external_agent field
This commit is contained in:
@@ -2,9 +2,14 @@ package coderd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"github.com/coder/coder/v2/coderd/database"
|
||||
"github.com/coder/coder/v2/coderd/httpapi"
|
||||
"github.com/coder/coder/v2/coderd/httpmw"
|
||||
"github.com/coder/coder/v2/codersdk"
|
||||
)
|
||||
|
||||
@@ -17,3 +22,77 @@ func (api *API) shouldBlockNonBrowserConnections(rw http.ResponseWriter) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// @Summary Get workspace external agent credentials
|
||||
// @ID get-workspace-external-agent-credentials
|
||||
// @Security CoderSessionToken
|
||||
// @Produce json
|
||||
// @Tags Enterprise
|
||||
// @Param workspace path string true "Workspace ID" format(uuid)
|
||||
// @Param agent path string true "Agent name"
|
||||
// @Success 200 {object} codersdk.ExternalAgentCredentials
|
||||
// @Router /workspaces/{workspace}/external-agent/{agent}/credentials [get]
|
||||
func (api *API) workspaceExternalAgentCredentials(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
workspace := httpmw.WorkspaceParam(r)
|
||||
agentName := chi.URLParam(r, "agent")
|
||||
|
||||
build, err := api.Database.GetLatestWorkspaceBuildByWorkspaceID(ctx, workspace.ID)
|
||||
if err != nil {
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Failed to get latest workspace build.",
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
if !build.HasExternalAgent.Bool {
|
||||
httpapi.Write(ctx, rw, http.StatusNotFound, codersdk.Response{
|
||||
Message: "Workspace does not have an external agent.",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
agents, err := api.Database.GetWorkspaceAgentsByWorkspaceAndBuildNumber(ctx, database.GetWorkspaceAgentsByWorkspaceAndBuildNumberParams{
|
||||
WorkspaceID: workspace.ID,
|
||||
BuildNumber: build.BuildNumber,
|
||||
})
|
||||
if err != nil {
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Failed to get workspace agents.",
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
var agent *database.WorkspaceAgent
|
||||
for i := range agents {
|
||||
if agents[i].Name == agentName {
|
||||
agent = &agents[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
if agent == nil {
|
||||
httpapi.Write(ctx, rw, http.StatusNotFound, codersdk.Response{
|
||||
Message: fmt.Sprintf("External agent '%s' not found in workspace.", agentName),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if agent.AuthInstanceID.Valid {
|
||||
httpapi.Write(ctx, rw, http.StatusNotFound, codersdk.Response{
|
||||
Message: "External agent is authenticated with an instance ID.",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
initScriptURL := fmt.Sprintf("%s/api/v2/init-script/%s/%s", api.AccessURL.String(), agent.OperatingSystem, agent.Architecture)
|
||||
command := fmt.Sprintf("CODER_AGENT_TOKEN=%q curl -fsSL %q | sh", agent.AuthToken.String(), initScriptURL)
|
||||
if agent.OperatingSystem == "windows" {
|
||||
command = fmt.Sprintf("$env:CODER_AGENT_TOKEN=%q; iwr -useb %q | iex", agent.AuthToken.String(), initScriptURL)
|
||||
}
|
||||
|
||||
httpapi.Write(ctx, rw, http.StatusOK, codersdk.ExternalAgentCredentials{
|
||||
AgentToken: agent.AuthToken.String(),
|
||||
Command: command,
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user