Skip to content
Merged
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
Implementation
  • Loading branch information
mtojek committed Sep 7, 2023
commit 20bd67c0d1e17c1a25da9ac8a4df0bb0594b08ff
70 changes: 62 additions & 8 deletions provisioner/terraform/provision.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@ import (
"strings"
"time"

"cdr.dev/slog"
"golang.org/x/xerrors"

"cdr.dev/slog"

"github.com/djherbis/times"

"github.com/coder/coder/v2/coderd/tracing"
"github.com/coder/coder/v2/provisionersdk"
"github.com/coder/coder/v2/provisionersdk/proto"
Expand Down Expand Up @@ -257,7 +260,10 @@ func logTerraformEnvVars(sink logSink) {
//
// Sample cachePath: /Users/<username>/Library/Caches/coder/provisioner-<N>/tf
func cleanStaleTerraformPlugins(ctx context.Context, cachePath string, now time.Time, logger slog.Logger) error {
// Review cached Terraform plugins
cachePath, err := filepath.Abs(cachePath) // sanity check in case the path is e.g. ../../../cache
if err != nil {
return xerrors.Errorf("unable to determine absolute path %q: %w", cachePath, err)
}

// Filter directory trees matching pattern: <repositoryURL>/<company>/<plugin>/<version>/<distribution>
filterFunc := func(path string, info os.FileInfo) bool {
Expand All @@ -278,8 +284,9 @@ func cleanStaleTerraformPlugins(ctx context.Context, cachePath string, now time.
return true
}

// Review cached Terraform plugins
var pluginPaths []string
err := filepath.Walk(cachePath, func(path string, info fs.FileInfo, err error) error {
err = filepath.Walk(cachePath, func(path string, info fs.FileInfo, err error) error {
if err != nil {
return err
}
Expand Down Expand Up @@ -310,14 +317,61 @@ func cleanStaleTerraformPlugins(ctx context.Context, cachePath string, now time.
}

// Remove stale plugins
// TODO
for _, stalePluginPath := range stalePlugins {
// Remove the plugin directory
err = os.RemoveAll(stalePluginPath)
if err != nil {
return xerrors.Errorf("unable to remove stale plugin %q: %w", stalePluginPath, err)
}

// Compact the plugin structure by removing empty directories.
wd := stalePluginPath
level := 4 // <repositoryURL>/<company>/<plugin>/<version>/<distribution>
for {
level--
if level == 0 {
break // do not compact further
}

wd = filepath.Dir(wd)

files, err := os.ReadDir(wd)
if err != nil {
return xerrors.Errorf("unable to read directory content %q: %w", wd, err)
}

// Maintain the directory tree
// TODO
if len(files) > 0 {
break // there are still other plugins
}

logger.Debug(ctx, "remove empty directory: %s", wd)
err = os.Remove(wd)
if err != nil {
return xerrors.Errorf("unable to remove directory %q: %w", wd, err)
}
}
}
return nil
}

func latestAccessTime(path string) (time.Time, error) {
// TODO
// latestAccessTime walks recursively through the directory content, and locates
// the last accessed file.
func latestAccessTime(pluginPath string) (time.Time, error) {
var latest time.Time
err := filepath.Walk(pluginPath, func(path string, info fs.FileInfo, err error) error {
if err != nil {
return err
}

timeSpec := times.Get(info)
accessTime := timeSpec.AccessTime()
if latest.Before(accessTime) {
latest = accessTime
}
return nil
})
if err != nil {
return time.Time{}, xerrors.Errorf("unable to walk the plugin path %q: %w", pluginPath, err)
}
return latest, nil
}