@@ -21,15 +21,18 @@ import (
2121"github.com/coder/coder/v2/provisionersdk/tfpath"
2222)
2323
24- var _ tfpath.LayoutInterface = (* TerraformDirectory )(nil )
24+ var _ tfpath.LayoutInterface = (* Layout )(nil )
2525
26- func SessionDir (parentDir ,sessID string ,config * proto.Config )TerraformDirectory {
27- if config .TemplateId == "" || config .TemplateId == uuid .Nil .String ()||
28- config .TemplateVersionId == "" || config .TemplateVersionId == uuid .Nil .String () {
26+ func SessionDir (parentDir ,sessID string ,config * proto.Config )Layout {
27+ missingID := config .TemplateId == "" || config .TemplateId == uuid .Nil .String ()||
28+ config .TemplateVersionId == "" || config .TemplateVersionId == uuid .Nil .String ()
29+
30+ // Both templateID and templateVersionID must be set to reuse workspace.
31+ if ! config .TerraformWorkspaceReuse || missingID {
2932return EphemeralSessionDir (parentDir ,sessID )
3033}
3134
32- return TerraformDirectory {
35+ return Layout {
3336workDirectory :filepath .Join (parentDir ,config .TemplateId ,config .TemplateVersionId ),
3437sessionID :sessID ,
3538ephemeral :false ,
@@ -39,15 +42,15 @@ func SessionDir(parentDir, sessID string, config *proto.Config) TerraformDirecto
3942// EphemeralSessionDir returns the directory name with mandatory prefix. These
4043// directories are created for each provisioning session and are meant to be
4144// ephemeral.
42- func EphemeralSessionDir (parentDir ,sessID string )TerraformDirectory {
43- return TerraformDirectory {
45+ func EphemeralSessionDir (parentDir ,sessID string )Layout {
46+ return Layout {
4447workDirectory :filepath .Join (parentDir ,sessionDirPrefix + sessID ),
4548sessionID :sessID ,
4649ephemeral :true ,
4750}
4851}
4952
50- type TerraformDirectory struct {
53+ type Layout struct {
5154workDirectory string
5255sessionID string
5356ephemeral bool
@@ -60,7 +63,7 @@ const (
6063sessionDirPrefix = "Session"
6164)
6265
63- func (td TerraformDirectory )Cleanup (ctx context.Context ,logger slog.Logger ,fs afero.Fs ) {
66+ func (td Layout )Cleanup (ctx context.Context ,logger slog.Logger ,fs afero.Fs ) {
6467var err error
6568path := td .WorkDirectory ()
6669if ! td .ephemeral {
@@ -90,7 +93,7 @@ func (td TerraformDirectory) Cleanup(ctx context.Context, logger slog.Logger, fs
9093return
9194}
9295
93- func (td TerraformDirectory )WorkDirectory ()string {
96+ func (td Layout )WorkDirectory ()string {
9497return td .workDirectory
9598}
9699
@@ -99,39 +102,39 @@ func (td TerraformDirectory) WorkDirectory() string {
99102//
100103// These files should be cleaned up on exit. In the case of a failure, they will
101104// not collide with other builds since each build uses a unique session ID.
102- func (td TerraformDirectory )StateSessionDirectory ()string {
105+ func (td Layout )StateSessionDirectory ()string {
103106return filepath .Join (td .workDirectory ,"terraform.tfstate.d" ,td .sessionID )
104107}
105108
106- func (td TerraformDirectory )StateFilePath ()string {
109+ func (td Layout )StateFilePath ()string {
107110return filepath .Join (td .StateSessionDirectory (),"terraform.tfstate" )
108111}
109112
110- func (td TerraformDirectory )PlanFilePath ()string {
113+ func (td Layout )PlanFilePath ()string {
111114return filepath .Join (td .StateSessionDirectory (),"terraform.tfplan" )
112115}
113116
114- func (td TerraformDirectory )TerraformLockFile ()string {
117+ func (td Layout )TerraformLockFile ()string {
115118return filepath .Join (td .WorkDirectory (),".terraform.lock.hcl" )
116119}
117120
118- func (td TerraformDirectory )ReadmeFilePath ()string {
121+ func (td Layout )ReadmeFilePath ()string {
119122return filepath .Join (td .WorkDirectory (),ReadmeFile )
120123}
121124
122- func (td TerraformDirectory )TerraformMetadataDir ()string {
125+ func (td Layout )TerraformMetadataDir ()string {
123126return filepath .Join (td .WorkDirectory (),".terraform" )
124127}
125128
126- func (td TerraformDirectory )ModulesDirectory ()string {
129+ func (td Layout )ModulesDirectory ()string {
127130return filepath .Join (td .TerraformMetadataDir (),"modules" )
128131}
129132
130- func (td TerraformDirectory )ModulesFilePath ()string {
133+ func (td Layout )ModulesFilePath ()string {
131134return filepath .Join (td .ModulesDirectory (),"modules.json" )
132135}
133136
134- func (td TerraformDirectory )ExtractArchive (ctx context.Context ,logger slog.Logger ,fs afero.Fs ,cfg * proto.Config )error {
137+ func (td Layout )ExtractArchive (ctx context.Context ,logger slog.Logger ,fs afero.Fs ,cfg * proto.Config )error {
135138logger .Info (ctx ,"unpacking template source archive" ,
136139slog .F ("size_bytes" ,len (cfg .TemplateSourceArchive )),
137140)
@@ -224,13 +227,14 @@ func (td TerraformDirectory) ExtractArchive(ctx context.Context, logger slog.Log
224227return nil
225228}
226229
227- //CleanInactiveTemplateVersions assumes thisTerraformDirectory is the latest
228- //active template version. Assuming that, any other template version directories
229- //found alongside it are considered inactive and can be removed. Inactive
230- //template versions should use ephemeral TerraformDirectories.
231- func (td TerraformDirectory ) CleanInactiveTemplateVersions (ctx context.Context ,logger slog.Logger ,fs afero.Fs )error {
230+ //CleanStaleSessions assumes thisLayout is the latest active template version.
231+ // Assuming that, any other template version directories found alongside it are
232+ // considered inactive and can be removed. Inactive template versions should use
233+ // ephemeral TerraformDirectories.
234+ func (td Layout ) CleanStaleSessions (ctx context.Context ,logger slog.Logger ,fs afero.Fs , now time. Time )error {
232235if td .ephemeral {
233- return nil
236+ // Use the existing cleanup for ephemeral sessions.
237+ return tfpath .FromWorkingDirectory (td .workDirectory ).CleanStaleSessions (ctx ,logger ,fs ,now )
234238}
235239
236240wd := td .WorkDirectory ()