mirror of
https://github.com/coder/coder.git
synced 2025-07-09 11:45:56 +00:00
feat: Add external provisioner daemons (#4935)
* Start to port over provisioner daemons PR * Move to Enterprise * Begin adding tests for external registration * Move provisioner daemons query to enterprise * Move around provisioner daemons schema * Add tags to provisioner daemons * make gen * Add user local provisioner daemons * Add provisioner daemons * Add feature for external daemons * Add command to start a provisioner daemon * Add provisioner tags to template push and create * Rename migration files * Fix tests * Fix entitlements test * PR comments * Update migration * Fix FE types
This commit is contained in:
@ -15,13 +15,14 @@ const (
|
||||
)
|
||||
|
||||
const (
|
||||
FeatureUserLimit = "user_limit"
|
||||
FeatureAuditLog = "audit_log"
|
||||
FeatureBrowserOnly = "browser_only"
|
||||
FeatureSCIM = "scim"
|
||||
FeatureTemplateRBAC = "template_rbac"
|
||||
FeatureHighAvailability = "high_availability"
|
||||
FeatureMultipleGitAuth = "multiple_git_auth"
|
||||
FeatureUserLimit = "user_limit"
|
||||
FeatureAuditLog = "audit_log"
|
||||
FeatureBrowserOnly = "browser_only"
|
||||
FeatureSCIM = "scim"
|
||||
FeatureTemplateRBAC = "template_rbac"
|
||||
FeatureHighAvailability = "high_availability"
|
||||
FeatureMultipleGitAuth = "multiple_git_auth"
|
||||
FeatureExternalProvisionerDaemons = "external_provisioner_daemons"
|
||||
)
|
||||
|
||||
var FeatureNames = []string{
|
||||
@ -32,6 +33,7 @@ var FeatureNames = []string{
|
||||
FeatureTemplateRBAC,
|
||||
FeatureHighAvailability,
|
||||
FeatureMultipleGitAuth,
|
||||
FeatureExternalProvisionerDaemons,
|
||||
}
|
||||
|
||||
type Feature struct {
|
||||
|
@ -36,11 +36,12 @@ type Organization struct {
|
||||
type CreateTemplateVersionRequest struct {
|
||||
Name string `json:"name,omitempty" validate:"omitempty,template_name"`
|
||||
// TemplateID optionally associates a version with a template.
|
||||
TemplateID uuid.UUID `json:"template_id,omitempty"`
|
||||
TemplateID uuid.UUID `json:"template_id,omitempty"`
|
||||
StorageMethod ProvisionerStorageMethod `json:"storage_method" validate:"oneof=file,required"`
|
||||
FileID uuid.UUID `json:"file_id" validate:"required"`
|
||||
Provisioner ProvisionerType `json:"provisioner" validate:"oneof=terraform echo,required"`
|
||||
ProvisionerTags map[string]string `json:"tags"`
|
||||
|
||||
StorageMethod ProvisionerStorageMethod `json:"storage_method" validate:"oneof=file,required"`
|
||||
FileID uuid.UUID `json:"file_id" validate:"required"`
|
||||
Provisioner ProvisionerType `json:"provisioner" validate:"oneof=terraform echo,required"`
|
||||
// ParameterValues allows for additional parameters to be provided
|
||||
// during the dry-run provision stage.
|
||||
ParameterValues []CreateParameterRequest `json:"parameter_values,omitempty"`
|
||||
|
@ -13,20 +13,22 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/hashicorp/yamux"
|
||||
"golang.org/x/xerrors"
|
||||
"nhooyr.io/websocket"
|
||||
|
||||
"github.com/coder/coder/provisionerd/proto"
|
||||
"github.com/coder/coder/provisionersdk"
|
||||
)
|
||||
|
||||
type LogSource string
|
||||
|
||||
const (
|
||||
LogSourceProvisionerDaemon LogSource = "provisioner_daemon"
|
||||
LogSourceProvisioner LogSource = "provisioner"
|
||||
)
|
||||
|
||||
type LogLevel string
|
||||
|
||||
const (
|
||||
LogSourceProvisionerDaemon LogSource = "provisioner_daemon"
|
||||
LogSourceProvisioner LogSource = "provisioner"
|
||||
|
||||
LogLevelTrace LogLevel = "trace"
|
||||
LogLevelDebug LogLevel = "debug"
|
||||
LogLevelInfo LogLevel = "info"
|
||||
@ -40,6 +42,7 @@ type ProvisionerDaemon struct {
|
||||
UpdatedAt sql.NullTime `json:"updated_at"`
|
||||
Name string `json:"name"`
|
||||
Provisioners []ProvisionerType `json:"provisioners"`
|
||||
Tags map[string]string `json:"tags"`
|
||||
}
|
||||
|
||||
// ProvisionerJobStatus represents the at-time state of a job.
|
||||
@ -73,6 +76,7 @@ type ProvisionerJob struct {
|
||||
Status ProvisionerJobStatus `json:"status"`
|
||||
WorkerID *uuid.UUID `json:"worker_id,omitempty"`
|
||||
FileID uuid.UUID `json:"file_id"`
|
||||
Tags map[string]string `json:"tags"`
|
||||
}
|
||||
|
||||
type ProvisionerJobLog struct {
|
||||
@ -162,3 +166,51 @@ func (c *Client) provisionerJobLogsAfter(ctx context.Context, path string, after
|
||||
return nil
|
||||
}), nil
|
||||
}
|
||||
|
||||
// ListenProvisionerDaemon returns the gRPC service for a provisioner daemon implementation.
|
||||
func (c *Client) ServeProvisionerDaemon(ctx context.Context, organization uuid.UUID, provisioners []ProvisionerType, tags map[string]string) (proto.DRPCProvisionerDaemonClient, error) {
|
||||
serverURL, err := c.URL.Parse(fmt.Sprintf("/api/v2/organizations/%s/provisionerdaemons/serve", organization))
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("parse url: %w", err)
|
||||
}
|
||||
query := serverURL.Query()
|
||||
for _, provisioner := range provisioners {
|
||||
query.Add("provisioner", string(provisioner))
|
||||
}
|
||||
for key, value := range tags {
|
||||
query.Add("tag", fmt.Sprintf("%s=%s", key, value))
|
||||
}
|
||||
serverURL.RawQuery = query.Encode()
|
||||
jar, err := cookiejar.New(nil)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("create cookie jar: %w", err)
|
||||
}
|
||||
jar.SetCookies(serverURL, []*http.Cookie{{
|
||||
Name: SessionTokenKey,
|
||||
Value: c.SessionToken(),
|
||||
}})
|
||||
httpClient := &http.Client{
|
||||
Jar: jar,
|
||||
}
|
||||
conn, res, err := websocket.Dial(ctx, serverURL.String(), &websocket.DialOptions{
|
||||
HTTPClient: httpClient,
|
||||
// Need to disable compression to avoid a data-race.
|
||||
CompressionMode: websocket.CompressionDisabled,
|
||||
})
|
||||
if err != nil {
|
||||
if res == nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, readBodyAsError(res)
|
||||
}
|
||||
// Align with the frame size of yamux.
|
||||
conn.SetReadLimit(256 * 1024)
|
||||
|
||||
config := yamux.DefaultConfig()
|
||||
config.LogOutput = io.Discard
|
||||
session, err := yamux.Client(websocket.NetConn(ctx, conn, websocket.MessageBinary), config)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("multiplex client: %w", err)
|
||||
}
|
||||
return proto.NewDRPCProvisionerDaemonClient(provisionersdk.Conn(session)), nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user