Skip to content

Commit 27f40aa

Browse files
committed
move around some functions
1 parent 11897dc commit 27f40aa

File tree

8 files changed

+145
-101
lines changed

8 files changed

+145
-101
lines changed

coderd/provisionerdserver/provisionerdserver.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,7 @@ func (s *server) acquireProtoJob(ctx context.Context, job database.ProvisionerJo
698698
}
699699
}
700700

701+
activeVersion := template.ActiveVersionID == templateVersion.ID
701702
protoJob.Type = &proto.AcquiredJob_WorkspaceBuild_{
702703
WorkspaceBuild: &proto.AcquiredJob_WorkspaceBuild{
703704
WorkspaceBuildId: workspaceBuild.ID.String(),
@@ -707,7 +708,9 @@ func (s *server) acquireProtoJob(ctx context.Context, job database.ProvisionerJo
707708
PreviousParameterValues: convertRichParameterValues(lastWorkspaceBuildParameters),
708709
VariableValues: asVariableValues(templateVariables),
709710
ExternalAuthProviders: externalAuthProviders,
710-
TerraformWorkspaceReuse: false, // TODO: Toggle based on experiment
711+
// If active and experiment is enabled, allow workspace reuse existing TF
712+
// workspaces (directories) for a faster startup.
713+
TerraformWorkspaceReuse: activeVersion && s.Experiments.Enabled(codersdk.ExperimentTerraformWorkspace),
711714
Metadata: &sdkproto.Metadata{
712715
CoderUrl: s.AccessURL.String(),
713716
WorkspaceTransition: transition,
@@ -721,6 +724,7 @@ func (s *server) acquireProtoJob(ctx context.Context, job database.ProvisionerJo
721724
WorkspaceOwnerId: owner.ID.String(),
722725
TemplateId: template.ID.String(),
723726
TemplateName: template.Name,
727+
TemplateVersionId: templateVersion.ID.String(),
724728
TemplateVersion: templateVersion.Name,
725729
WorkspaceOwnerSessionToken: sessionToken,
726730
WorkspaceOwnerSshPublicKey: ownerSSHPublicKey,

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: 9 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,11 @@ 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 := tfpath.FromWorkingDirectory(workDirectory)
5050

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

5455
// then
5556
entries, err := afero.ReadDir(fs, workDirectory)
@@ -70,9 +71,11 @@ func TestStaleSessions(t *testing.T) {
7071
addSessionFolder(t, fs, first, now.Add(-7*24*time.Hour))
7172
second := tfpath.Session(workDirectory, uuid.NewString())
7273
addSessionFolder(t, fs, second, now.Add(-6*24*time.Hour))
74+
tfDir := tfpath.FromWorkingDirectory(workDirectory)
7375

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

7780
// then
7881
entries, err := afero.ReadDir(fs, workDirectory)
@@ -94,9 +97,11 @@ func TestStaleSessions(t *testing.T) {
9497
addSessionFolder(t, fs, first, now.Add(-6*24*time.Hour))
9598
second := tfpath.Session(workDirectory, uuid.NewString())
9699
addSessionFolder(t, fs, second, now.Add(-5*24*time.Hour))
100+
tfDir := tfpath.FromWorkingDirectory(workDirectory)
97101

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

101106
// then
102107
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
// Extract the template source archive into the work directory.

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".
@@ -202,3 +210,40 @@ func (l Layout) Cleanup(ctx context.Context, logger slog.Logger, fs afero.Fs) {
202210
logger.Error(ctx, "failed to clean up work directory after multiple attempts",
203211
slog.F("path", path), slog.Error(err))
204212
}
213+
214+
// CleanStaleSessions browses the work directory searching for stale session
215+
// directories. Coder provisioner is supposed to remove them once after finishing the provisioning,
216+
// but there is a risk of keeping them in case of a failure.
217+
func (l Layout) CleanStaleSessions(ctx context.Context, logger slog.Logger, fs afero.Fs, now time.Time) error {
218+
parent := filepath.Dir(l.WorkDirectory())
219+
entries, err := afero.ReadDir(fs, filepath.Dir(l.WorkDirectory()))
220+
if err != nil {
221+
return xerrors.Errorf("can't read %q directory", parent)
222+
}
223+
224+
for _, fi := range entries {
225+
dirName := fi.Name()
226+
227+
if fi.IsDir() && isValidSessionDir(dirName) {
228+
sessionDirPath := filepath.Join(parent, dirName)
229+
230+
modTime := fi.ModTime() // fallback to modTime if modTime is not available (afero)
231+
232+
if modTime.Add(staleSessionRetention).After(now) {
233+
continue
234+
}
235+
236+
logger.Info(ctx, "remove stale session directory", slog.F("session_path", sessionDirPath))
237+
err = fs.RemoveAll(sessionDirPath)
238+
if err != nil {
239+
return xerrors.Errorf("can't remove %q directory: %w", sessionDirPath, err)
240+
}
241+
}
242+
}
243+
return nil
244+
}
245+
246+
func isValidSessionDir(dirName string) bool {
247+
match, err := filepath.Match(sessionDirPrefix+"*", dirName)
248+
return err == nil && match
249+
}

0 commit comments

Comments
 (0)