Skip to content

feat: Support caching provisioner assets #574

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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 28, 2022
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
feat: Support caching provisioner assets
This caches the Terraform binary, and Terraform plugins.
Eventually, it could cache other temporary files.
  • Loading branch information
kylecarbs committed Mar 26, 2022
commit 87cd77cf5b0a4d3540a93058b9335f7c5f50902c
15 changes: 12 additions & 3 deletions cli/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"net/url"
"os"
"os/signal"
"path/filepath"
"strconv"
"time"

Expand Down Expand Up @@ -42,6 +43,7 @@ func start() *cobra.Command {
var (
accessURL string
address string
cacheDir string
dev bool
postgresURL string
provisionerDaemonCount uint8
Expand Down Expand Up @@ -164,7 +166,7 @@ func start() *cobra.Command {

provisionerDaemons := make([]*provisionerd.Server, 0)
for i := uint8(0); i < provisionerDaemonCount; i++ {
daemonClose, err := newProvisionerDaemon(cmd.Context(), client, logger)
daemonClose, err := newProvisionerDaemon(cmd.Context(), client, logger, cacheDir)
if err != nil {
return xerrors.Errorf("create provisioner daemon: %w", err)
}
Expand Down Expand Up @@ -312,6 +314,12 @@ func start() *cobra.Command {
}
root.Flags().StringVarP(&accessURL, "access-url", "", os.Getenv("CODER_ACCESS_URL"), "Specifies the external URL to access Coder (uses $CODER_ACCESS_URL).")
root.Flags().StringVarP(&address, "address", "a", defaultAddress, "The address to serve the API and dashboard (uses $CODER_ADDRESS).")
// systemd uses the CACHE_DIRECTORY environment variable!
defaultCacheDir := os.Getenv("CACHE_DIRECTORY")
if defaultCacheDir == "" {
defaultCacheDir = filepath.Join(os.TempDir(), ".coder-cache")
}
root.Flags().StringVarP(&cacheDir, "cache-dir", "", defaultCacheDir, "Specify a directory to cache binaries for provision operations.")
defaultDev, _ := strconv.ParseBool(os.Getenv("CODER_DEV_MODE"))
root.Flags().BoolVarP(&dev, "dev", "", defaultDev, "Serve Coder in dev mode for tinkering (uses $CODER_DEV_MODE).")
root.Flags().StringVarP(&postgresURL, "postgres-url", "", "",
Expand Down Expand Up @@ -381,14 +389,15 @@ func createFirstUser(cmd *cobra.Command, client *codersdk.Client, cfg config.Roo
return nil
}

func newProvisionerDaemon(ctx context.Context, client *codersdk.Client, logger slog.Logger) (*provisionerd.Server, error) {
func newProvisionerDaemon(ctx context.Context, client *codersdk.Client, logger slog.Logger, cacheDir string) (*provisionerd.Server, error) {
terraformClient, terraformServer := provisionersdk.TransportPipe()
go func() {
err := terraform.Serve(ctx, &terraform.ServeOptions{
ServeOptions: &provisionersdk.ServeOptions{
Listener: terraformServer,
},
Logger: logger,
CachePath: cacheDir,
Logger: logger,
})
if err != nil {
panic(err)
Expand Down
1 change: 1 addition & 0 deletions coder.service
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ PrivateTmp=yes
PrivateDevices=yes
SecureBits=keep-caps
AmbientCapabilities=CAP_IPC_LOCK
CacheDirectory=coder
CapabilityBoundingSet=CAP_SYSLOG CAP_IPC_LOCK CAP_NET_BIND_SERVICE
NoNewPrivileges=yes
ExecStart=/usr/bin/coder start
Expand Down
8 changes: 8 additions & 0 deletions provisioner/terraform/provision.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,14 @@ func (t *terraform) Provision(stream proto.DRPCProvisioner_ProvisionStream) erro
})
}
}()
if t.cachePath != "" {
err = terraform.SetEnv(map[string]string{
"TF_PLUGIN_CACHE_DIR": t.cachePath,
})
if err != nil {
return xerrors.Errorf("set terraform plugin cache dir: %w", err)
}
}
terraform.SetStdout(writer)
t.logger.Debug(shutdown, "running initialization")
err = terraform.Init(shutdown)
Expand Down
8 changes: 6 additions & 2 deletions provisioner/terraform/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ type ServeOptions struct {
// BinaryPath specifies the "terraform" binary to use.
// If omitted, the $PATH will attempt to find it.
BinaryPath string
CachePath string
Logger slog.Logger
}

Expand All @@ -43,8 +44,9 @@ func Serve(ctx context.Context, options *ServeOptions) error {
binaryPath, err := exec.LookPath("terraform")
if err != nil {
installer := &releases.ExactVersion{
Product: product.Terraform,
Version: version.Must(version.NewVersion("1.1.7")),
InstallDir: options.CachePath,
Product: product.Terraform,
Version: version.Must(version.NewVersion("1.1.7")),
}

execPath, err := installer.Install(ctx)
Expand All @@ -58,11 +60,13 @@ func Serve(ctx context.Context, options *ServeOptions) error {
}
return provisionersdk.Serve(ctx, &terraform{
binaryPath: options.BinaryPath,
cachePath: options.CachePath,
logger: options.Logger,
}, options.ServeOptions)
}

type terraform struct {
binaryPath string
cachePath string
logger slog.Logger
}