ããã¯ããªã«ãããããŠæžãããã®ïŒ
Terraformã«å¯Ÿãããã¹ãã³ãŒããæžãã®ã«ãTerratestãšãããã®ã䜿ãããšãããããªã®ã§ã
ãã¡ããè©ŠããŠã¿ããããªããšã
Terratest
Terratestãšã¯ãã€ã³ãã©ã¹ãã©ã¯ãã£ãŒããã¹ãããããã®ãã¿ãŒã³ããã«ããŒé¢æ°ãæäŸããGoã®ã©ã€ãã©ãªã§ãã
Terratest | Automated tests for your infrastructure code.
GitHub - gruntwork-io/terratest: Terratest is a Go library that makes it easier to write automated tests for your infrastructure code.
ããã¥ã¡ã³ããšGoDdocã¯ããã¡ãã
Documentation
terratest · pkg.go.dev
ã¡ãããšèŠããŸã§ããã£ãšTerraformåãã®ãã¹ãã©ã€ãã©ãªã ãšæã£ãŠããã®ã§ããããããªæãã§ãã£ããããããª
ãã¹ããã§ããããã§ãã
â»ããã¥ã¡ã³ãçã«èšèŒãããŠããé çªãããå°ãå
¥ãæ¿ããŠããŸã
Introduction
- Testing Terraform code
- Testing Packer templates
- Testing Docker images
- Testing Helm Charts
- Working with AWS APIs
- Working with Azure APIs
- Working with GCP APIs
- Working with Kubernetes APIs
- Executing commands on servers over SSH
- Making HTTP requests
- Running shell commands
- And much more
Package by package overview
https://github.com/gruntwork-io/terratest/tree/v0.35.1/modules
åºæ¬çãªäœ¿ãæ¹ã¯ããã¡ãã«èŒã£ãŠããŸãã
Quick start / Setting up your project
Quick start / Terratest intro
ãã¹ãã³ãŒãã¯éåžžã®Goã®ãã¹ãã³ãŒããšããŠæžããgo test
ã³ãã³ãã§å®è¡ããããšã«ãªããŸãã
ãã¹ãã³ãŒãã®å®è¡æã«ã
- Terratestã䜿çšããŠIaCããŒã«ïŒTerraformãPackerãDockerãªã©ïŒãå®è¡ããŠãå®éã®ç°å¢ãæ§ç¯
- TerratestãæäŸããã©ã€ãã©ãªã䜿çšããŠãHTTPãªã¯ãšã¹ãã®å®è¡ãAPIåŒã³åºããªã©ãè¡ã£ãŠç¢ºèª
ãšããã¹ããããèžã¿ãæåŸã«ãã¹ãäžã«æ§ç¯ããç°å¢ïŒãªãœãŒã¹ïŒãç Žæ£ããŸãã
åãã¹ãã®ãµã³ãã«ã¯ãQuick startãExamplesã«ããã®ã§ãã
Quick start
Examples
GitHubãªããžããªã«ã¯ãããã«å€æ°ã®ãµã³ãã«ããããŸãã
https://github.com/gruntwork-io/terratest/tree/v0.35.1/examples
ã€ã³ãã©ãã³ãŒãã§ãã¹ãããéã®èãæ¹ã¯ããã¡ããèŠããšããããã§ãã
How to test infrastructure code: automated testing for Terraform, Kub…
ä»åã¯ãTerraformã䜿ã£ããã¹ãã³ãŒããæžããŠã¿ãããšæããŸãã
ç°å¢
ä»åã®ç°å¢ã¯ããã¡ãã
$ go version
go version go1.16.4 linux/amd64
$ terraform version
Terraform v0.15.5
on linux_amd64
TerratestïŒ0.35.1æç¹ïŒã§ã¯ãTerratestãèŠæ±ããŠããã®ã¯Go 1.13以äžãã®ã¿ã§ãã
Quick start / Requirements
ã§ãããTerratestã§Terraformã®ãã¹ããæžãããšãããšãå
éšçã«terraform
ã³ãã³ããå®è¡ãããããçµå±Terraformã
å¿
èŠã«ãªããŸãã
ãŸããTerraformã§ã¯MySQL Providerã䜿ãããšã«ããŸãã
Provider: MySQL - Terraform by HashiCorp
ããã§äœ¿çšããMySQLã¯8.0.25ã§ã172.17.0.2ã§ã¢ã¯ã»ã¹ã§ãããã®ãšããŸãã
ãé¡
ä»åã¯ãTerraformã§MySQLã«é¢ãããªãœãŒã¹ãæ§ç¯ããããã«å¯Ÿãããã¹ããæžããŸãã
ãã¹ãã¯ãQuick startã«ç¿ã£ãŠåçŽã«Terraformã®outputã確èªãããã®ã®ãšãæ§ç¯ããããªãœãŒã¹ã®ç¢ºèªãå«ããŠ
è¡ããã®ã®2ã€ãè¡ããŸãããã
æºå
ãŸãã¯ããã£ã¬ã¯ããªãäœæããŸãã
Quick startãèŠãŠãããšãTerratestã䜿ã£ããã¹ãã³ãŒãã¯test
ãã£ã¬ã¯ããªã«çœ®ãããŸãGoã¢ãžã¥ãŒã«ã®ã«ãŒããã£ã¬ã¯ããªãš
ããæ¹ãè¯ãããã§ããã
Quick start / Setting up your project
terraform
ãtest
ãã£ã¬ã¯ããªãããããäœæããããšã«ããŸããã
$ mkdir terraform test
TerrateståŽã®ãã¹ãã³ãŒããããã®ããã«ãªã£ãŠããŸãïŒGoã¢ãžã¥ãŒã«ã®ã«ãŒããã£ã¬ã¯ããªã§ã¯ãªãã§ããïŒã
https://github.com/gruntwork-io/terratest/tree/v0.35.1/test
ä»åäœæãããã£ã¬ã¯ããªããã¡ã€ã«ã¯ãæçµçã«ãããªæãã«ãªããŸããã
.
âââ terraform
â  âââ complex
â  â  âââ main.tf
â  âââ simple
â  âââ main.tf
âââ test
âââ go.mod
âââ go.sum
âââ mysql_test.go
ã§ã¯ãGoã¢ãžã¥ãŒã«åŽã®ã»ããã¢ãããããŸããããtest
ãã£ã¬ã¯ããªãžç§»åãã
$ cd test
Goã¢ãžã¥ãŒã«ã®åæåã
$ go mod init getting-started
go: creating new go.mod: module getting-started
Terratestãgo get
ããŸãã
$ go get github.com/gruntwork-io/terratest/modules/terraform@v0.35.1
go get github.com/gruntwork-io/terratest@v0.35.1
ã ãšãã©ã€ãã©ãªã足ããªãç¶æ
ã«ãªããŸããâŠã
ããšã¯ããã¹ãã©ã€ãã©ãªãšããŠtestifyããMySQLãžã¢ã¯ã»ã¹ããããã«MySQLã®ãã©ã€ããŒãã€ã³ã¹ããŒã«ããŸãã
$ go get github.com/stretchr/testify@v1.7.0
$ go get github.com/go-sql-driver/mysql@v1.6.0
go.mod
ã¯ããããªããŸããã
go.mod
module getting-started
go 1.16
require (
github.com/go-sql-driver/mysql v1.6.0
github.com/gruntwork-io/terratest v0.35.1
github.com/stretchr/testify v1.7.0
)
ãã¹ãã³ãŒãã®é圢
æåã«ããã¹ãã³ãŒãã®é圢ãæžããŠãããŸãããã
mysql_test.go
package test
import (
"database/sql"
"fmt"
"testing"
_ "github.com/go-sql-driver/mysql"
"github.com/gruntwork-io/terratest/modules/terraform"
"github.com/stretchr/testify/assert"
)
Terratestã䜿ã£ãŠãTerraformãå®è¡ãã
æåã«ãTerraformã®æ§æãã¡ã€ã«ãæžããŸããããå
ã»ã©äœæããterraform
ãã£ã¬ã¯ããªå
ã«ããã£ã¬ã¯ããªãè¿œå ããŸãã
$ mkdir terraform/simple
$ cd terraform/simple
ãããªæãã«ãããŒã¿ããŒã¹ãäœæããã ãã®main.tf
ãã¡ã€ã«ãäœæã
main.tf
terraform {
required_version = "0.15.5"
required_providers {
mysql = {
source = "terraform-providers/mysql"
version = "1.9.0"
}
}
}
provider "mysql" {
endpoint = "172.17.0.2:3306"
username = "root"
password = "password"
}
resource "mysql_database" "app" {
name = "my_database"
}
output "database_name" {
value = mysql_database.app.name
}
output
ã¯ãããŒã¿ããŒã¹åã®ã¿ã§ãã
äžå¿ãåäœã§ã確èªããŠãããŸãããã
$ terraform init
$ terraform fmt -diff -recursive
$ terraform apply
$ terraform destroy
次ã«ããã¹ãã³ãŒãã«ãã¹ããè¿œå ããŸãã
ãã¡ããåèã«ã
Quick start / Example #1: Terraform âHello, Worldâ
func TestTerraformMySqlHelloWorld(t *testing.T) {
terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
TerraformDir: "../terraform/simple",
})
defer terraform.Destroy(t, terraformOptions)
terraform.InitAndApply(t, terraformOptions)
databaseName := terraform.Output(t, terraformOptions, "database_name")
assert.Equal(t, "my_database", databaseName)
}
ãã¡ãã§ãå®è¡ããTerraformã®æ§æãã¡ã€ã«ãé
眮ãããŠãããã£ã¬ã¯ããªãæå®ã
terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
TerraformDir: "../terraform/simple",
})
WithDefaultRetryableErrors
ãšããé¢æ°ã¯ãOptions
ããã«ãªãã©ã€èšå®ãè¿œå ãããã®ã«ãªããŸãã
type Options
func WithDefaultRetryableErrors
æ»ãå€ã¯ãOptions
ã®ãŸãŸã§ãã
ãã¹ãã®æåïŒå€±æã«é¢ããããæåŸã«terraform destroy
ããããã«ããŠããŸãã
func Destroy
defer terraform.Destroy(t, terraformOptions)
ããšã¯terraform init
ãšterraform apply
ãè¡ã
func InitAndApply
terraform.InitAndApply(t, terraformOptions)
output
ãååŸããŠã¢ãµãŒã·ã§ã³ããŠå®äºã§ãã
func Output
databaseName := terraform.Output(t, terraformOptions, "database_name")
assert.Equal(t, "my_database", databaseName)
output
ãæ±ãé¢æ°ã¯ä»ã«ããããå
šéšã®output
ãååŸããããã§ãããã§ãããåã¢ãµãŒã·ã§ã³ãå¿
èŠãããªã®ã§ã
ãããªãã«åãåããããã®ã䜿ãã®ãè¯ãããã§ãã
ã§ã¯ãå®è¡ããŠã¿ãŸãããã
$ go test -v
å®è¡ãã°ã¯ããããªæãã«ãªããŸããã
$ go test -v
=== RUN TestTerraformMySqlHelloWorld
TestTerraformMySqlHelloWorld 2021-06-05T22:02:09+09:00 retry.go:91: terraform [init -upgrade=false]
TestTerraformMySqlHelloWorld 2021-06-05T22:02:09+09:00 logger.go:66: Running command terraform with args [init -upgrade=false]
TestTerraformMySqlHelloWorld 2021-06-05T22:02:09+09:00 logger.go:66:
TestTerraformMySqlHelloWorld 2021-06-05T22:02:09+09:00 logger.go:66: Initializing the backend...
TestTerraformMySqlHelloWorld 2021-06-05T22:02:09+09:00 logger.go:66:
TestTerraformMySqlHelloWorld 2021-06-05T22:02:09+09:00 logger.go:66: Initializing provider plugins...
TestTerraformMySqlHelloWorld 2021-06-05T22:02:09+09:00 logger.go:66: - Reusing previous version of terraform-providers/mysql from the dependency lock file
TestTerraformMySqlHelloWorld 2021-06-05T22:02:09+09:00 logger.go:66: - Using previously-installed terraform-providers/mysql v1.9.0
TestTerraformMySqlHelloWorld 2021-06-05T22:02:09+09:00 logger.go:66:
TestTerraformMySqlHelloWorld 2021-06-05T22:02:09+09:00 logger.go:66: Terraform has been successfully initialized!
TestTerraformMySqlHelloWorld 2021-06-05T22:02:09+09:00 logger.go:66:
TestTerraformMySqlHelloWorld 2021-06-05T22:02:09+09:00 logger.go:66: You may now begin working with Terraform. Try running "terraform plan" to see
TestTerraformMySqlHelloWorld 2021-06-05T22:02:09+09:00 logger.go:66: any changes that are required for your infrastructure. All Terraform commands
TestTerraformMySqlHelloWorld 2021-06-05T22:02:09+09:00 logger.go:66: should now work.
TestTerraformMySqlHelloWorld 2021-06-05T22:02:09+09:00 logger.go:66:
TestTerraformMySqlHelloWorld 2021-06-05T22:02:09+09:00 logger.go:66: If you ever set or change modules or backend configuration for Terraform,
TestTerraformMySqlHelloWorld 2021-06-05T22:02:09+09:00 logger.go:66: rerun this command to reinitialize your working directory. If you forget, other
TestTerraformMySqlHelloWorld 2021-06-05T22:02:09+09:00 logger.go:66: commands will detect it and remind you to do so if necessary.
TestTerraformMySqlHelloWorld 2021-06-05T22:02:09+09:00 retry.go:91: terraform [apply -input=false -auto-approve -lock=false]
TestTerraformMySqlHelloWorld 2021-06-05T22:02:09+09:00 logger.go:66: Running command terraform with args [apply -input=false -auto-approve -lock=false]
TestTerraformMySqlHelloWorld 2021-06-05T22:02:10+09:00 logger.go:66:
TestTerraformMySqlHelloWorld 2021-06-05T22:02:10+09:00 logger.go:66: Terraform used the selected providers to generate the following execution
TestTerraformMySqlHelloWorld 2021-06-05T22:02:10+09:00 logger.go:66: plan. Resource actions are indicated with the following symbols:
TestTerraformMySqlHelloWorld 2021-06-05T22:02:10+09:00 logger.go:66: + create
TestTerraformMySqlHelloWorld 2021-06-05T22:02:10+09:00 logger.go:66:
TestTerraformMySqlHelloWorld 2021-06-05T22:02:10+09:00 logger.go:66: Terraform will perform the following actions:
TestTerraformMySqlHelloWorld 2021-06-05T22:02:10+09:00 logger.go:66:
TestTerraformMySqlHelloWorld 2021-06-05T22:02:10+09:00 logger.go:66: # mysql_database.app will be created
TestTerraformMySqlHelloWorld 2021-06-05T22:02:10+09:00 logger.go:66: + resource "mysql_database" "app" {
TestTerraformMySqlHelloWorld 2021-06-05T22:02:10+09:00 logger.go:66: + default_character_set = "utf8"
TestTerraformMySqlHelloWorld 2021-06-05T22:02:10+09:00 logger.go:66: + default_collation = "utf8_general_ci"
TestTerraformMySqlHelloWorld 2021-06-05T22:02:10+09:00 logger.go:66: + id = (known after apply)
TestTerraformMySqlHelloWorld 2021-06-05T22:02:10+09:00 logger.go:66: + name = "my_database"
TestTerraformMySqlHelloWorld 2021-06-05T22:02:10+09:00 logger.go:66: }
TestTerraformMySqlHelloWorld 2021-06-05T22:02:10+09:00 logger.go:66:
TestTerraformMySqlHelloWorld 2021-06-05T22:02:10+09:00 logger.go:66: Plan: 1 to add, 0 to change, 0 to destroy.
TestTerraformMySqlHelloWorld 2021-06-05T22:02:10+09:00 logger.go:66:
TestTerraformMySqlHelloWorld 2021-06-05T22:02:10+09:00 logger.go:66: Changes to Outputs:
TestTerraformMySqlHelloWorld 2021-06-05T22:02:10+09:00 logger.go:66: + database_name = "my_database"
TestTerraformMySqlHelloWorld 2021-06-05T22:02:10+09:00 logger.go:66: mysql_database.app: Creating...
TestTerraformMySqlHelloWorld 2021-06-05T22:02:10+09:00 logger.go:66: mysql_database.app: Creation complete after 0s [id=my_database]
TestTerraformMySqlHelloWorld 2021-06-05T22:02:10+09:00 logger.go:66:
TestTerraformMySqlHelloWorld 2021-06-05T22:02:10+09:00 logger.go:66: Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
TestTerraformMySqlHelloWorld 2021-06-05T22:02:10+09:00 logger.go:66:
TestTerraformMySqlHelloWorld 2021-06-05T22:02:10+09:00 logger.go:66: Outputs:
TestTerraformMySqlHelloWorld 2021-06-05T22:02:10+09:00 logger.go:66:
TestTerraformMySqlHelloWorld 2021-06-05T22:02:10+09:00 logger.go:66: database_name = "my_database"
TestTerraformMySqlHelloWorld 2021-06-05T22:02:10+09:00 retry.go:91: terraform [output -no-color -json database_name]
TestTerraformMySqlHelloWorld 2021-06-05T22:02:10+09:00 logger.go:66: Running command terraform with args [output -no-color -json database_name]
TestTerraformMySqlHelloWorld 2021-06-05T22:02:10+09:00 logger.go:66: "my_database"
TestTerraformMySqlHelloWorld 2021-06-05T22:02:10+09:00 retry.go:91: terraform [destroy -auto-approve -input=false -lock=false]
TestTerraformMySqlHelloWorld 2021-06-05T22:02:10+09:00 logger.go:66: Running command terraform with args [destroy -auto-approve -input=false -lock=false]
TestTerraformMySqlHelloWorld 2021-06-05T22:02:11+09:00 logger.go:66: mysql_database.app: Refreshing state... [id=my_database]
TestTerraformMySqlHelloWorld 2021-06-05T22:02:11+09:00 logger.go:66:
TestTerraformMySqlHelloWorld 2021-06-05T22:02:11+09:00 logger.go:66: Terraform used the selected providers to generate the following execution
TestTerraformMySqlHelloWorld 2021-06-05T22:02:11+09:00 logger.go:66: plan. Resource actions are indicated with the following symbols:
TestTerraformMySqlHelloWorld 2021-06-05T22:02:11+09:00 logger.go:66: - destroy
TestTerraformMySqlHelloWorld 2021-06-05T22:02:11+09:00 logger.go:66:
TestTerraformMySqlHelloWorld 2021-06-05T22:02:11+09:00 logger.go:66: Terraform will perform the following actions:
TestTerraformMySqlHelloWorld 2021-06-05T22:02:11+09:00 logger.go:66:
TestTerraformMySqlHelloWorld 2021-06-05T22:02:11+09:00 logger.go:66: # mysql_database.app will be destroyed
TestTerraformMySqlHelloWorld 2021-06-05T22:02:11+09:00 logger.go:66: - resource "mysql_database" "app" {
TestTerraformMySqlHelloWorld 2021-06-05T22:02:11+09:00 logger.go:66: - default_character_set = "utf8" -> null
TestTerraformMySqlHelloWorld 2021-06-05T22:02:11+09:00 logger.go:66: - default_collation = "utf8_general_ci" -> null
TestTerraformMySqlHelloWorld 2021-06-05T22:02:11+09:00 logger.go:66: - id = "my_database" -> null
TestTerraformMySqlHelloWorld 2021-06-05T22:02:11+09:00 logger.go:66: - name = "my_database" -> null
TestTerraformMySqlHelloWorld 2021-06-05T22:02:11+09:00 logger.go:66: }
TestTerraformMySqlHelloWorld 2021-06-05T22:02:11+09:00 logger.go:66:
TestTerraformMySqlHelloWorld 2021-06-05T22:02:11+09:00 logger.go:66: Plan: 0 to add, 0 to change, 1 to destroy.
TestTerraformMySqlHelloWorld 2021-06-05T22:02:11+09:00 logger.go:66:
TestTerraformMySqlHelloWorld 2021-06-05T22:02:11+09:00 logger.go:66: Changes to Outputs:
TestTerraformMySqlHelloWorld 2021-06-05T22:02:11+09:00 logger.go:66: - database_name = "my_database" -> null
TestTerraformMySqlHelloWorld 2021-06-05T22:02:11+09:00 logger.go:66: mysql_database.app: Destroying... [id=my_database]
TestTerraformMySqlHelloWorld 2021-06-05T22:02:11+09:00 logger.go:66: mysql_database.app: Destruction complete after 1s
TestTerraformMySqlHelloWorld 2021-06-05T22:02:11+09:00 logger.go:66:
TestTerraformMySqlHelloWorld 2021-06-05T22:02:11+09:00 logger.go:66: Destroy complete! Resources: 1 destroyed.
TestTerraformMySqlHelloWorld 2021-06-05T22:02:11+09:00 logger.go:66:
--- PASS: TestTerraformMySqlHelloWorld (2.46s)
PASS
ok getting-started 2.462s
ããããèŠããšãterraform
ã³ãã³ãã®å®è¡å
容ããã°ã«å«ãŸããŠããŸãã
terraform [init -upgrade=false]
terraform [apply -input=false -auto-approve -lock=false]
terraform [output -no-color -json database_name]
terraform [destroy -auto-approve -input=false -lock=false]
ãªã®ã§ãterraform
ã³ãã³ããã€ã³ã¹ããŒã«ãããŠããªãå Žåã¯ããã®ãã¹ãã¯å®è¡ã«å€±æããŸãã
TestTerraformMySqlHelloWorld 2021-06-05T22:05:01+09:00 retry.go:99: Returning due to fatal error: FatalError{Underlying: error while running command: exec: "terraform": executable file not found in $PATH; }
apply.go:15:
Error Trace: apply.go:15
mysql_test.go:20
Error: Received unexpected error:
FatalError{Underlying: error while running command: exec: "terraform": executable file not found in $PATH; }
Test: TestTerraformMySqlHelloWorld
ãªããšãªããåºæ¬çãªäœ¿ãæ¹ã¯ããã£ãæ°ãããŸãã
ããšã¯ããã®ä»ã®TerratestãæäŸããIaCããŒã«ãµããŒããã©ã€ãã©ãªã®äœ¿ãæ¹ãèŠãããã
ããã¥ã¡ã³ãã«ããã¹ãã®ãã¹ããã©ã¯ãã£ã¹ããèŒã£ãŠããã®ã§ããã¡ããèŠããããŠæ
£ããŠããã®ããªããš
æããŸãã
Testing best practices
ããå°ãè€éãªäŸã
ç¶ããŠãå
ã»ã©ã®ã·ã³ãã«ãªäŸã«ããå°ãèŠçŽ ãå ãããã®ããã£ãŠã¿ãŸãããã
ãã£ã¬ã¯ããªãè¿œå ã
$ mkdir terraform/complex
$ cd terraform/complex
Terraformã®æ§æãã¡ã€ã«ã¯ããã¡ãã
main.tf
terraform {
required_version = "0.15.5"
required_providers {
mysql = {
source = "terraform-providers/mysql"
version = "1.9.0"
}
}
}
variable "database_name" {
type = string
}
variable "app_user_name" {
type = string
default = "app_user"
}
variable "app_user_password" {
type = string
}
provider "mysql" {
endpoint = "172.17.0.2:3306"
username = "root"
password = "password"
}
resource "mysql_database" "app" {
name = var.database_name
}
resource "mysql_user" "app_user" {
user = var.app_user_name
plaintext_password = var.app_user_password
host = "%"
}
resource "mysql_grant" "user_grant" {
user = mysql_user.app_user.user
host = mysql_user.app_user.host
database = mysql_database.app.name
privileges = ["ALL"]
}
output "database_name" {
value = mysql_database.app.name
}
output "app_user_name" {
value = mysql_user.app_user.user
}
ä»åã¯ãvariable
ãåãããã«ããŸããã
variable "database_name" {
type = string
}
variable "app_user_name" {
type = string
default = "app_user"
}
variable "app_user_password" {
type = string
}
ãŠãŒã¶ãŒãäœæããããã«ããŠããŸãã
resource "mysql_user" "app_user" {
user = var.app_user_name
plaintext_password = var.app_user_password
host = "%"
}
resource "mysql_grant" "user_grant" {
user = mysql_user.app_user.user
host = mysql_user.app_user.host
database = mysql_database.app.name
privileges = ["ALL"]
}
ãã¹ãã³ãŒãã¯ããã¡ãã
func TestTerraformMySqlWithValidation(t *testing.T) {
appUserPassword := "app_password"
terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
TerraformDir: "../terraform/complex",
Vars: map[string]interface{}{
"database_name": "practice",
"app_user_password": appUserPassword,
},
})
defer terraform.Destroy(t, terraformOptions)
terraform.InitAndApply(t, terraformOptions)
databaseName := terraform.Output(t, terraformOptions, "database_name")
appUserName := terraform.Output(t, terraformOptions, "app_user_name")
assert.Equal(t, "practice", databaseName)
assert.Equal(t, "app_user", appUserName)
db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@(%s:%d)/%s", appUserName, appUserPassword, "172.17.0.2", 3306, databaseName))
assert.Nil(t, err)
assert.NotNil(t, db)
defer db.Close()
err = db.Ping()
assert.Nil(t, err)
}
Options
ã«ãä»åã¯Var
ã®æå®ãè¿œå ããŸããã-var
ãšåãã§ããã
terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
TerraformDir: "../terraform/complex",
Vars: map[string]interface{}{
"database_name": "practice",
"app_user_password": appUserPassword,
},
})
terraform destroy
ã®ä»èŸŒã¿ããterraform init
ãterraform apply
ã®å®è¡ãterraform output
ããã®ã¢ãµãŒã·ã§ã³ãè¡ãã€ã€
defer terraform.Destroy(t, terraformOptions)
terraform.InitAndApply(t, terraformOptions)
databaseName := terraform.Output(t, terraformOptions, "database_name")
appUserName := terraform.Output(t, terraformOptions, "app_user_name")
assert.Equal(t, "practice", databaseName)
assert.Equal(t, "app_user", appUserName)
æåŸã«ãäœæãããŠãŒã¶ãŒã§ãMySQLã«æ¥ç¶ã§ããããšã確èªããŸãã
db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@(%s:%d)/%s", appUserName, appUserPassword, "172.17.0.2", 3306, databaseName))
assert.Nil(t, err)
assert.NotNil(t, db)
defer db.Close()
err = db.Ping()
assert.Nil(t, err)
ãã®ããã«ãæ§ç¯ããããªãœãŒã¹ã«å¯ŸããŠåäœç¢ºèªïŒHTTPãªã¯ãšã¹ããå®è¡ãããAPIåŒã³åºããè¡ããSSHã§ã³ãã³ãã
å®è¡ããããªã©ïŒããããšããããªããŒã·ã§ã³ãšåŒãã§ããã¿ããã§ãã
https://www.slideshare.net/brikis98/how-to-test-infrastructure-code-automated-testing-for-terraform-kubernetes-docker-packer-and-more/53
https://www.slideshare.net/brikis98/how-to-test-infrastructure-code-automated-testing-for-terraform-kubernetes-docker-packer-and-more/67
https://www.slideshare.net/brikis98/how-to-test-infrastructure-code-automated-testing-for-terraform-kubernetes-docker-packer-and-more/69
ãã¹ãã§ç¢ºèªã
$ go test -v
å®è¡ãã°ã
$ go test -v
=== RUN TestTerraformMySqlWithValidation
TestTerraformMySqlWithValidation 2021-06-05T22:37:52+09:00 retry.go:91: terraform [init -upgrade=false]
TestTerraformMySqlWithValidation 2021-06-05T22:37:52+09:00 logger.go:66: Running command terraform with args [init -upgrade=false]
TestTerraformMySqlWithValidation 2021-06-05T22:37:52+09:00 logger.go:66:
TestTerraformMySqlWithValidation 2021-06-05T22:37:52+09:00 logger.go:66: Initializing the backend...
TestTerraformMySqlWithValidation 2021-06-05T22:37:52+09:00 logger.go:66:
TestTerraformMySqlWithValidation 2021-06-05T22:37:52+09:00 logger.go:66: Initializing provider plugins...
TestTerraformMySqlWithValidation 2021-06-05T22:37:52+09:00 logger.go:66: - Reusing previous version of terraform-providers/mysql from the dependency lock file
TestTerraformMySqlWithValidation 2021-06-05T22:37:52+09:00 logger.go:66: - Using previously-installed terraform-providers/mysql v1.9.0
TestTerraformMySqlWithValidation 2021-06-05T22:37:52+09:00 logger.go:66:
TestTerraformMySqlWithValidation 2021-06-05T22:37:52+09:00 logger.go:66: Terraform has been successfully initialized!
TestTerraformMySqlWithValidation 2021-06-05T22:37:52+09:00 logger.go:66:
TestTerraformMySqlWithValidation 2021-06-05T22:37:52+09:00 logger.go:66: You may now begin working with Terraform. Try running "terraform plan" to see
TestTerraformMySqlWithValidation 2021-06-05T22:37:52+09:00 logger.go:66: any changes that are required for your infrastructure. All Terraform commands
TestTerraformMySqlWithValidation 2021-06-05T22:37:52+09:00 logger.go:66: should now work.
TestTerraformMySqlWithValidation 2021-06-05T22:37:52+09:00 logger.go:66:
TestTerraformMySqlWithValidation 2021-06-05T22:37:52+09:00 logger.go:66: If you ever set or change modules or backend configuration for Terraform,
TestTerraformMySqlWithValidation 2021-06-05T22:37:52+09:00 logger.go:66: rerun this command to reinitialize your working directory. If you forget, other
TestTerraformMySqlWithValidation 2021-06-05T22:37:52+09:00 logger.go:66: commands will detect it and remind you to do so if necessary.
TestTerraformMySqlWithValidation 2021-06-05T22:37:52+09:00 retry.go:91: terraform [apply -input=false -auto-approve -var database_name=practice -var app_user_password=app_password -lock=false]
TestTerraformMySqlWithValidation 2021-06-05T22:37:52+09:00 logger.go:66: Running command terraform with args [apply -input=false -auto-approve -var database_name=practice -var app_user_password=app_password -lock=false]
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66:
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: Terraform used the selected providers to generate the following execution
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: plan. Resource actions are indicated with the following symbols:
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: + create
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66:
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: Terraform will perform the following actions:
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66:
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: # mysql_database.app will be created
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: + resource "mysql_database" "app" {
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: + default_character_set = "utf8"
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: + default_collation = "utf8_general_ci"
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: + id = (known after apply)
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: + name = "practice"
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: }
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66:
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: # mysql_grant.user_grant will be created
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: + resource "mysql_grant" "user_grant" {
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: + database = "practice"
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: + grant = false
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: + host = "%!"(MISSING)
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: + id = (known after apply)
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: + privileges = [
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: + "ALL",
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: ]
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: + table = "*"
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: + tls_option = "NONE"
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: + user = "app_user"
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: }
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66:
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: # mysql_user.app_user will be created
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: + resource "mysql_user" "app_user" {
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: + host = "%!"(MISSING)
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: + id = (known after apply)
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: + plaintext_password = (sensitive value)
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: + tls_option = "NONE"
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: + user = "app_user"
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: }
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66:
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: Plan: 3 to add, 0 to change, 0 to destroy.
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66:
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: Changes to Outputs:
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: + app_user_name = "app_user"
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: + database_name = "practice"
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: mysql_database.app: Creating...
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: mysql_user.app_user: Creating...
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: mysql_user.app_user: Creation complete after 1s [id=app_user@%!](MISSING)
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: mysql_database.app: Creation complete after 1s [id=practice]
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: mysql_grant.user_grant: Creating...
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: mysql_grant.user_grant: Creation complete after 0s [id=app_user@%!:(MISSING)`practice`]
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66:
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66:
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: Outputs:
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66:
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: app_user_name = "app_user"
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: database_name = "practice"
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 retry.go:91: terraform [output -no-color -json database_name]
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: Running command terraform with args [output -no-color -json database_name]
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: "practice"
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 retry.go:91: terraform [output -no-color -json app_user_name]
TestTerraformMySqlWithValidation 2021-06-05T22:37:53+09:00 logger.go:66: Running command terraform with args [output -no-color -json app_user_name]
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: "app_user"
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 retry.go:91: terraform [destroy -auto-approve -input=false -var app_user_password=app_password -var database_name=practice -lock=false]
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: Running command terraform with args [destroy -auto-approve -input=false -var app_user_password=app_password -var database_name=practice -lock=false]
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: mysql_database.app: Refreshing state... [id=practice]
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: mysql_user.app_user: Refreshing state... [id=app_user@%!](MISSING)
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: mysql_grant.user_grant: Refreshing state... [id=app_user@%!:(MISSING)`practice`]
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66:
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: Terraform used the selected providers to generate the following execution
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: plan. Resource actions are indicated with the following symbols:
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: - destroy
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66:
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: Terraform will perform the following actions:
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66:
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: # mysql_database.app will be destroyed
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: - resource "mysql_database" "app" {
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: - default_character_set = "utf8" -> null
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: - default_collation = "utf8_general_ci" -> null
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: - id = "practice" -> null
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: - name = "practice" -> null
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: }
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66:
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: # mysql_grant.user_grant will be destroyed
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: - resource "mysql_grant" "user_grant" {
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: - database = "practice" -> null
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: - grant = false -> null
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: - host = "%!"(MISSING) -> null
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: - id = "app_user@%!:(MISSING)`practice`" -> null
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: - privileges = [
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: - "ALL",
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: ] -> null
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: - table = "*" -> null
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: - tls_option = "NONE" -> null
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: - user = "app_user" -> null
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: }
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66:
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: # mysql_user.app_user will be destroyed
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: - resource "mysql_user" "app_user" {
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: - host = "%!"(MISSING) -> null
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: - id = "app_user@%!"(MISSING) -> null
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: - plaintext_password = (sensitive value)
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: - tls_option = "NONE" -> null
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: - user = "app_user" -> null
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: }
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66:
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: Plan: 0 to add, 0 to change, 3 to destroy.
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66:
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: Changes to Outputs:
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: - app_user_name = "app_user" -> null
TestTerraformMySqlWithValidation 2021-06-05T22:37:54+09:00 logger.go:66: - database_name = "practice" -> null
TestTerraformMySqlWithValidation 2021-06-05T22:37:55+09:00 logger.go:66: mysql_grant.user_grant: Destroying... [id=app_user@%!:(MISSING)`practice`]
TestTerraformMySqlWithValidation 2021-06-05T22:37:55+09:00 logger.go:66: mysql_grant.user_grant: Destruction complete after 0s
TestTerraformMySqlWithValidation 2021-06-05T22:37:55+09:00 logger.go:66: mysql_database.app: Destroying... [id=practice]
TestTerraformMySqlWithValidation 2021-06-05T22:37:55+09:00 logger.go:66: mysql_user.app_user: Destroying... [id=app_user@%!](MISSING)
TestTerraformMySqlWithValidation 2021-06-05T22:37:55+09:00 logger.go:66: mysql_user.app_user: Destruction complete after 0s
TestTerraformMySqlWithValidation 2021-06-05T22:37:55+09:00 logger.go:66: mysql_database.app: Destruction complete after 0s
TestTerraformMySqlWithValidation 2021-06-05T22:37:55+09:00 logger.go:66:
TestTerraformMySqlWithValidation 2021-06-05T22:37:55+09:00 logger.go:66: Destroy complete! Resources: 3 destroyed.
TestTerraformMySqlWithValidation 2021-06-05T22:37:55+09:00 logger.go:66:
--- PASS: TestTerraformMySqlWithValidation (3.12s)
PASS
ok getting-started 3.127s
æåã«äœæãããã¹ããšãterraform
ã³ãã³ãã®å®è¡ããªãšãŒã·ã§ã³ãç°ãªãã®ã¯ã-var
ãè¿œå ãããããšã§ããã
terraform [apply -input=false -auto-approve -var database_name=practice -var app_user_password=app_password -lock=false]
ããã§ãvariable
ãæž¡ããããå®éã«æ§ç¯ãããªãœãŒã¹ã確èªããããããã¹ããã§ããŸããããšã
ãŸãšã
Terratestã䜿ã£ãŠãTerraformã®æ§æãã¡ã€ã«ã«å¯Ÿãããã¹ããè¡ã£ãŠã¿ãŸããã
調ã¹ãŠã¿ããšãTerraform以å€ã®ã€ã³ãã©é¢ä¿ã®ããŒã«ã®ãã¹ããã§ããããªã®ã§ãããã¡ãã£ãšèª¿ã¹ãŠã¿ãŠãããããã§ããã
æåŸã«ããã¹ãã³ãŒãå
šäœãèŒããŠãããŸãã
mysql_test.go
package test
import (
"database/sql"
"fmt"
"testing"
_ "github.com/go-sql-driver/mysql"
"github.com/gruntwork-io/terratest/modules/terraform"
"github.com/stretchr/testify/assert"
)
func TestTerraformMySqlHelloWorld(t *testing.T) {
terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
TerraformDir: "../terraform/simple",
})
defer terraform.Destroy(t, terraformOptions)
terraform.InitAndApply(t, terraformOptions)
databaseName := terraform.Output(t, terraformOptions, "database_name")
assert.Equal(t, "my_database", databaseName)
}
func TestTerraformMySqlWithValidation(t *testing.T) {
appUserPassword := "app_password"
terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
TerraformDir: "../terraform/complex",
Vars: map[string]interface{}{
"database_name": "practice",
"app_user_password": appUserPassword,
},
})
defer terraform.Destroy(t, terraformOptions)
terraform.InitAndApply(t, terraformOptions)
databaseName := terraform.Output(t, terraformOptions, "database_name")
appUserName := terraform.Output(t, terraformOptions, "app_user_name")
assert.Equal(t, "practice", databaseName)
assert.Equal(t, "app_user", appUserName)
db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@(%s:%d)/%s", appUserName, appUserPassword, "172.17.0.2", 3306, databaseName))
assert.Nil(t, err)
assert.NotNil(t, db)
defer db.Close()
err = db.Ping()
assert.Nil(t, err)
}