Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Terratest build fixes #1395

Merged
merged 21 commits into from
Jul 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ env: &env
MODULE_GCP_CI_VERSION: v0.1.1
MODULE_CI_CIRCLECI_HELPER_VERSION: v0.56.0
TERRAFORM_VERSION: 1.5.7
PACKER_VERSION: 1.7.4
PACKER_VERSION: 1.10.0
TERRAGRUNT_VERSION: v0.52.0
OPA_VERSION: v0.33.1
GO_VERSION: 1.21.1
Expand Down
4 changes: 4 additions & 0 deletions examples/packer-docker-example/build.pkr.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ packer {
version = ">=v1.0.0"
source = "github.com/hashicorp/amazon"
}
docker = {
version = ">=v1.0.1"
source = "github.com/hashicorp/docker"
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion examples/packer-docker-example/configure-sinatra-app.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ sudo apt-get update
sudo apt-get install -y make zlib1g-dev build-essential ruby ruby-dev

echo "Installing Sinatra"
sudo gem install sinatra json
sudo gem install sinatra json rackup

echo "Moving $APP_RB_SRC to $APP_RB_DST"
mkdir -p "$(dirname "$APP_RB_DST")"
Expand Down
4 changes: 2 additions & 2 deletions examples/terraform-aws-lambda-example/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ resource "aws_lambda_function" "lambda" {
source_code_hash = data.archive_file.zip.output_base64sha256
function_name = var.function_name
role = aws_iam_role.lambda.arn
handler = "lambda"
runtime = "go1.x"
handler = "bootstrap"
runtime = "provided.al2023"
}

resource "aws_iam_role" "lambda" {
Expand Down
2 changes: 1 addition & 1 deletion examples/terraform-aws-lambda-example/src/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
The lambda executable `handler` was built using

``` shell
go build lambda.go
go build bootstrap.go
```
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ type Event struct {
}

// Fails if ShouldFail is `true`, otherwise echos the input.
func HandleRequest(ctx context.Context, evnt Event) (string, error) {
func HandleRequest(ctx context.Context, evnt *Event) (string, error) {
if evnt == nil {
return "", fmt.Errorf("received nil event")
}
if evnt.ShouldFail {
return "", fmt.Errorf("Failed to handle %#v", evnt)
}
Expand Down
Binary file removed examples/terraform-aws-lambda-example/src/lambda
Binary file not shown.
2 changes: 1 addition & 1 deletion examples/terraform-ssh-password-example/user_data.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ adduser --disabled-password --gecos "" terratest
echo "terratest:${terratest_password}" | chpasswd

# Enable password auth on the SSH service
sed -i 's/^PasswordAuthentication no$/PasswordAuthentication yes/g' /etc/ssh/sshd_config
echo "PasswordAuthentication yes" > /etc/ssh/sshd_config.d/01-password-auth.conf

# Bounce the service to apply the config change
service ssh restart
6 changes: 3 additions & 3 deletions modules/aws/rds_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ func TestGetRecommendedRdsInstanceTypeHappyPath(t *testing.T) {
region: "us-east-2",
databaseEngine: "mysql",
engineMajorVersion: "8.0",
instanceTypes: []string{"db.t2.micro", "db.t3.micro", "db.t3.small"},
expected: "db.t2.micro",
instanceTypes: []string{"db.t4g.micro", "db.t4g.small"},
expected: "db.t4g.micro",
},
{
name: "EU region, postgres, 2nd offering available based on region",
Expand Down Expand Up @@ -121,7 +121,7 @@ func TestGetRecommendedRdsInstanceTypeErrors(t *testing.T) {
name: "No instance type available for engine",
region: "us-east-1",
databaseEngine: "oracle-ee",
databaseEngineVersion: "19.0.0.0.ru-2021-01.rur-2021-01.r1",
databaseEngineVersion: "19.0.0.0.ru-2024-04.rur-2024-04.r1",
instanceTypes: []string{"db.r5a.large"},
},
{
Expand Down
4 changes: 2 additions & 2 deletions modules/helm/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ func RenderTemplateE(t testing.TestingT, options *Options, chartDir string, rele
return RunHelmCommandAndGetStdOutE(t, options, "template", args...)
}

// RenderTemplate runs `helm template` to render a *remote* chart given the provided options and returns stdout/stderr from
// RenderRemoteTemplate runs `helm template` to render a *remote* chart given the provided options and returns stdout/stderr from
// the template command. If you pass in templateFiles, this will only render those templates. This function will fail
// the test if there is an error rendering the template.
func RenderRemoteTemplate(t testing.TestingT, options *Options, chartURL string, releaseName string, templateFiles []string, extraHelmArgs ...string) string {
Expand All @@ -86,7 +86,7 @@ func RenderRemoteTemplate(t testing.TestingT, options *Options, chartURL string,
return out
}

// RenderTemplate runs `helm template` to render a *remote* helm chart given the provided options and returns stdout/stderr from
// RenderRemoteTemplateE runs `helm template` to render a *remote* helm chart given the provided options and returns stdout/stderr from
// the template command. If you pass in templateFiles, this will only render those templates.
func RenderRemoteTemplateE(t testing.TestingT, options *Options, chartURL string, releaseName string, templateFiles []string, extraHelmArgs ...string) (string, error) {
// Now construct the args
Expand Down
68 changes: 28 additions & 40 deletions modules/helm/template_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,33 @@ func TestRemoteChartRender(t *testing.T) {
// Test that we can dump all the manifest locally a remote chart (e.g bitnami/nginx)
// so that I can use them later to compare between two versions of the same chart for example
func TestRemoteChartRenderDump(t *testing.T) {
t.Parallel()
renderChartDump(t, "13.2.20", t.TempDir())
}

// Test that we can diff all the manifest to a local snapshot using a remote chart (e.g bitnami/nginx)
func TestRemoteChartRenderDiff(t *testing.T) {
t.Parallel()

initialSnapshot := t.TempDir()
updatedSnapshot := t.TempDir()
renderChartDump(t, "5.0.0", initialSnapshot)
output := renderChartDump(t, "5.1.0", updatedSnapshot)

options := &Options{
Logger: logger.Default,
SnapshotPath: initialSnapshot,
}
// diff in: spec.initContainers.preserve-logs-symlinks.imag, spec.containers.nginx.image, tls certificates
require.Equal(t, 5, DiffAgainstSnapshot(t, options, output, "nginx"))
}

// render chart dump and return the rendered output
func renderChartDump(t *testing.T, remoteChartVersion, snapshotDir string) string {
const (
remoteChartSource = "https://charts.bitnami.com/bitnami"
remoteChartName = "nginx"
remoteChartVersion = "13.2.20"
// need to set a fix name for the namespace so it is not flag as a difference
remoteChartSource = "https://charts.bitnami.com/bitnami"
remoteChartName = "nginx"
// need to set a fix name for the namespace, so it is not flag as a difference
namespaceName = "dump-ns"
)

Expand Down Expand Up @@ -106,42 +128,8 @@ func TestRemoteChartRenderDump(t *testing.T) {
// write chart manifest to a local filesystem directory
options = &Options{
Logger: logger.Default,
SnapshotPath: "__chart_manifests_snapshot__",
SnapshotPath: snapshotDir,
}
UpdateSnapshot(t, options, output, releaseName)
}

// Test that we can diff all the manifest to a local snapshot using a remote chart (e.g bitnami/nginx)
func TestRemoteChartRenderDiff(t *testing.T) {
const (
remoteChartSource = "https://charts.bitnami.com/bitnami"
remoteChartName = "nginx"
remoteChartVersion = "13.2.24"
// need to set a fix name for the namespace so it is not flag as a difference
namespaceName = "dump-ns"
)

releaseName := remoteChartName
options := &Options{
SetValues: map[string]string{
"image.repository": remoteChartName,
"image.registry": "",
"image.tag": remoteChartVersion,
},
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
Logger: logger.Discard,
SnapshotPath: "__chart_manifests_snapshot__",
}

// Run RenderTemplate to render the template and capture the output. Note that we use the version without `E`, since
// we want to assert that the template renders without any errors.
output := RenderRemoteTemplate(t, options, remoteChartSource, releaseName, []string{})

// Now we use kubernetes/client-go library to render the template output into the Deployment struct. This will
// ensure the Deployment resource is rendered correctly.
var deployment appsv1.Deployment
UnmarshalK8SYaml(t, output, &deployment)

// run the diff and assert there is only one difference: the image name
require.Equal(t, 1, DiffAgainstSnapshot(t, options, output, releaseName))
return output
}
13 changes: 12 additions & 1 deletion modules/packer/packer.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,10 +186,11 @@ func hasPackerInit(t testing.TestingT, options *Options) (bool, error) {
Env: options.Env,
WorkingDir: options.WorkingDir,
}
localVersion, err := shell.RunCommandAndGetOutputE(t, cmd)
versionCmdOutput, err := shell.RunCommandAndGetOutputE(t, cmd)
if err != nil {
return false, err
}
localVersion := trimPackerVersion(versionCmdOutput)
thisVersion, err := version.NewVersion(localVersion)
if err != nil {
return false, err
Expand Down Expand Up @@ -262,3 +263,13 @@ func formatPackerArgs(options *Options) []string {

return append(args, options.Template)
}

// From packer 1.10 the -version command output is prefixed with Packer v
func trimPackerVersion(versionCmdOutput string) string {
re := regexp.MustCompile(`(?:Packer v?|)(\d+\.\d+\.\d+)`)
matches := re.FindStringSubmatch(versionCmdOutput)
if len(matches) > 1 {
return matches[1]
}
return ""
}
32 changes: 32 additions & 0 deletions modules/packer/packer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,3 +174,35 @@ func TestFormatPackerArgs(t *testing.T) {
assert.Equal(t, strings.Join(args, " "), test.expected)
}
}

func TestTrimPackerVersion(t *testing.T) {
t.Parallel()

tests := []struct {
versionOutput string
expected string
}{
{
// Pre 1.10 output
versionOutput: "1.7.0",
expected: "1.7.0",
},
{
// From 1.10 matches the output of packer version
versionOutput: "Packer v1.10.0",
expected: "1.10.0",
},
{
// From 1.10 matches the output of packer version
versionOutput: "Packer v1.10.0\n\nYour version of Packer is out of date! The latest version\nis 1.10.3. You can update by downloading from www.packer.io/downloads\n",
expected: "1.10.0",
},
}

for _, test := range tests {
t.Run(test.versionOutput, func(t *testing.T) {
out := trimPackerVersion(test.versionOutput)
assert.Equal(t, test.expected, out)
})
}
}
2 changes: 1 addition & 1 deletion test/terraform_aws_lambda_example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func TestTerraformAwsLambdaExample(t *testing.T) {
assert.Contains(t, string(functionError.Payload), "Failed to handle")
}

// Annother example of how to test the Terraform module in
// Another example of how to test the Terraform module in
// examples/terraform-aws-lambda-example using Terratest, this time with
// the aws.InvokeFunctionWithParams.
func TestTerraformAwsLambdaWithParamsExample(t *testing.T) {
Expand Down