Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
chore: switch to interface to swap implementations
  • Loading branch information
Emyrk committed Nov 12, 2025
commit fcab660256e0059cf9966a83e8b5cd330872c96d
2 changes: 1 addition & 1 deletion provisioner/terraform/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ type executor struct {
// cachePath and files must not be used by multiple processes at once.
cachePath string
cliConfigPath string
files tfpath.Layout
files tfpath.LayoutInterface
// used to capture execution times at various stages
timings *timingAggregator
}
Expand Down
2 changes: 1 addition & 1 deletion provisioner/terraform/modules.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func parseModulesFile(filePath string) ([]*proto.Module, error) {
// getModules returns the modules from the modules file if it exists.
// It returns nil if the file does not exist.
// Modules become available after terraform init.
func getModules(files tfpath.Layout) ([]*proto.Module, error) {
func getModules(files tfpath.LayoutInterface) ([]*proto.Module, error) {
filePath := files.ModulesFilePath()
if _, err := os.Stat(filePath); os.IsNotExist(err) {
return nil, nil
Expand Down
2 changes: 1 addition & 1 deletion provisioner/terraform/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ func (s *server) startTrace(ctx context.Context, name string, opts ...trace.Span
))...)
}

func (s *server) executor(files tfpath.Layout, stage database.ProvisionerJobTimingStage) *executor {
func (s *server) executor(files tfpath.LayoutInterface, stage database.ProvisionerJobTimingStage) *executor {
return &executor{
server: s,
mut: s.execMut,
Expand Down
4 changes: 2 additions & 2 deletions provisionersdk/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/codersdk/drpcsdk"
"github.com/coder/coder/v2/provisionersdk/tfpath"
"github.com/coder/coder/v2/provisionersdk/x"

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

Expand Down Expand Up @@ -78,7 +79,6 @@ func (p *protoServer) Session(stream proto.DRPCProvisioner_SessionStream) error
}
}


err = s.Files.ExtractArchive(s.Context(), s.Logger, afero.NewOsFs(), s.Config)
if err != nil {
return xerrors.Errorf("extract archive: %w", err)
Expand Down Expand Up @@ -211,7 +211,7 @@ func (s *Session) handleRequests() error {

type Session struct {
Logger slog.Logger
Files tfpath.Layout
Files tfpath.LayoutInterface
Config *proto.Config

server Server
Expand Down
13 changes: 13 additions & 0 deletions provisionersdk/tfpath/tfpath.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,19 @@ import (
"github.com/coder/coder/v2/provisionersdk/proto"
)

type LayoutInterface interface {
WorkDirectory() string
StateFilePath() string
PlanFilePath() string
TerraformLockFile() string
ReadmeFilePath() string
TerraformMetadataDir() string
ModulesDirectory() string
ModulesFilePath() string
ExtractArchive(ctx context.Context, logger slog.Logger, fs afero.Fs, cfg *proto.Config) error
Cleanup(ctx context.Context, logger slog.Logger, fs afero.Fs)
}

const (
// ReadmeFile is the location we look for to extract documentation from template versions.
ReadmeFile = "README.md"
Expand Down
23 changes: 15 additions & 8 deletions provisionersdk/x/directories.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@ import (

"cdr.dev/slog"
"github.com/coder/coder/v2/provisionersdk/proto"
"github.com/coder/coder/v2/provisionersdk/tfpath"
)

var _ tfpath.LayoutInterface = (*TerraformDirectory)(nil)

func SessionDir(parentDir, sessID string, config *proto.Config) TerraformDirectory {
if config.TemplateId == "" || config.TemplateId == uuid.Nil.String() ||
config.TemplateVersionId == "" || config.TemplateVersionId == uuid.Nil.String() {
Expand Down Expand Up @@ -57,16 +60,16 @@ const (
sessionDirPrefix = "Session"
)

func (td TerraformDirectory) Cleanup(ctx context.Context, logger slog.Logger) {
func (td TerraformDirectory) Cleanup(ctx context.Context, logger slog.Logger, fs afero.Fs) {
var err error
path := td.workDirectory
path := td.WorkDirectory()
if !td.ephemeral {
// Non-ephemeral directories only clean up the session subdirectory.
// Leaving in place the wider work directory for reuse.
path = td.StateSessionDirectory()
}
for attempt := 0; attempt < 5; attempt++ {
err := os.RemoveAll(path)
err := fs.RemoveAll(path)
if err != nil {
// On Windows, open files cannot be removed.
// When the provisioner daemon is shutting down,
Expand Down Expand Up @@ -116,20 +119,24 @@ func (td TerraformDirectory) ReadmeFilePath() string {
return filepath.Join(td.WorkDirectory(), ReadmeFile)
}

func (td TerraformDirectory) TerraformMetadataDir() string {
return filepath.Join(td.WorkDirectory(), ".terraform")
}

func (td TerraformDirectory) ModulesDirectory() string {
return filepath.Join(td.WorkDirectory(), ".terraform", "modules")
return filepath.Join(td.TerraformMetadataDir(), "modules")
}

func (td TerraformDirectory) ModulesFilePath() string {
return filepath.Join(td.ModulesDirectory(), "modules.json")
}

func (td TerraformDirectory) ExtractArchive(ctx context.Context, logger slog.Logger, cfg *proto.Config) error {
func (td TerraformDirectory) ExtractArchive(ctx context.Context, logger slog.Logger, fs afero.Fs, cfg *proto.Config) error {
logger.Info(ctx, "unpacking template source archive",
slog.F("size_bytes", len(cfg.TemplateSourceArchive)),
)

err := os.MkdirAll(td.WorkDirectory(), 0o700)
err := fs.MkdirAll(td.WorkDirectory(), 0o700)
if err != nil {
return xerrors.Errorf("create work directory %q: %w", td.WorkDirectory(), err)
}
Expand Down Expand Up @@ -175,7 +182,7 @@ func (td TerraformDirectory) ExtractArchive(ctx context.Context, logger slog.Log
}
switch header.Typeflag {
case tar.TypeDir:
err = os.MkdirAll(headerPath, mode)
err = fs.MkdirAll(headerPath, mode)
if err != nil {
return xerrors.Errorf("mkdir %q: %w", headerPath, err)
}
Expand All @@ -186,7 +193,7 @@ func (td TerraformDirectory) ExtractArchive(ctx context.Context, logger slog.Log
// TODO: If we are overwriting an existing file, that means we are reusing
// the terraform directory. In that case, we should check the file content
// matches what already exists on disk.
file, err := os.OpenFile(headerPath, os.O_CREATE|os.O_RDWR|os.O_TRUNC, mode)
file, err := fs.OpenFile(headerPath, os.O_CREATE|os.O_RDWR|os.O_TRUNC, mode)
if err != nil {
return xerrors.Errorf("create file %q (mode %s): %w", headerPath, mode, err)
}
Expand Down