@@ -10,7 +10,6 @@ import (
1010"io"
1111"os"
1212"os/exec"
13- "path/filepath"
1413"runtime"
1514"strings"
1615"sync"
@@ -22,6 +21,7 @@ import (
2221"golang.org/x/xerrors"
2322
2423"cdr.dev/slog"
24+ "github.com/coder/coder/v2/provisionersdk/tfpath"
2525
2626"github.com/coder/coder/v2/coderd/database"
2727"github.com/coder/coder/v2/coderd/tracing"
@@ -38,10 +38,10 @@ type executor struct {
3838server * server
3939mut * sync.Mutex
4040binaryPath string
41- // cachePath andworkdir must not be used by multiple processes at once.
41+ // cachePath andfiles must not be used by multiple processes at once.
4242cachePath string
4343cliConfigPath string
44- workdir string
44+ files tfpath. Layout
4545// used to capture execution times at various stages
4646timings * timingAggregator
4747}
@@ -90,7 +90,7 @@ func (e *executor) execWriteOutput(ctx, killCtx context.Context, args, env []str
9090
9191// #nosec
9292cmd := exec .CommandContext (killCtx ,e .binaryPath ,args ... )
93- cmd .Dir = e .workdir
93+ cmd .Dir = e .files . WorkDirectory ()
9494if env == nil {
9595// We don't want to passthrough host env when unset.
9696env = []string {}
@@ -131,7 +131,7 @@ func (e *executor) execParseJSON(ctx, killCtx context.Context, args, env []strin
131131
132132// #nosec
133133cmd := exec .CommandContext (killCtx ,e .binaryPath ,args ... )
134- cmd .Dir = e .workdir
134+ cmd .Dir = e .files . WorkDirectory ()
135135cmd .Env = env
136136out := & bytes.Buffer {}
137137stdErr := & bytes.Buffer {}
@@ -225,7 +225,7 @@ func (e *executor) init(ctx, killCtx context.Context, logr logSink) error {
225225defer e .mut .Unlock ()
226226
227227// Record lock file checksum before init
228- lockFilePath := filepath . Join ( e . workdir , ".terraform.lock.hcl" )
228+ lockFilePath := e . files . TerraformLockFile ( )
229229preInitChecksum := checksumFileCRC32 (ctx ,e .logger ,lockFilePath )
230230
231231outWriter ,doneOut := e .provisionLogWriter (logr )
@@ -289,14 +289,6 @@ func checksumFileCRC32(ctx context.Context, logger slog.Logger, path string) uin
289289return crc32 .ChecksumIEEE (content )
290290}
291291
292- func getPlanFilePath (workdir string )string {
293- return filepath .Join (workdir ,"terraform.tfplan" )
294- }
295-
296- func getStateFilePath (workdir string )string {
297- return filepath .Join (workdir ,"terraform.tfstate" )
298- }
299-
300292// revive:disable-next-line:flag-parameter
301293func (e * executor )plan (ctx ,killCtx context.Context ,env ,vars []string ,logr logSink ,req * proto.PlanRequest ) (* proto.PlanComplete ,error ) {
302294ctx ,span := e .server .startTrace (ctx ,tracing .FuncName ())
@@ -307,7 +299,7 @@ func (e *executor) plan(ctx, killCtx context.Context, env, vars []string, logr l
307299
308300metadata := req .Metadata
309301
310- planfilePath := getPlanFilePath ( e . workdir )
302+ planfilePath := e . files . PlanFilePath ( )
311303args := []string {
312304"plan" ,
313305"-no-color" ,
@@ -359,7 +351,7 @@ func (e *executor) plan(ctx, killCtx context.Context, env, vars []string, logr l
359351// a workspace build. This removes some added costs of sending the modules
360352// payload back to coderd if coderd is just going to ignore it.
361353if ! req .OmitModuleFiles {
362- moduleFiles ,err = GetModulesArchive (os .DirFS (e .workdir ))
354+ moduleFiles ,err = GetModulesArchive (os .DirFS (e .files . WorkDirectory () ))
363355if err != nil {
364356// TODO: we probably want to persist this error or make it louder eventually
365357e .logger .Warn (ctx ,"failed to archive terraform modules" ,slog .Error (err ))
@@ -551,7 +543,7 @@ func (e *executor) graph(ctx, killCtx context.Context) (string, error) {
551543var out strings.Builder
552544cmd := exec .CommandContext (killCtx ,e .binaryPath ,args ... )// #nosec
553545cmd .Stdout = & out
554- cmd .Dir = e .workdir
546+ cmd .Dir = e .files . WorkDirectory ()
555547cmd .Env = e .basicEnv ()
556548
557549e .server .logger .Debug (ctx ,"executing terraform command graph" ,
@@ -588,7 +580,7 @@ func (e *executor) apply(
588580"-auto-approve" ,
589581"-input=false" ,
590582"-json" ,
591- getPlanFilePath ( e . workdir ),
583+ e . files . PlanFilePath ( ),
592584}
593585
594586outWriter ,doneOut := e .provisionLogWriter (logr )
@@ -608,7 +600,7 @@ func (e *executor) apply(
608600if err != nil {
609601return nil ,err
610602}
611- statefilePath := getStateFilePath ( e . workdir )
603+ statefilePath := e . files . StateFilePath ( )
612604stateContent ,err := os .ReadFile (statefilePath )
613605if err != nil {
614606return nil ,xerrors .Errorf ("read statefile %q: %w" ,statefilePath ,err )