Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fix: Convert all jobs to use a common resource and agent type
This enables a consistent API for project import and provisioned resources.
  • Loading branch information
kylecarbs committed Feb 27, 2022
commit 89b188709afee3f67948262b3b6e6ae33cbbdbaa
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"ntqry",
"oneof",
"parameterscopeid",
"pqtype",
"promptui",
"protobuf",
"provisionerd",
Expand Down
2 changes: 1 addition & 1 deletion cli/projects.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func projects() *cobra.Command {
return cmd
}

func displayProjectImportInfo(cmd *cobra.Command, parameterSchemas []coderd.ParameterSchema, parameterValues []coderd.ComputedParameterValue, resources []coderd.ProjectImportJobResource) error {
func displayProjectImportInfo(cmd *cobra.Command, parameterSchemas []coderd.ParameterSchema, parameterValues []coderd.ComputedParameterValue, resources []coderd.ProvisionerJobResource) error {
schemaByID := map[string]coderd.ParameterSchema{}
for _, schema := range parameterSchemas {
schemaByID[schema.ID.String()] = schema
Expand Down
7 changes: 2 additions & 5 deletions coderd/projectimport.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@ type ParameterSchema database.ParameterSchema
// ComputedParameterValue represents a computed parameter value.
type ComputedParameterValue parameter.ComputedValue

// ProjectImportJobResource is a resource created by a project import job.
type ProjectImportJobResource database.ProjectImportJobResource

// CreateProjectImportJobRequest provides options to create a project import job.
type CreateProjectImportJobRequest struct {
StorageMethod database.ProvisionerStorageMethod `json:"storage_method" validate:"oneof=file,required"`
Expand Down Expand Up @@ -167,7 +164,7 @@ func (api *api) projectImportJobResourcesByID(rw http.ResponseWriter, r *http.Re
})
return
}
resources, err := api.Database.GetProjectImportJobResourcesByJobID(r.Context(), job.ID)
resources, err := api.Database.GetProvisionerJobResourcesByJobID(r.Context(), job.ID)
if errors.Is(err, sql.ErrNoRows) {
err = nil
}
Expand All @@ -178,7 +175,7 @@ func (api *api) projectImportJobResourcesByID(rw http.ResponseWriter, r *http.Re
return
}
if resources == nil {
resources = []database.ProjectImportJobResource{}
resources = []database.ProvisionerJobResource{}
}
render.Status(r, http.StatusOK)
render.JSON(rw, r, resources)
Expand Down
87 changes: 60 additions & 27 deletions coderd/provisionerdaemons.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/google/uuid"
"github.com/hashicorp/yamux"
"github.com/moby/moby/pkg/namesgenerator"
"github.com/tabbed/pqtype"
"golang.org/x/xerrors"
"nhooyr.io/websocket"
"storj.io/drpc/drpcmux"
Expand Down Expand Up @@ -453,14 +454,8 @@ func (server *provisionerdServer) CompleteJob(ctx context.Context, completed *pr
slog.F("resource_name", resource.Name),
slog.F("resource_type", resource.Type),
slog.F("transition", transition))
_, err = server.Database.InsertProjectImportJobResource(ctx, database.InsertProjectImportJobResourceParams{
ID: uuid.New(),
CreatedAt: database.Now(),
JobID: jobID,
Transition: transition,
Type: resource.Type,
Name: resource.Name,
})

err = insertProvisionerJobResource(ctx, server.Database, jobID, transition, resource)
if err != nil {
return nil, xerrors.Errorf("insert resource: %w", err)
}
Expand Down Expand Up @@ -516,26 +511,9 @@ func (server *provisionerdServer) CompleteJob(ctx context.Context, completed *pr
}
// This could be a bulk insert to improve performance.
for _, protoResource := range jobType.WorkspaceProvision.Resources {
var instanceID sql.NullString
if protoResource.Agent != nil && protoResource.Agent.GetGoogleInstanceIdentity() != nil {
instanceID = sql.NullString{
String: protoResource.Agent.GetGoogleInstanceIdentity().InstanceId,
Valid: true,
}
}
_, err = db.InsertWorkspaceResource(ctx, database.InsertWorkspaceResourceParams{
ID: uuid.New(),
CreatedAt: database.Now(),
WorkspaceHistoryID: input.WorkspaceHistoryID,
Type: protoResource.Type,
Name: protoResource.Name,
InstanceID: instanceID,
// TODO: Generate this at the variable validation phase.
// Set the value in `default_source`, and disallow overwrite.
WorkspaceAgentToken: uuid.NewString(),
})
err = insertProvisionerJobResource(ctx, db, job.ID, workspaceHistory.Transition, protoResource)
if err != nil {
return xerrors.Errorf("insert workspace resource %q: %w", protoResource.Name, err)
return xerrors.Errorf("insert provisioner job: %w", err)
}
}
return nil
Expand All @@ -551,6 +529,61 @@ func (server *provisionerdServer) CompleteJob(ctx context.Context, completed *pr
return &proto.Empty{}, nil
}

func insertProvisionerJobResource(ctx context.Context, db database.Store, jobID uuid.UUID, transition database.WorkspaceTransition, protoResource *sdkproto.Resource) error {
resource, err := db.InsertProvisionerJobResource(ctx, database.InsertProvisionerJobResourceParams{
ID: uuid.New(),
CreatedAt: database.Now(),
JobID: jobID,
Transition: transition,
Type: protoResource.Type,
Name: protoResource.Name,
AgentID: uuid.NullUUID{
UUID: uuid.New(),
Valid: protoResource.Agent != nil,
},
})
if err != nil {
return xerrors.Errorf("insert provisioner job resource %q: %w", protoResource.Name, err)
}
if resource.AgentID.Valid {
var instanceID sql.NullString
if protoResource.Agent.GetGoogleInstanceIdentity() != nil {
instanceID = sql.NullString{
String: protoResource.Agent.GetGoogleInstanceIdentity().InstanceId,
Valid: true,
}
}
var env pqtype.NullRawMessage
if protoResource.Agent.Env != nil {
data, err := json.Marshal(protoResource.Agent.Env)
if err != nil {
return xerrors.Errorf("marshal env: %w", err)
}
env = pqtype.NullRawMessage{
RawMessage: data,
Valid: true,
}
}

_, err := db.InsertProvisionerJobAgent(ctx, database.InsertProvisionerJobAgentParams{
ID: resource.AgentID.UUID,
CreatedAt: database.Now(),
ResourceID: resource.ID,
AuthToken: uuid.New(),
AuthInstanceID: instanceID,
EnvironmentVariables: env,
StartupScript: sql.NullString{
String: protoResource.Agent.StartupScript,
Valid: protoResource.Agent.StartupScript != "",
},
})
if err != nil {
return xerrors.Errorf("insert agent: %w", err)
}
}
return nil
}

func convertValidationTypeSystem(typeSystem sdkproto.ParameterSchema_TypeSystem) (database.ParameterTypeSystem, error) {
switch typeSystem {
case sdkproto.ParameterSchema_None:
Expand Down
21 changes: 20 additions & 1 deletion coderd/provisionerjobs.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,32 @@ type ProvisionerJob struct {

// ProvisionerJobLog represents a single log from a provisioner job.
type ProvisionerJobLog struct {
ID uuid.UUID
ID uuid.UUID `json:"id"`
CreatedAt time.Time `json:"created_at"`
Source database.LogSource `json:"log_source"`
Level database.LogLevel `json:"log_level"`
Output string `json:"output"`
}

type ProvisionerJobResource struct {
ID uuid.UUID `json:"id"`
CreatedAt time.Time `json:"created_at"`
JobID uuid.UUID `json:"job_id"`
Transition database.WorkspaceTransition `json:"workspace_transition"`
Type string `json:"type"`
Name string `json:"name"`
}

type ProvisionerJobAgent struct {
ID uuid.UUID `json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
ResourceID uuid.UUID `json:"resource_id"`
InstanceID string `json:"instance_id,omitempty"`
EnvironmentVariables map[string]string `json:"environment_variables"`
StartupScript string `json:"startup_script,omitempty"`
}

func (*api) provisionerJobByID(rw http.ResponseWriter, r *http.Request) {
job := httpmw.ProvisionerJobParam(r)
render.Status(r, http.StatusOK)
Expand Down
42 changes: 39 additions & 3 deletions coderd/workspaceagent.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ package coderd

import (
"database/sql"
"encoding/json"
"errors"
"fmt"
"net/http"

"github.com/go-chi/render"

"github.com/coder/coder/database"
"github.com/coder/coder/httpapi"

"github.com/mitchellh/mapstructure"
Expand Down Expand Up @@ -54,14 +56,48 @@ func (api *api) postAuthenticateWorkspaceAgentUsingGoogleInstanceIdentity(rw htt
})
return
}
resource, err := api.Database.GetWorkspaceResourceByInstanceID(r.Context(), claims.Google.ComputeEngine.InstanceID)
agent, err := api.Database.GetProvisionerJobAgentByInstanceID(r.Context(), claims.Google.ComputeEngine.InstanceID)
if errors.Is(err, sql.ErrNoRows) {
httpapi.Write(rw, http.StatusNotFound, httpapi.Response{
Message: fmt.Sprintf("instance with id %q not found", claims.Google.ComputeEngine.InstanceID),
})
return
}
resourceHistory, err := api.Database.GetWorkspaceHistoryByID(r.Context(), resource.WorkspaceHistoryID)
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
Message: fmt.Sprintf("get provisioner job agent: %s", err),
})
return
}
resource, err := api.Database.GetProvisionerJobResourceByID(r.Context(), agent.ResourceID)
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
Message: fmt.Sprintf("get provisioner job resource: %s", err),
})
return
}
job, err := api.Database.GetProvisionerJobByID(r.Context(), resource.JobID)
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
Message: fmt.Sprintf("get provisioner job: %s", err),
})
return
}
if job.Type != database.ProvisionerJobTypeWorkspaceProvision {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{
Message: fmt.Sprintf("%q jobs cannot be authenticated", job.Type),
})
return
}
var jobData workspaceProvisionJob
err = json.Unmarshal(job.Input, &jobData)
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
Message: fmt.Sprintf("extract job data: %s", err),
})
return
}
resourceHistory, err := api.Database.GetWorkspaceHistoryByID(r.Context(), jobData.WorkspaceHistoryID)
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
Message: fmt.Sprintf("get workspace history: %s", err),
Expand All @@ -86,6 +122,6 @@ func (api *api) postAuthenticateWorkspaceAgentUsingGoogleInstanceIdentity(rw htt
}
render.Status(r, http.StatusOK)
render.JSON(rw, r, WorkspaceAgentAuthenticateResponse{
SessionToken: resource.WorkspaceAgentToken,
SessionToken: agent.AuthToken.String(),
})
}
4 changes: 2 additions & 2 deletions codersdk/projectimport.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func (c *Client) ProjectImportJobParameters(ctx context.Context, organization st
}

// ProjectImportJobResources returns resources for a project import job.
func (c *Client) ProjectImportJobResources(ctx context.Context, organization string, job uuid.UUID) ([]coderd.ProjectImportJobResource, error) {
func (c *Client) ProjectImportJobResources(ctx context.Context, organization string, job uuid.UUID) ([]coderd.ProvisionerJobResource, error) {
res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/projectimport/%s/%s/resources", organization, job), nil)
if err != nil {
return nil, err
Expand All @@ -90,6 +90,6 @@ func (c *Client) ProjectImportJobResources(ctx context.Context, organization str
if res.StatusCode != http.StatusOK {
return nil, readBodyAsError(res)
}
var resources []coderd.ProjectImportJobResource
var resources []coderd.ProvisionerJobResource
return resources, json.NewDecoder(res.Body).Decode(&resources)
}
Loading