mirror of https://github.com/coder/coder.git
feat!: update terraform to version 1.6.x, relax max version constraint (#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
This commit is contained in:
parent
b8e32a37de
commit
36808f19dc
|
@ -168,10 +168,9 @@ RUN apt-get update --quiet && apt-get install --yes \
|
||||||
# Configure FIPS-compliant policies
|
# Configure FIPS-compliant policies
|
||||||
update-crypto-policies --set FIPS
|
update-crypto-policies --set FIPS
|
||||||
|
|
||||||
# NOTE: In scripts/Dockerfile.base we specifically install Terraform version 1.5.7
|
# NOTE: In scripts/Dockerfile.base we specifically install Terraform version 1.6.6.
|
||||||
# as it is the last version licensed under the MPL. Installing the same version
|
# Installing the same version here to match.
|
||||||
# here for consistency.
|
RUN wget -O /tmp/terraform.zip "https://releases.hashicorp.com/terraform/1.6.6/terraform_1.6.6_linux_amd64.zip" && \
|
||||||
RUN wget -O /tmp/terraform.zip "https://releases.hashicorp.com/terraform/1.5.7/terraform_1.5.7_linux_amd64.zip" && \
|
|
||||||
unzip /tmp/terraform.zip -d /usr/local/bin && \
|
unzip /tmp/terraform.zip -d /usr/local/bin && \
|
||||||
rm -f /tmp/terraform.zip && \
|
rm -f /tmp/terraform.zip && \
|
||||||
chmod +x /usr/local/bin/terraform && \
|
chmod +x /usr/local/bin/terraform && \
|
||||||
|
|
|
@ -19,10 +19,10 @@ var (
|
||||||
// TerraformVersion is the version of Terraform used internally
|
// TerraformVersion is the version of Terraform used internally
|
||||||
// when Terraform is not available on the system.
|
// when Terraform is not available on the system.
|
||||||
// NOTE: Keep this in sync with the version in scripts/Dockerfile.base.
|
// NOTE: Keep this in sync with the version in scripts/Dockerfile.base.
|
||||||
TerraformVersion = version.Must(version.NewVersion("1.4.6"))
|
TerraformVersion = version.Must(version.NewVersion("1.6.6"))
|
||||||
|
|
||||||
minTerraformVersion = version.Must(version.NewVersion("1.1.0"))
|
minTerraformVersion = version.Must(version.NewVersion("1.1.0"))
|
||||||
maxTerraformVersion = version.Must(version.NewVersion("1.5.9")) // use .9 to automatically allow patch releases
|
maxTerraformVersion = version.Must(version.NewVersion("1.6.9")) // use .9 to automatically allow patch releases
|
||||||
|
|
||||||
terraformMinorVersionMismatch = xerrors.New("Terraform binary minor version mismatch.")
|
terraformMinorVersionMismatch = xerrors.New("Terraform binary minor version mismatch.")
|
||||||
)
|
)
|
||||||
|
|
|
@ -39,7 +39,7 @@ type ServeOptions struct {
|
||||||
ExitTimeout time.Duration
|
ExitTimeout time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
func absoluteBinaryPath(ctx context.Context) (string, error) {
|
func absoluteBinaryPath(ctx context.Context, logger slog.Logger) (string, error) {
|
||||||
binaryPath, err := safeexec.LookPath("terraform")
|
binaryPath, err := safeexec.LookPath("terraform")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", xerrors.Errorf("Terraform binary not found: %w", err)
|
return "", xerrors.Errorf("Terraform binary not found: %w", err)
|
||||||
|
@ -56,22 +56,37 @@ func absoluteBinaryPath(ctx context.Context) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checking the installed version of Terraform.
|
// Checking the installed version of Terraform.
|
||||||
version, err := versionFromBinaryPath(ctx, absoluteBinary)
|
installedVersion, err := versionFromBinaryPath(ctx, absoluteBinary)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", xerrors.Errorf("Terraform binary get version failed: %w", err)
|
return "", xerrors.Errorf("Terraform binary get version failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if version.LessThan(minTerraformVersion) || version.GreaterThan(maxTerraformVersion) {
|
logger.Info(ctx, "detected terraform version",
|
||||||
|
slog.F("installed_version", installedVersion.String()),
|
||||||
|
slog.F("min_version", maxTerraformVersion.String()),
|
||||||
|
slog.F("max_version", maxTerraformVersion.String()))
|
||||||
|
|
||||||
|
if installedVersion.LessThan(minTerraformVersion) {
|
||||||
|
logger.Warn(ctx, "installed terraform version too old, will download known good version to cache")
|
||||||
return "", terraformMinorVersionMismatch
|
return "", terraformMinorVersionMismatch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Warn if the installed version is newer than what we've decided is the max.
|
||||||
|
// We used to ignore it and download our own version but this makes it easier
|
||||||
|
// to test out newer versions of Terraform.
|
||||||
|
if installedVersion.GreaterThanOrEqual(maxTerraformVersion) {
|
||||||
|
logger.Warn(ctx, "installed terraform version newer than expected, you may experience bugs",
|
||||||
|
slog.F("installed_version", installedVersion.String()),
|
||||||
|
slog.F("max_version", maxTerraformVersion.String()))
|
||||||
|
}
|
||||||
|
|
||||||
return absoluteBinary, nil
|
return absoluteBinary, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Serve starts a dRPC server on the provided transport speaking Terraform provisioner.
|
// Serve starts a dRPC server on the provided transport speaking Terraform provisioner.
|
||||||
func Serve(ctx context.Context, options *ServeOptions) error {
|
func Serve(ctx context.Context, options *ServeOptions) error {
|
||||||
if options.BinaryPath == "" {
|
if options.BinaryPath == "" {
|
||||||
absoluteBinary, err := absoluteBinaryPath(ctx)
|
absoluteBinary, err := absoluteBinaryPath(ctx, options.Logger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// This is an early exit to prevent extra execution in case the context is canceled.
|
// This is an early exit to prevent extra execution in case the context is canceled.
|
||||||
// It generally happens in unit tests since this method is asynchronous and
|
// It generally happens in unit tests since this method is asynchronous and
|
||||||
|
@ -80,6 +95,9 @@ func Serve(ctx context.Context, options *ServeOptions) error {
|
||||||
return xerrors.Errorf("absolute binary context canceled: %w", err)
|
return xerrors.Errorf("absolute binary context canceled: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
options.Logger.Warn(ctx, "no usable terraform binary found, downloading to cache dir",
|
||||||
|
slog.F("terraform_version", TerraformVersion.String()),
|
||||||
|
slog.F("cache_dir", options.CachePath))
|
||||||
binPath, err := Install(ctx, options.Logger, options.CachePath, TerraformVersion)
|
binPath, err := Install(ctx, options.Logger, options.CachePath, TerraformVersion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return xerrors.Errorf("install terraform: %w", err)
|
return xerrors.Errorf("install terraform: %w", err)
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package terraform
|
package terraform
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -11,40 +10,41 @@ import (
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
|
"github.com/coder/coder/v2/testutil"
|
||||||
|
|
||||||
|
"cdr.dev/slog/sloggers/slogtest"
|
||||||
)
|
)
|
||||||
|
|
||||||
// nolint:paralleltest
|
// nolint:paralleltest
|
||||||
func Test_absoluteBinaryPath(t *testing.T) {
|
func Test_absoluteBinaryPath(t *testing.T) {
|
||||||
type args struct {
|
|
||||||
ctx context.Context
|
|
||||||
}
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
args args
|
|
||||||
terraformVersion string
|
terraformVersion string
|
||||||
expectedErr error
|
expectedErr error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "TestCorrectVersion",
|
name: "TestCorrectVersion",
|
||||||
args: args{ctx: context.Background()},
|
|
||||||
terraformVersion: "1.3.0",
|
terraformVersion: "1.3.0",
|
||||||
expectedErr: nil,
|
expectedErr: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "TestOldVersion",
|
name: "TestOldVersion",
|
||||||
args: args{ctx: context.Background()},
|
|
||||||
terraformVersion: "1.0.9",
|
terraformVersion: "1.0.9",
|
||||||
expectedErr: terraformMinorVersionMismatch,
|
expectedErr: terraformMinorVersionMismatch,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "TestNewVersion",
|
name: "TestNewVersion",
|
||||||
args: args{ctx: context.Background()},
|
|
||||||
terraformVersion: "1.3.0",
|
terraformVersion: "1.3.0",
|
||||||
expectedErr: nil,
|
expectedErr: nil,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "TestNewestNewVersion",
|
||||||
|
terraformVersion: "9.9.9",
|
||||||
|
expectedErr: nil,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "TestMalformedVersion",
|
name: "TestMalformedVersion",
|
||||||
args: args{ctx: context.Background()},
|
|
||||||
terraformVersion: "version",
|
terraformVersion: "version",
|
||||||
expectedErr: xerrors.Errorf("Terraform binary get version failed: Malformed version: version"),
|
expectedErr: xerrors.Errorf("Terraform binary get version failed: Malformed version: version"),
|
||||||
},
|
},
|
||||||
|
@ -56,6 +56,7 @@ func Test_absoluteBinaryPath(t *testing.T) {
|
||||||
t.Skip("Dummy terraform executable on Windows requires sh which isn't very practical.")
|
t.Skip("Dummy terraform executable on Windows requires sh which isn't very practical.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log := slogtest.Make(t, nil)
|
||||||
// Create a temp dir with the binary
|
// Create a temp dir with the binary
|
||||||
tempDir := t.TempDir()
|
tempDir := t.TempDir()
|
||||||
terraformBinaryOutput := fmt.Sprintf(`#!/bin/sh
|
terraformBinaryOutput := fmt.Sprintf(`#!/bin/sh
|
||||||
|
@ -85,7 +86,8 @@ func Test_absoluteBinaryPath(t *testing.T) {
|
||||||
expectedAbsoluteBinary = filepath.Join(tempDir, "terraform")
|
expectedAbsoluteBinary = filepath.Join(tempDir, "terraform")
|
||||||
}
|
}
|
||||||
|
|
||||||
actualAbsoluteBinary, actualErr := absoluteBinaryPath(tt.args.ctx)
|
ctx := testutil.Context(t, testutil.WaitShort)
|
||||||
|
actualAbsoluteBinary, actualErr := absoluteBinaryPath(ctx, log)
|
||||||
|
|
||||||
require.Equal(t, expectedAbsoluteBinary, actualAbsoluteBinary)
|
require.Equal(t, expectedAbsoluteBinary, actualAbsoluteBinary)
|
||||||
if tt.expectedErr == nil {
|
if tt.expectedErr == nil {
|
||||||
|
|
|
@ -26,9 +26,7 @@ RUN apk add --no-cache \
|
||||||
# Terraform was disabled in the edge repo due to a build issue.
|
# Terraform was disabled in the edge repo due to a build issue.
|
||||||
# https://gitlab.alpinelinux.org/alpine/aports/-/commit/f3e263d94cfac02d594bef83790c280e045eba35
|
# https://gitlab.alpinelinux.org/alpine/aports/-/commit/f3e263d94cfac02d594bef83790c280e045eba35
|
||||||
# Using wget for now. Note that busybox unzip doesn't support streaming.
|
# Using wget for now. Note that busybox unzip doesn't support streaming.
|
||||||
#
|
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" && \
|
||||||
# WARNING: Do not update to 1.6.x, as it is the first release licensed under BSL instead of MPL.
|
|
||||||
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" && \
|
|
||||||
busybox unzip /tmp/terraform.zip -d /usr/local/bin && \
|
busybox unzip /tmp/terraform.zip -d /usr/local/bin && \
|
||||||
rm -f /tmp/terraform.zip && \
|
rm -f /tmp/terraform.zip && \
|
||||||
chmod +x /usr/local/bin/terraform && \
|
chmod +x /usr/local/bin/terraform && \
|
||||||
|
|
Loading…
Reference in New Issue