Skip to content

Commit 1b05f76

Browse files
committed
move around some functions
1 parent 294ad7c commit 1b05f76

File tree

9 files changed

+201
-140
lines changed

9 files changed

+201
-140
lines changed

coderd/provisionerdserver/provisionerdserver.go

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -699,16 +699,19 @@ func (s *server) acquireProtoJob(ctx context.Context, job database.ProvisionerJo
699699
}
700700
}
701701

702+
activeVersion := template.ActiveVersionID == templateVersion.ID
702703
protoJob.Type = &proto.AcquiredJob_WorkspaceBuild_{
703704
WorkspaceBuild: &proto.AcquiredJob_WorkspaceBuild{
704-
WorkspaceBuildId: workspaceBuild.ID.String(),
705-
WorkspaceName: workspace.Name,
706-
State: workspaceBuild.ProvisionerState,
707-
RichParameterValues: convertRichParameterValues(workspaceBuildParameters),
708-
PreviousParameterValues: convertRichParameterValues(lastWorkspaceBuildParameters),
709-
VariableValues: asVariableValues(templateVariables),
710-
ExternalAuthProviders: externalAuthProviders,
711-
ExpReuseTerraformWorkspace: ptr.Ref(false), // TODO: Toggle based on experiment
705+
WorkspaceBuildId: workspaceBuild.ID.String(),
706+
WorkspaceName: workspace.Name,
707+
State: workspaceBuild.ProvisionerState,
708+
RichParameterValues: convertRichParameterValues(workspaceBuildParameters),
709+
PreviousParameterValues: convertRichParameterValues(lastWorkspaceBuildParameters),
710+
VariableValues: asVariableValues(templateVariables),
711+
ExternalAuthProviders: externalAuthProviders,
712+
// If active and experiment is enabled, allow workspace reuse existing TF
713+
// workspaces (directories) for a faster startup.
714+
ExpReuseTerraformWorkspace: ptr.Ref(activeVersion && s.Experiments.Enabled(codersdk.ExperimentTerraformWorkspace)),
712715
Metadata: &sdkproto.Metadata{
713716
CoderUrl: s.AccessURL.String(),
714717
WorkspaceTransition: transition,
@@ -722,6 +725,7 @@ func (s *server) acquireProtoJob(ctx context.Context, job database.ProvisionerJo
722725
WorkspaceOwnerId: owner.ID.String(),
723726
TemplateId: template.ID.String(),
724727
TemplateName: template.Name,
728+
TemplateVersionId: templateVersion.ID.String(),
725729
TemplateVersion: templateVersion.Name,
726730
WorkspaceOwnerSessionToken: sessionToken,
727731
WorkspaceOwnerSshPublicKey: ownerSSHPublicKey,

coderd/provisionerdserver/provisionerdserver_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,7 @@ func TestAcquireJob(t *testing.T) {
452452
TemplateId: template.ID.String(),
453453
TemplateName: template.Name,
454454
TemplateVersion: version.Name,
455+
TemplateVersionId: version.ID.String(),
455456
WorkspaceOwnerSessionToken: sessionToken,
456457
WorkspaceOwnerSshPublicKey: sshKey.PublicKey,
457458
WorkspaceOwnerSshPrivateKey: sshKey.PrivateKey,

provisioner/terraform/executor.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,11 @@ func (e *executor) graph(ctx, killCtx context.Context) (string, error) {
536536
if err != nil {
537537
return "", err
538538
}
539-
args := []string{"graph"}
539+
args := []string{
540+
"graph",
541+
// TODO: When the plan is present, we should probably use it?
542+
// "-plan=" + e.files.PlanFilePath(),
543+
}
540544
if ver.GreaterThanOrEqual(version170) {
541545
args = append(args, "-type=plan")
542546
}

provisionerd/provisionerd_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"github.com/coder/coder/v2/provisionerd/proto"
2727
"github.com/coder/coder/v2/provisionersdk"
2828
sdkproto "github.com/coder/coder/v2/provisionersdk/proto"
29+
"github.com/coder/coder/v2/provisionersdk/tfpath"
2930
"github.com/coder/coder/v2/testutil"
3031
)
3132

@@ -318,8 +319,8 @@ func TestProvisionerd(t *testing.T) {
318319
JobId: "test",
319320
Provisioner: "someprovisioner",
320321
TemplateSourceArchive: testutil.CreateTar(t, map[string]string{
321-
"test.txt": "content",
322-
provisionersdk.ReadmeFile: "# A cool template 😎\n",
322+
"test.txt": "content",
323+
tfpath.ReadmeFile: "# A cool template 😎\n",
323324
}),
324325
Type: &proto.AcquiredJob_TemplateImport_{
325326
TemplateImport: &proto.AcquiredJob_TemplateImport{

provisionersdk/cleanup.go

Lines changed: 0 additions & 48 deletions
This file was deleted.

provisionersdk/cleanup_test.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
"github.com/stretchr/testify/require"
1212

1313
"cdr.dev/slog"
14-
"github.com/coder/coder/v2/provisionersdk"
1514
"github.com/coder/coder/v2/provisionersdk/tfpath"
1615
"github.com/coder/coder/v2/testutil"
1716
)
@@ -47,9 +46,12 @@ func TestStaleSessions(t *testing.T) {
4746
addSessionFolder(t, fs, second, now.Add(-8*24*time.Hour))
4847
third := tfpath.Session(workDirectory, uuid.NewString())
4948
addSessionFolder(t, fs, third, now.Add(-9*24*time.Hour))
49+
// tfDir is a fake session that will clean up the others
50+
tfDir := tfpath.Session(workDirectory, uuid.NewString())
5051

5152
// when
52-
provisionersdk.CleanStaleSessions(ctx, workDirectory, fs, now, logger)
53+
err := tfDir.CleanStaleSessions(ctx, logger, fs, now)
54+
require.NoError(t, err)
5355

5456
// then
5557
entries, err := afero.ReadDir(fs, workDirectory)
@@ -70,9 +72,11 @@ func TestStaleSessions(t *testing.T) {
7072
addSessionFolder(t, fs, first, now.Add(-7*24*time.Hour))
7173
second := tfpath.Session(workDirectory, uuid.NewString())
7274
addSessionFolder(t, fs, second, now.Add(-6*24*time.Hour))
75+
tfDir := tfpath.Session(workDirectory, uuid.NewString())
7376

7477
// when
75-
provisionersdk.CleanStaleSessions(ctx, workDirectory, fs, now, logger)
78+
err := tfDir.CleanStaleSessions(ctx, logger, fs, now)
79+
require.NoError(t, err)
7680

7781
// then
7882
entries, err := afero.ReadDir(fs, workDirectory)
@@ -94,9 +98,11 @@ func TestStaleSessions(t *testing.T) {
9498
addSessionFolder(t, fs, first, now.Add(-6*24*time.Hour))
9599
second := tfpath.Session(workDirectory, uuid.NewString())
96100
addSessionFolder(t, fs, second, now.Add(-5*24*time.Hour))
101+
tfDir := tfpath.Session(workDirectory, uuid.NewString())
97102

98103
// when
99-
provisionersdk.CleanStaleSessions(ctx, workDirectory, fs, now, logger)
104+
err := tfDir.CleanStaleSessions(ctx, logger, fs, now)
105+
require.NoError(t, err)
100106

101107
// then
102108
entries, err := afero.ReadDir(fs, workDirectory)

provisionersdk/session.go

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,13 @@ import (
1616
"github.com/coder/coder/v2/codersdk"
1717
"github.com/coder/coder/v2/codersdk/drpcsdk"
1818
"github.com/coder/coder/v2/provisionersdk/tfpath"
19-
"github.com/coder/coder/v2/provisionersdk/x"
19+
"github.com/coder/coder/v2/provisionersdk/tfpath/x"
2020

2121
protobuf "google.golang.org/protobuf/proto"
2222

2323
"github.com/coder/coder/v2/provisionersdk/proto"
2424
)
2525

26-
const (
27-
// ReadmeFile is the location we look for to extract documentation from template versions.
28-
ReadmeFile = "README.md"
29-
30-
sessionDirPrefix = "Session"
31-
staleSessionRetention = 7 * 24 * time.Hour
32-
)
33-
3426
// protoServer is a wrapper that translates the dRPC protocol into a Session with method calls into the Server.
3527
type protoServer struct {
3628
server Server
@@ -45,11 +37,6 @@ func (p *protoServer) Session(stream proto.DRPCProvisioner_SessionStream) error
4537
server: p.server,
4638
}
4739

48-
err := CleanStaleSessions(s.Context(), p.opts.WorkDirectory, afero.NewOsFs(), time.Now(), s.Logger)
49-
if err != nil {
50-
return xerrors.Errorf("unable to clean stale sessions %q: %w", s.Files, err)
51-
}
52-
5340
s.Files = tfpath.Session(p.opts.WorkDirectory, sessID)
5441

5542
defer func() {
@@ -70,13 +57,13 @@ func (p *protoServer) Session(stream proto.DRPCProvisioner_SessionStream) error
7057
}
7158

7259
if p.opts.Experiments.Enabled(codersdk.ExperimentTerraformWorkspace) {
73-
// TODO: Also indicate if opted into the feature via config
7460
s.Files = x.SessionDir(p.opts.WorkDirectory, sessID, config)
61+
}
7562

76-
err = s.Files.CleanInactiveTemplateVersions(s.Context(), s.Logger, afero.NewOsFs())
77-
if err != nil {
78-
return xerrors.Errorf("unable to clean inactive versions %q: %w", s.Files.WorkDirectory(), err)
79-
}
63+
// Cleanup any previously left stale sessions.
64+
err = s.Files.CleanStaleSessions(s.Context(), s.Logger, afero.NewOsFs(), time.Now())
65+
if err != nil {
66+
return xerrors.Errorf("unable to clean stale sessions %q: %w", s.Files, err)
8067
}
8168

8269
err = s.Files.ExtractArchive(s.Context(), s.Logger, afero.NewOsFs(), s.Config)

provisionersdk/tfpath/tfpath.go

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,17 @@ type LayoutInterface interface {
3030
ModulesFilePath() string
3131
ExtractArchive(ctx context.Context, logger slog.Logger, fs afero.Fs, cfg *proto.Config) error
3232
Cleanup(ctx context.Context, logger slog.Logger, fs afero.Fs)
33+
CleanStaleSessions(ctx context.Context, logger slog.Logger, fs afero.Fs, now time.Time) error
3334
}
3435

36+
var _ LayoutInterface = (*Layout)(nil)
37+
3538
const (
3639
// ReadmeFile is the location we look for to extract documentation from template versions.
3740
ReadmeFile = "README.md"
3841

39-
sessionDirPrefix = "Session"
42+
sessionDirPrefix = "Session"
43+
staleSessionRetention = 7 * 24 * time.Hour
4044
)
4145

4246
// Session creates a directory structure layout for terraform execution. The
@@ -47,6 +51,10 @@ func Session(parentDirPath, sessionID string) Layout {
4751
return Layout(filepath.Join(parentDirPath, sessionDirPrefix+sessionID))
4852
}
4953

54+
func FromWorkingDirectory(workDir string) Layout {
55+
return Layout(workDir)
56+
}
57+
5058
// Layout is the terraform execution working directory structure.
5159
// It also contains some methods for common file operations within that layout.
5260
// Such as "Cleanup" and "ExtractArchive".
@@ -203,3 +211,40 @@ func (l Layout) Cleanup(ctx context.Context, logger slog.Logger, fs afero.Fs) {
203211
logger.Error(ctx, "failed to clean up work directory after multiple attempts",
204212
slog.F("path", path), slog.Error(err))
205213
}
214+
215+
// CleanStaleSessions browses the work directory searching for stale session
216+
// directories. Coder provisioner is supposed to remove them once after finishing the provisioning,
217+
// but there is a risk of keeping them in case of a failure.
218+
func (l Layout) CleanStaleSessions(ctx context.Context, logger slog.Logger, fs afero.Fs, now time.Time) error {
219+
parent := filepath.Dir(l.WorkDirectory())
220+
entries, err := afero.ReadDir(fs, filepath.Dir(l.WorkDirectory()))
221+
if err != nil {
222+
return xerrors.Errorf("can't read %q directory", parent)
223+
}
224+
225+
for _, fi := range entries {
226+
dirName := fi.Name()
227+
228+
if fi.IsDir() && isValidSessionDir(dirName) {
229+
sessionDirPath := filepath.Join(parent, dirName)
230+
231+
modTime := fi.ModTime() // fallback to modTime if modTime is not available (afero)
232+
233+
if modTime.Add(staleSessionRetention).After(now) {
234+
continue
235+
}
236+
237+
logger.Info(ctx, "remove stale session directory", slog.F("session_path", sessionDirPath))
238+
err = fs.RemoveAll(sessionDirPath)
239+
if err != nil {
240+
return xerrors.Errorf("can't remove %q directory: %w", sessionDirPath, err)
241+
}
242+
}
243+
}
244+
return nil
245+
}
246+
247+
func isValidSessionDir(dirName string) bool {
248+
match, err := filepath.Match(sessionDirPrefix+"*", dirName)
249+
return err == nil && match
250+
}

0 commit comments

Comments
 (0)