2022-12-15 14:12:47 +00:00
|
|
|
package terraform
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2022-12-15 16:30:33 +00:00
|
|
|
"fmt"
|
|
|
|
"log"
|
|
|
|
"os"
|
2022-12-15 14:12:47 +00:00
|
|
|
"os/exec"
|
2022-12-15 16:30:33 +00:00
|
|
|
"path/filepath"
|
2022-12-15 14:12:47 +00:00
|
|
|
|
|
|
|
"github.com/databricks/bricks/bundle"
|
2022-12-15 16:30:33 +00:00
|
|
|
"github.com/databricks/bricks/bundle/config"
|
|
|
|
"github.com/hashicorp/go-version"
|
|
|
|
"github.com/hashicorp/hc-install/product"
|
|
|
|
"github.com/hashicorp/hc-install/releases"
|
2022-12-15 14:12:47 +00:00
|
|
|
"github.com/hashicorp/terraform-exec/tfexec"
|
|
|
|
)
|
|
|
|
|
|
|
|
type initialize struct{}
|
|
|
|
|
|
|
|
func (m *initialize) Name() string {
|
|
|
|
return "terraform.Initialize"
|
|
|
|
}
|
|
|
|
|
2022-12-15 16:30:33 +00:00
|
|
|
func (m *initialize) findExecPath(ctx context.Context, b *bundle.Bundle, tf *config.Terraform) (string, error) {
|
|
|
|
// If set, pass it through [exec.LookPath] to resolve its absolute path.
|
|
|
|
if tf.ExecPath != "" {
|
|
|
|
execPath, err := exec.LookPath(tf.ExecPath)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
tf.ExecPath = execPath
|
|
|
|
log.Printf("[DEBUG] Using Terraform at %s", tf.ExecPath)
|
|
|
|
return tf.ExecPath, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
binDir, err := b.CacheDir("bin")
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the execPath already exists, return it.
|
|
|
|
execPath := filepath.Join(binDir, product.Terraform.BinaryName())
|
|
|
|
_, err = os.Stat(execPath)
|
|
|
|
if err != nil && !os.IsNotExist(err) {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
if err == nil {
|
|
|
|
tf.ExecPath = execPath
|
|
|
|
log.Printf("[DEBUG] Using Terraform at %s", tf.ExecPath)
|
|
|
|
return tf.ExecPath, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Download Terraform to private bin directory.
|
|
|
|
installer := &releases.LatestVersion{
|
|
|
|
Product: product.Terraform,
|
|
|
|
Constraints: version.MustConstraints(version.NewConstraint("<2.0")),
|
|
|
|
InstallDir: binDir,
|
|
|
|
}
|
|
|
|
execPath, err = installer.Install(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return "", fmt.Errorf("error downloading Terraform: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
tf.ExecPath = execPath
|
|
|
|
log.Printf("[DEBUG] Using Terraform at %s", tf.ExecPath)
|
|
|
|
return tf.ExecPath, nil
|
|
|
|
}
|
|
|
|
|
2022-12-15 14:12:47 +00:00
|
|
|
func (m *initialize) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutator, error) {
|
2022-12-15 16:30:33 +00:00
|
|
|
tfConfig := b.Config.Bundle.Terraform
|
|
|
|
if tfConfig == nil {
|
|
|
|
tfConfig = &config.Terraform{}
|
|
|
|
b.Config.Bundle.Terraform = tfConfig
|
|
|
|
}
|
|
|
|
|
|
|
|
execPath, err := m.findExecPath(ctx, b, tfConfig)
|
2022-12-15 14:12:47 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2022-12-15 16:30:33 +00:00
|
|
|
workingDir, err := Dir(b)
|
2022-12-15 14:12:47 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
tf, err := tfexec.NewTerraform(workingDir, execPath)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
b.Terraform = tf
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func Initialize() bundle.Mutator {
|
|
|
|
return &initialize{}
|
|
|
|
}
|