@@ -2,7 +2,10 @@ package terraform
2
2
3
3
import (
4
4
"context"
5
+ "os/exec"
5
6
"path/filepath"
7
+ "regexp"
8
+ "strings"
6
9
7
10
"github.com/cli/safeexec"
8
11
"github.com/hashicorp/go-version"
@@ -17,6 +20,7 @@ import (
17
20
// This is the exact version of Terraform used internally
18
21
// when Terraform is missing on the system.
19
22
const terraformVersion = "1.1.9"
23
+ const versionDelimiter = "."
20
24
21
25
var (
22
26
// The minimum version of Terraform supported by the provisioner.
@@ -45,7 +49,46 @@ type ServeOptions struct {
45
49
func Serve (ctx context.Context , options * ServeOptions ) error {
46
50
if options .BinaryPath == "" {
47
51
binaryPath , err := safeexec .LookPath ("terraform" )
52
+ var downloadTerraform bool
48
53
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 {
49
92
installer := & releases.ExactVersion {
50
93
InstallDir : options .CachePath ,
51
94
Product : product .Terraform ,
@@ -57,17 +100,6 @@ func Serve(ctx context.Context, options *ServeOptions) error {
57
100
return xerrors .Errorf ("install terraform: %w" , err )
58
101
}
59
102
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
71
103
}
72
104
}
73
105
return provisionersdk .Serve (ctx , & server {
0 commit comments