Skip to content

Commit 33f533a

Browse files
committed
download default terraform version when minor version mismatches
1 parent 7cce7a9 commit 33f533a

File tree

1 file changed

+43
-11
lines changed

1 file changed

+43
-11
lines changed

provisioner/terraform/serve.go

+43-11
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ package terraform
22

33
import (
44
"context"
5+
"os/exec"
56
"path/filepath"
7+
"regexp"
8+
"strings"
69

710
"github.com/cli/safeexec"
811
"github.com/hashicorp/go-version"
@@ -17,6 +20,7 @@ import (
1720
// This is the exact version of Terraform used internally
1821
// when Terraform is missing on the system.
1922
const terraformVersion = "1.1.9"
23+
const versionDelimiter = "."
2024

2125
var (
2226
// The minimum version of Terraform supported by the provisioner.
@@ -45,7 +49,46 @@ type ServeOptions struct {
4549
func Serve(ctx context.Context, options *ServeOptions) error {
4650
if options.BinaryPath == "" {
4751
binaryPath, err := safeexec.LookPath("terraform")
52+
var downloadTerraform bool
4853
if err != nil {
54+
downloadTerraform = true
55+
} else {
56+
// If the "coder" binary is in the same directory as
57+
// the "terraform" binary, "terraform" is returned.
58+
//
59+
// We must resolve the absolute path for other processes
60+
// to execute this properly!
61+
absoluteBinary, err := filepath.Abs(binaryPath)
62+
if err != nil {
63+
return xerrors.Errorf("absolute: %w", err)
64+
}
65+
// Checking the installed version of Terraform.
66+
output, err := exec.Command(absoluteBinary, "version").Output()
67+
if err != nil {
68+
return xerrors.Errorf("terraform version: %w", err)
69+
}
70+
// The output for `terraform version` is:
71+
// Terraform v1.2.1
72+
// on linux_amd64
73+
versionRegex := regexp.MustCompile("Terraform v(.+)\n?.*")
74+
match := versionRegex.FindStringSubmatch(string(output))
75+
if match != nil {
76+
// match[0] is the entire string.
77+
// match[1] is the matched substring.
78+
version := match[1]
79+
terraformMinorVersion := strings.Join(strings.Split(terraformVersion, versionDelimiter)[:2], versionDelimiter)
80+
if !strings.HasPrefix(version, terraformMinorVersion) {
81+
downloadTerraform = true
82+
}
83+
} else {
84+
// Download the required Terraform version when unable to determine the existing one.
85+
downloadTerraform = true
86+
}
87+
if !downloadTerraform {
88+
options.BinaryPath = absoluteBinary
89+
}
90+
}
91+
if downloadTerraform {
4992
installer := &releases.ExactVersion{
5093
InstallDir: options.CachePath,
5194
Product: product.Terraform,
@@ -57,17 +100,6 @@ func Serve(ctx context.Context, options *ServeOptions) error {
57100
return xerrors.Errorf("install terraform: %w", err)
58101
}
59102
options.BinaryPath = execPath
60-
} else {
61-
// If the "coder" binary is in the same directory as
62-
// the "terraform" binary, "terraform" is returned.
63-
//
64-
// We must resolve the absolute path for other processes
65-
// to execute this properly!
66-
absoluteBinary, err := filepath.Abs(binaryPath)
67-
if err != nil {
68-
return xerrors.Errorf("absolute: %w", err)
69-
}
70-
options.BinaryPath = absoluteBinary
71103
}
72104
}
73105
return provisionersdk.Serve(ctx, &server{

0 commit comments

Comments
 (0)