mirror of https://github.com/coder/coder.git
feat: Support caching provisioner assets (#574)
* feat: Add AWS instance identity authentication This allows zero-trust authentication for all AWS instances. Prior to this, AWS instances could be used by passing `CODER_TOKEN` as an environment variable to the startup script. AWS explicitly states that secrets should not be passed in startup scripts because it's user-readable. * feat: Support caching provisioner assets This caches the Terraform binary, and Terraform plugins. Eventually, it could cache other temporary files. * chore: fix linter Co-authored-by: Garrett <garrett@coder.com>
This commit is contained in:
parent
9485fd62da
commit
13cef7d07c
11
cli/start.go
11
cli/start.go
|
@ -13,6 +13,7 @@ import (
|
|||
"net/url"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/briandowns/spinner"
|
||||
|
@ -42,6 +43,7 @@ func start() *cobra.Command {
|
|||
var (
|
||||
accessURL string
|
||||
address string
|
||||
cacheDir string
|
||||
dev bool
|
||||
postgresURL string
|
||||
// provisionerDaemonCount is a uint8 to ensure a number > 0.
|
||||
|
@ -161,7 +163,7 @@ func start() *cobra.Command {
|
|||
|
||||
provisionerDaemons := make([]*provisionerd.Server, 0)
|
||||
for i := 0; uint8(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)
|
||||
}
|
||||
|
@ -305,6 +307,8 @@ func start() *cobra.Command {
|
|||
|
||||
cliflag.StringVarP(root.Flags(), &accessURL, "access-url", "", "CODER_ACCESS_URL", "", "Specifies the external URL to access Coder")
|
||||
cliflag.StringVarP(root.Flags(), &address, "address", "a", "CODER_ADDRESS", "127.0.0.1:3000", "The address to serve the API and dashboard")
|
||||
// systemd uses the CACHE_DIRECTORY environment variable!
|
||||
cliflag.StringVarP(root.Flags(), &cacheDir, "cache-dir", "", "CACHE_DIRECTORY", filepath.Join(os.TempDir(), ".coder-cache"), "Specifies a directory to cache binaries for provision operations.")
|
||||
cliflag.BoolVarP(root.Flags(), &dev, "dev", "", "CODER_DEV_MODE", false, "Serve Coder in dev mode for tinkering")
|
||||
cliflag.StringVarP(root.Flags(), &postgresURL, "postgres-url", "", "CODER_PG_CONNECTION_URL", "", "URL of a PostgreSQL database to connect to")
|
||||
cliflag.Uint8VarP(root.Flags(), &provisionerDaemonCount, "provisioner-daemons", "", "CODER_PROVISIONER_DAEMONS", 1, "The amount of provisioner daemons to create on start.")
|
||||
|
@ -358,14 +362,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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue