feat: Add graceful exits to provisionerd (#372)

* ci: Update DataDog GitHub branch to fallback to GITHUB_REF

This was detecting branches, but not our "main" branch before.
Hopefully this fixes it!

* Add basic Terraform Provider

* Rename post files to upload

* Add tests for resources

* Skip instance identity test

* Add tests for ensuring agent get's passed through properly

* Fix linting errors

* Add echo path

* Fix agent authentication

* fix: Convert all jobs to use a common resource and agent type

This enables a consistent API for project import and provisioned resources.

* Add "coder_workspace" data source

* feat: Remove magical parameters from being injected

This is a much cleaner abstraction. Explicitly declaring the user
parameters for each provisioner makes for significantly simpler
testing.

* feat: Add graceful exits to provisionerd

Terraform (or other provisioners) may need to cleanup state, or
cancel actions before exit. This adds the ability to gracefully
exit provisionerd.

* Fix cancel error check
This commit is contained in:
Kyle Carberry
2022-02-28 12:40:49 -06:00
committed by GitHub
parent e5c95552cd
commit 9d2803e07a
13 changed files with 1091 additions and 537 deletions

View File

@ -404,8 +404,8 @@ func (server *provisionerdServer) UpdateJob(ctx context.Context, request *proto.
return &proto.UpdateJobResponse{}, nil
}
func (server *provisionerdServer) CancelJob(ctx context.Context, cancelJob *proto.CancelledJob) (*proto.Empty, error) {
jobID, err := uuid.Parse(cancelJob.JobId)
func (server *provisionerdServer) FailJob(ctx context.Context, failJob *proto.FailedJob) (*proto.Empty, error) {
jobID, err := uuid.Parse(failJob.JobId)
if err != nil {
return nil, xerrors.Errorf("parse job id: %w", err)
}
@ -422,19 +422,35 @@ func (server *provisionerdServer) CancelJob(ctx context.Context, cancelJob *prot
Time: database.Now(),
Valid: true,
},
CancelledAt: sql.NullTime{
Time: database.Now(),
Valid: true,
},
UpdatedAt: database.Now(),
Error: sql.NullString{
String: cancelJob.Error,
Valid: cancelJob.Error != "",
String: failJob.Error,
Valid: failJob.Error != "",
},
})
if err != nil {
return nil, xerrors.Errorf("update provisioner job: %w", err)
}
switch jobType := failJob.Type.(type) {
case *proto.FailedJob_WorkspaceProvision_:
if jobType.WorkspaceProvision.State == nil {
break
}
var input workspaceProvisionJob
err = json.Unmarshal(job.Input, &input)
if err != nil {
return nil, xerrors.Errorf("unmarshal workspace provision input: %w", err)
}
err = server.Database.UpdateWorkspaceHistoryByID(ctx, database.UpdateWorkspaceHistoryByIDParams{
ID: jobID,
UpdatedAt: database.Now(),
ProvisionerState: jobType.WorkspaceProvision.State,
})
if err != nil {
return nil, xerrors.Errorf("update workspace history state: %w", err)
}
case *proto.FailedJob_ProjectImport_:
}
return &proto.Empty{}, nil
}

View File

@ -276,7 +276,11 @@ func convertProvisionerJob(provisionerJob database.ProvisionerJob) ProvisionerJo
case !provisionerJob.StartedAt.Valid:
job.Status = ProvisionerJobStatusPending
case provisionerJob.CompletedAt.Valid:
job.Status = ProvisionerJobStatusSucceeded
if job.Error == "" {
job.Status = ProvisionerJobStatusSucceeded
} else {
job.Status = ProvisionerJobStatusFailed
}
case database.Now().Sub(provisionerJob.UpdatedAt) > 30*time.Second:
job.Status = ProvisionerJobStatusFailed
job.Error = "Worker failed to update job in time."
@ -284,10 +288,6 @@ func convertProvisionerJob(provisionerJob database.ProvisionerJob) ProvisionerJo
job.Status = ProvisionerJobStatusRunning
}
if !provisionerJob.CancelledAt.Valid && job.Error != "" {
job.Status = ProvisionerJobStatusFailed
}
return job
}