Skip to content

Commit 36808f1

Browse files
authored
feat!: update terraform to version 1.6.x, relax max version constraint (coder#12027)
* feat(provisioner): relax max terraform version constraint * feat!(scripts/Dockerfile.base): update bundled terraform to 1.6.x * bump terraform version in Dogfood image * fix over-zealous rename
1 parent b8e32a3 commit 36808f1

File tree

5 files changed

+40
-23
lines changed

5 files changed

+40
-23
lines changed

dogfood/Dockerfile

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -168,10 +168,9 @@ RUN apt-get update --quiet && apt-get install --yes \
168168
# Configure FIPS-compliant policies
169169
update-crypto-policies --set FIPS
170170

171-
# NOTE: In scripts/Dockerfile.base we specifically install Terraform version 1.5.7
172-
# as it is the last version licensed under the MPL. Installing the same version
173-
# here for consistency.
174-
RUN wget -O /tmp/terraform.zip "https://releases.hashicorp.com/terraform/1.5.7/terraform_1.5.7_linux_amd64.zip" && \
171+
# NOTE: In scripts/Dockerfile.base we specifically install Terraform version 1.6.6.
172+
# Installing the same version here to match.
173+
RUN wget -O /tmp/terraform.zip "https://releases.hashicorp.com/terraform/1.6.6/terraform_1.6.6_linux_amd64.zip" && \
175174
unzip /tmp/terraform.zip -d /usr/local/bin && \
176175
rm -f /tmp/terraform.zip && \
177176
chmod +x /usr/local/bin/terraform && \

provisioner/terraform/install.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ var (
1919
// TerraformVersion is the version of Terraform used internally
2020
// when Terraform is not available on the system.
2121
// NOTE: Keep this in sync with the version in scripts/Dockerfile.base.
22-
TerraformVersion = version.Must(version.NewVersion("1.4.6"))
22+
TerraformVersion = version.Must(version.NewVersion("1.6.6"))
2323

2424
minTerraformVersion = version.Must(version.NewVersion("1.1.0"))
25-
maxTerraformVersion = version.Must(version.NewVersion("1.5.9")) // use .9 to automatically allow patch releases
25+
maxTerraformVersion = version.Must(version.NewVersion("1.6.9")) // use .9 to automatically allow patch releases
2626

2727
terraformMinorVersionMismatch = xerrors.New("Terraform binary minor version mismatch.")
2828
)

provisioner/terraform/serve.go

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ type ServeOptions struct {
3939
ExitTimeout time.Duration
4040
}
4141

42-
func absoluteBinaryPath(ctx context.Context) (string, error) {
42+
func absoluteBinaryPath(ctx context.Context, logger slog.Logger) (string, error) {
4343
binaryPath, err := safeexec.LookPath("terraform")
4444
if err != nil {
4545
return "", xerrors.Errorf("Terraform binary not found: %w", err)
@@ -56,22 +56,37 @@ func absoluteBinaryPath(ctx context.Context) (string, error) {
5656
}
5757

5858
// Checking the installed version of Terraform.
59-
version, err := versionFromBinaryPath(ctx, absoluteBinary)
59+
installedVersion, err := versionFromBinaryPath(ctx, absoluteBinary)
6060
if err != nil {
6161
return "", xerrors.Errorf("Terraform binary get version failed: %w", err)
6262
}
6363

64-
if version.LessThan(minTerraformVersion) || version.GreaterThan(maxTerraformVersion) {
64+
logger.Info(ctx, "detected terraform version",
65+
slog.F("installed_version", installedVersion.String()),
66+
slog.F("min_version", maxTerraformVersion.String()),
67+
slog.F("max_version", maxTerraformVersion.String()))
68+
69+
if installedVersion.LessThan(minTerraformVersion) {
70+
logger.Warn(ctx, "installed terraform version too old, will download known good version to cache")
6571
return "", terraformMinorVersionMismatch
6672
}
6773

74+
// Warn if the installed version is newer than what we've decided is the max.
75+
// We used to ignore it and download our own version but this makes it easier
76+
// to test out newer versions of Terraform.
77+
if installedVersion.GreaterThanOrEqual(maxTerraformVersion) {
78+
logger.Warn(ctx, "installed terraform version newer than expected, you may experience bugs",
79+
slog.F("installed_version", installedVersion.String()),
80+
slog.F("max_version", maxTerraformVersion.String()))
81+
}
82+
6883
return absoluteBinary, nil
6984
}
7085

7186
// Serve starts a dRPC server on the provided transport speaking Terraform provisioner.
7287
func Serve(ctx context.Context, options *ServeOptions) error {
7388
if options.BinaryPath == "" {
74-
absoluteBinary, err := absoluteBinaryPath(ctx)
89+
absoluteBinary, err := absoluteBinaryPath(ctx, options.Logger)
7590
if err != nil {
7691
// This is an early exit to prevent extra execution in case the context is canceled.
7792
// It generally happens in unit tests since this method is asynchronous and
@@ -80,6 +95,9 @@ func Serve(ctx context.Context, options *ServeOptions) error {
8095
return xerrors.Errorf("absolute binary context canceled: %w", err)
8196
}
8297

98+
options.Logger.Warn(ctx, "no usable terraform binary found, downloading to cache dir",
99+
slog.F("terraform_version", TerraformVersion.String()),
100+
slog.F("cache_dir", options.CachePath))
83101
binPath, err := Install(ctx, options.Logger, options.CachePath, TerraformVersion)
84102
if err != nil {
85103
return xerrors.Errorf("install terraform: %w", err)

provisioner/terraform/serve_internal_test.go

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package terraform
22

33
import (
4-
"context"
54
"fmt"
65
"os"
76
"path/filepath"
@@ -11,40 +10,41 @@ import (
1110

1211
"github.com/stretchr/testify/require"
1312
"golang.org/x/xerrors"
13+
14+
"github.com/coder/coder/v2/testutil"
15+
16+
"cdr.dev/slog/sloggers/slogtest"
1417
)
1518

1619
// nolint:paralleltest
1720
func Test_absoluteBinaryPath(t *testing.T) {
18-
type args struct {
19-
ctx context.Context
20-
}
2121
tests := []struct {
2222
name string
23-
args args
2423
terraformVersion string
2524
expectedErr error
2625
}{
2726
{
2827
name: "TestCorrectVersion",
29-
args: args{ctx: context.Background()},
3028
terraformVersion: "1.3.0",
3129
expectedErr: nil,
3230
},
3331
{
3432
name: "TestOldVersion",
35-
args: args{ctx: context.Background()},
3633
terraformVersion: "1.0.9",
3734
expectedErr: terraformMinorVersionMismatch,
3835
},
3936
{
4037
name: "TestNewVersion",
41-
args: args{ctx: context.Background()},
4238
terraformVersion: "1.3.0",
4339
expectedErr: nil,
4440
},
41+
{
42+
name: "TestNewestNewVersion",
43+
terraformVersion: "9.9.9",
44+
expectedErr: nil,
45+
},
4546
{
4647
name: "TestMalformedVersion",
47-
args: args{ctx: context.Background()},
4848
terraformVersion: "version",
4949
expectedErr: xerrors.Errorf("Terraform binary get version failed: Malformed version: version"),
5050
},
@@ -56,6 +56,7 @@ func Test_absoluteBinaryPath(t *testing.T) {
5656
t.Skip("Dummy terraform executable on Windows requires sh which isn't very practical.")
5757
}
5858

59+
log := slogtest.Make(t, nil)
5960
// Create a temp dir with the binary
6061
tempDir := t.TempDir()
6162
terraformBinaryOutput := fmt.Sprintf(`#!/bin/sh
@@ -85,7 +86,8 @@ func Test_absoluteBinaryPath(t *testing.T) {
8586
expectedAbsoluteBinary = filepath.Join(tempDir, "terraform")
8687
}
8788

88-
actualAbsoluteBinary, actualErr := absoluteBinaryPath(tt.args.ctx)
89+
ctx := testutil.Context(t, testutil.WaitShort)
90+
actualAbsoluteBinary, actualErr := absoluteBinaryPath(ctx, log)
8991

9092
require.Equal(t, expectedAbsoluteBinary, actualAbsoluteBinary)
9193
if tt.expectedErr == nil {

scripts/Dockerfile.base

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,7 @@ RUN apk add --no-cache \
2626
# Terraform was disabled in the edge repo due to a build issue.
2727
# https://gitlab.alpinelinux.org/alpine/aports/-/commit/f3e263d94cfac02d594bef83790c280e045eba35
2828
# Using wget for now. Note that busybox unzip doesn't support streaming.
29-
#
30-
# WARNING: Do not update to 1.6.x, as it is the first release licensed under BSL instead of MPL.
31-
RUN ARCH="$(arch)"; if [ "${ARCH}" == "x86_64" ]; then ARCH="amd64"; elif [ "${ARCH}" == "aarch64" ]; then ARCH="arm64"; fi; wget -O /tmp/terraform.zip "https://releases.hashicorp.com/terraform/1.5.7/terraform_1.5.7_linux_${ARCH}.zip" && \
29+
RUN ARCH="$(arch)"; if [ "${ARCH}" == "x86_64" ]; then ARCH="amd64"; elif [ "${ARCH}" == "aarch64" ]; then ARCH="arm64"; fi; wget -O /tmp/terraform.zip "https://releases.hashicorp.com/terraform/1.6.6/terraform_1.6.6_linux_${ARCH}.zip" && \
3230
busybox unzip /tmp/terraform.zip -d /usr/local/bin && \
3331
rm -f /tmp/terraform.zip && \
3432
chmod +x /usr/local/bin/terraform && \

0 commit comments

Comments
 (0)