Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

chore: implement persistent terraform directories (experimental)#20563

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Draft
Emyrk wants to merge3 commits intostevenmasley/cache_init_exp
base:stevenmasley/cache_init_exp
Choose a base branch
Loading
fromstevenmasley/cache_init_feature
Draft
Show file tree
Hide file tree
Changes fromall commits
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
6 changes: 5 additions & 1 deletioncoderd/provisionerdserver/provisionerdserver.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -698,6 +698,7 @@ func (s *server) acquireProtoJob(ctx context.Context, job database.ProvisionerJo
}
}

activeVersion := template.ActiveVersionID == templateVersion.ID
protoJob.Type = &proto.AcquiredJob_WorkspaceBuild_{
WorkspaceBuild: &proto.AcquiredJob_WorkspaceBuild{
WorkspaceBuildId: workspaceBuild.ID.String(),
Expand All@@ -707,7 +708,9 @@ func (s *server) acquireProtoJob(ctx context.Context, job database.ProvisionerJo
PreviousParameterValues: convertRichParameterValues(lastWorkspaceBuildParameters),
VariableValues: asVariableValues(templateVariables),
ExternalAuthProviders: externalAuthProviders,
TerraformWorkspaceReuse: false, // TODO: Toggle based on experiment
// If active and experiment is enabled, allow workspace reuse existing TF
// workspaces (directories) for a faster startup.
TerraformWorkspaceReuse: activeVersion && s.Experiments.Enabled(codersdk.ExperimentTerraformWorkspace),
Metadata: &sdkproto.Metadata{
CoderUrl: s.AccessURL.String(),
WorkspaceTransition: transition,
Expand All@@ -721,6 +724,7 @@ func (s *server) acquireProtoJob(ctx context.Context, job database.ProvisionerJo
WorkspaceOwnerId: owner.ID.String(),
TemplateId: template.ID.String(),
TemplateName: template.Name,
TemplateVersionId: templateVersion.ID.String(),
TemplateVersion: templateVersion.Name,
WorkspaceOwnerSessionToken: sessionToken,
WorkspaceOwnerSshPublicKey: ownerSSHPublicKey,
Expand Down
8 changes: 6 additions & 2 deletionsprovisioner/terraform/executor.go
View file
Open in desktop
Original file line numberDiff line numberDiff 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 DownExpand Up@@ -536,7 +536,11 @@ func (e *executor) graph(ctx, killCtx context.Context) (string, error) {
if err != nil {
return "", err
}
args := []string{"graph"}
args := []string{
"graph",
// TODO: When the plan is present, we should probably use it?
//"-plan=" + e.files.PlanFilePath(),
}
if ver.GreaterThanOrEqual(version170) {
args = append(args, "-type=plan")
}
Expand Down
2 changes: 1 addition & 1 deletionprovisioner/terraform/modules.go
View file
Open in desktop
Original file line numberDiff line numberDiff 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.
funcgetModules(files tfpath.Layout) ([]*proto.Module,error) {
funcgetModules(files tfpath.LayoutInterface) ([]*proto.Module,error) {
filePath:=files.ModulesFilePath()
if_,err:=os.Stat(filePath);os.IsNotExist(err) {
returnnil,nil
Expand Down
2 changes: 1 addition & 1 deletionprovisioner/terraform/serve.go
View file
Open in desktop
Original file line numberDiff line numberDiff 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
5 changes: 3 additions & 2 deletionsprovisionerd/provisionerd_test.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,6 +26,7 @@ import (
"github.com/coder/coder/v2/provisionerd/proto"
"github.com/coder/coder/v2/provisionersdk"
sdkproto"github.com/coder/coder/v2/provisionersdk/proto"
"github.com/coder/coder/v2/provisionersdk/tfpath"
"github.com/coder/coder/v2/testutil"
)

Expand DownExpand Up@@ -318,8 +319,8 @@ func TestProvisionerd(t *testing.T) {
JobId:"test",
Provisioner:"someprovisioner",
TemplateSourceArchive:testutil.CreateTar(t,map[string]string{
"test.txt":"content",
provisionersdk.ReadmeFile:"# A cool template 😎\n",
"test.txt":"content",
tfpath.ReadmeFile:"# A cool template 😎\n",
}),
Type:&proto.AcquiredJob_TemplateImport_{
TemplateImport:&proto.AcquiredJob_TemplateImport{
Expand Down
48 changes: 0 additions & 48 deletionsprovisionersdk/cleanup.go
View file
Open in desktop

This file was deleted.

13 changes: 9 additions & 4 deletionsprovisionersdk/cleanup_test.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -11,7 +11,6 @@ import (
"github.com/stretchr/testify/require"

"cdr.dev/slog"
"github.com/coder/coder/v2/provisionersdk"
"github.com/coder/coder/v2/provisionersdk/tfpath"
"github.com/coder/coder/v2/testutil"
)
Expand DownExpand Up@@ -47,9 +46,11 @@ func TestStaleSessions(t *testing.T) {
addSessionFolder(t,fs,second,now.Add(-8*24*time.Hour))
third:=tfpath.Session(workDirectory,uuid.NewString())
addSessionFolder(t,fs,third,now.Add(-9*24*time.Hour))
tfDir:=tfpath.FromWorkingDirectory(workDirectory)

// when
provisionersdk.CleanStaleSessions(ctx,workDirectory,fs,now,logger)
err:=tfDir.CleanStaleSessions(ctx,logger,fs,now)
require.NoError(t,err)

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

// when
provisionersdk.CleanStaleSessions(ctx,workDirectory,fs,now,logger)
err:=tfDir.CleanStaleSessions(ctx,logger,fs,now)
require.NoError(t,err)

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

// when
provisionersdk.CleanStaleSessions(ctx,workDirectory,fs,now,logger)
err:=tfDir.CleanStaleSessions(ctx,logger,fs,now)
require.NoError(t,err)

// then
entries,err:=afero.ReadDir(fs,workDirectory)
Expand Down
27 changes: 13 additions & 14 deletionsprovisionersdk/session.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,22 +13,16 @@ import (
"golang.org/x/xerrors"

"cdr.dev/slog"
"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/tfpath/x"

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

"github.com/coder/coder/v2/provisionersdk/proto"
)

const (
// ReadmeFile is the location we look for to extract documentation from template versions.
ReadmeFile = "README.md"

sessionDirPrefix = "Session"
staleSessionRetention = 7 * 24 * time.Hour
)

// protoServer is a wrapper that translates the dRPC protocol into a Session with method calls into the Server.
type protoServer struct {
server Server
Expand All@@ -43,11 +37,6 @@ func (p *protoServer) Session(stream proto.DRPCProvisioner_SessionStream) error
server: p.server,
}

err := CleanStaleSessions(s.Context(), p.opts.WorkDirectory, afero.NewOsFs(), time.Now(), s.Logger)
if err != nil {
return xerrors.Errorf("unable to clean stale sessions %q: %w", s.Files, err)
}

s.Files = tfpath.Session(p.opts.WorkDirectory, sessID)

defer func() {
Expand All@@ -67,6 +56,16 @@ func (p *protoServer) Session(stream proto.DRPCProvisioner_SessionStream) error
s.logLevel = proto.LogLevel_value[strings.ToUpper(s.Config.ProvisionerLogLevel)]
}

if p.opts.Experiments.Enabled(codersdk.ExperimentTerraformWorkspace) {
s.Files = x.SessionDir(p.opts.WorkDirectory, sessID, config)
}

// Cleanup any previously left stale sessions.
err = s.Files.CleanStaleSessions(s.Context(), s.Logger, afero.NewOsFs(), time.Now())
if err != nil {
return xerrors.Errorf("unable to clean stale sessions %q: %w", s.Files, err)
}

// Extract the template source archive into the work directory.
err = s.Files.ExtractArchive(s.Context(), s.Logger, afero.NewOsFs(), s.Config)
if err != nil {
Expand DownExpand Up@@ -202,7 +201,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
60 changes: 59 additions & 1 deletionprovisionersdk/tfpath/tfpath.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -19,11 +19,28 @@ 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)
CleanStaleSessions(ctx context.Context, logger slog.Logger, fs afero.Fs, now time.Time) error
}

var _ LayoutInterface = (*Layout)(nil)

const (
// ReadmeFile is the location we look for to extract documentation from template versions.
ReadmeFile = "README.md"

sessionDirPrefix = "Session"
sessionDirPrefix = "Session"
staleSessionRetention = 7 * 24 * time.Hour
)

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

func FromWorkingDirectory(workDir string) Layout {
return Layout(workDir)
}

// Layout is the terraform execution working directory structure.
// It also contains some methods for common file operations within that layout.
// Such as "Cleanup" and "ExtractArchive".
Expand DownExpand Up@@ -189,3 +210,40 @@ func (l Layout) Cleanup(ctx context.Context, logger slog.Logger, fs afero.Fs) {
logger.Error(ctx, "failed to clean up work directory after multiple attempts",
slog.F("path", path), slog.Error(err))
}

// CleanStaleSessions browses the work directory searching for stale session
// directories. Coder provisioner is supposed to remove them once after finishing the provisioning,
// but there is a risk of keeping them in case of a failure.
func (l Layout) CleanStaleSessions(ctx context.Context, logger slog.Logger, fs afero.Fs, now time.Time) error {
parent := filepath.Dir(l.WorkDirectory())
entries, err := afero.ReadDir(fs, filepath.Dir(l.WorkDirectory()))
if err != nil {
return xerrors.Errorf("can't read %q directory", parent)
}

for _, fi := range entries {
dirName := fi.Name()

if fi.IsDir() && isValidSessionDir(dirName) {
sessionDirPath := filepath.Join(parent, dirName)

modTime := fi.ModTime() // fallback to modTime if modTime is not available (afero)

if modTime.Add(staleSessionRetention).After(now) {
continue
}

logger.Info(ctx, "remove stale session directory", slog.F("session_path", sessionDirPath))
err = fs.RemoveAll(sessionDirPath)
if err != nil {
return xerrors.Errorf("can't remove %q directory: %w", sessionDirPath, err)
}
}
}
return nil
}

func isValidSessionDir(dirName string) bool {
match, err := filepath.Match(sessionDirPrefix+"*", dirName)
return err == nil && match
}
Loading
Loading

[8]ページ先頭

©2009-2025 Movatter.jp