fix test TF infra, add TF manager for testing
This commit is contained in:
9 files changed
+300
-6
No files matched your search
@@ -0,0 +1,3 @@
|
||||
.terraform*
|
||||
terraform.tfstate*
|
||||
plan.tfplan
|
||||
@@ -6,5 +6,6 @@ require (
|
||||
github.com/aws/aws-sdk-go v1.40.44
|
||||
github.com/hashicorp/boundary/sdk v0.0.11-0.20210917171013-480e801d6447
|
||||
github.com/hashicorp/go-secure-stdlib/awsutil v0.1.3
|
||||
github.com/hashicorp/terraform-json v0.12.0 // indirect
|
||||
google.golang.org/protobuf v1.27.1
|
||||
)
|
||||
@@ -58,6 +58,7 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190620160927-9418d7b0cd0f/go.mod h1:myCDvQSzCW+wB1WAlocEru4wMGJxy+vlxHdhegi1CDQ=
|
||||
github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk=
|
||||
github.com/armon/go-metrics v0.3.0/go.mod h1:zXjbSimjXTd7vOpY8B0/2LpvNvDoXBuplAD+gJD3GYs=
|
||||
github.com/armon/go-metrics v0.3.3/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
@@ -147,6 +148,7 @@ github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb
|
||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
@@ -236,6 +238,8 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hashicorp/terraform-json v0.12.0 h1:8czPgEEWWPROStjkWPUnTQDXmpmZPlkQAwYYLETaTvw=
|
||||
github.com/hashicorp/terraform-json v0.12.0/go.mod h1:pmbq9o4EuL43db5+0ogX10Yofv1nozM+wskr/bGFJpI=
|
||||
github.com/hashicorp/vault/api v1.0.5-0.20200519221902-385fac77e20f/go.mod h1:euTFbi2YJgwcju3imEt919lhJKF68nN1cQPq3aA+kBE=
|
||||
github.com/hashicorp/vault/api v1.1.1/go.mod h1:29UXcn/1cLOPHQNMWA7bCz2By4PSd0VKPAydKXS5yN0=
|
||||
github.com/hashicorp/vault/sdk v0.1.14-0.20200519221530-14615acda45f/go.mod h1:WX57W2PwkrOPQ6rVQk+dy5/htHIaB4aBM70EwKThu10=
|
||||
@@ -272,6 +276,7 @@ github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NB
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
|
||||
@@ -285,6 +290,7 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/cli v1.1.2/go.mod h1:6iaV0fGdElS6dPBx0EApTxHrcWvmJphyh2n8YBLPPZ4=
|
||||
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
|
||||
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
@@ -293,6 +299,7 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh
|
||||
github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
@@ -344,6 +351,7 @@ github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTE
|
||||
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/sebdah/goldie v1.0.0/go.mod h1:jXP4hmWywNEwZzhMuv2ccnqTSFpuq8iyQhtQdkkZBH4=
|
||||
github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
@@ -367,9 +375,12 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/tencentcloud/tencentcloud-sdk-go v1.0.162/go.mod h1:asUz5BPXxgoPGaRgZaVm1iGcUAuHyYUo1nXqKa83cvI=
|
||||
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
|
||||
github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
|
||||
github.com/yandex-cloud/go-genproto v0.0.0-20200722140432-762fe965ce77/go.mod h1:HEUYX/p8966tMUHHT+TsS0hF/Ca/NYwqprC5WXSDMfE=
|
||||
github.com/yandex-cloud/go-sdk v0.0.0-20200722140627-2194e5077f13/go.mod h1:LEdAMqa1v/7KYe4b13ALLkonuDxLph57ibUb50ctvJk=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/zclconf/go-cty v1.2.1 h1:vGMsygfmeCl4Xb6OA5U5XVAaQZ69FvoG7X2jUtQujb8=
|
||||
github.com/zclconf/go-cty v1.2.1/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
@@ -417,6 +428,7 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
||||
@@ -15,8 +15,6 @@ resource "aws_iam_user" "user" {
|
||||
|
||||
resource "aws_iam_access_key" "user_initial_key" {
|
||||
user = aws_iam_user.user.name
|
||||
|
||||
tags = var.project_path_tags
|
||||
}
|
||||
|
||||
resource "aws_iam_policy" "ec2_describeinstances" {
|
||||
@@ -36,11 +34,13 @@ resource "aws_iam_policy" "ec2_describeinstances" {
|
||||
]
|
||||
}
|
||||
EOF
|
||||
|
||||
tags = var.project_path_tags
|
||||
}
|
||||
|
||||
resource "aws_iam_user_policy_attachement" "user_ec2_describeinstances_attachment" {
|
||||
resource "aws_iam_user_policy_attachment" "user_ec2_describeinstances_attachment" {
|
||||
user = aws_iam_user.user.name
|
||||
policy_arn = aws_iam_policy.ec2_describeinstancest.arn
|
||||
policy_arn = aws_iam_policy.ec2_describeinstances.arn
|
||||
}
|
||||
|
||||
resource "aws_iam_policy" "user_self_manage_policy" {
|
||||
@@ -62,9 +62,29 @@ resource "aws_iam_policy" "user_self_manage_policy" {
|
||||
]
|
||||
}
|
||||
EOF
|
||||
|
||||
tags = var.project_path_tags
|
||||
}
|
||||
|
||||
resource "aws_iam_user_policy_attachement" "user_self_manage_policy_attachment" {
|
||||
resource "aws_iam_user_policy_attachment" "user_self_manage_policy_attachment" {
|
||||
user = aws_iam_user.user.name
|
||||
policy_arn = aws_iam_policy.user_self_manage_policy.arn
|
||||
}
|
||||
|
||||
output "iam_user_name" {
|
||||
value = aws_iam_user.user.name
|
||||
}
|
||||
|
||||
output "iam_user_arn" {
|
||||
value = aws_iam_user.user.arn
|
||||
}
|
||||
|
||||
output "iam_access_key_id" {
|
||||
value = aws_iam_access_key.user_initial_key.id
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
output "iam_secret_access_key" {
|
||||
value = aws_iam_access_key.user_initial_key.secret
|
||||
sensitive = true
|
||||
}
|
||||
File renamed without changes.
+1
-1
@@ -57,7 +57,7 @@ resource "aws_instance" "instances" {
|
||||
ami = data.aws_ami.ubuntu.id
|
||||
instance_type = "t3.nano"
|
||||
|
||||
tags = merge(instance_tags[count.index], var.project_path_tags)
|
||||
tags = merge(var.instance_tags[count.index], var.project_path_tags)
|
||||
}
|
||||
|
||||
output "instance_tags" {
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
resource "random_id" "foo" {
|
||||
byte_length = 2
|
||||
prefix = "test-foo"
|
||||
}
|
||||
|
||||
output "random_id_decimal" {
|
||||
value = random_id.foo.dec
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
package testing
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"sync"
|
||||
|
||||
tfjson "github.com/hashicorp/terraform-json"
|
||||
)
|
||||
|
||||
// TestTerraformer is an object representing the lifecycle of a
|
||||
// particular Terraform project.
|
||||
//
|
||||
// Note that Terraform must be installed in the system PATH (not to
|
||||
// be confused with the working directory below). This object does
|
||||
// not manage anything with regards to installation or version
|
||||
// management.
|
||||
type TestTerraformer struct {
|
||||
// The full path to the Terraform binary, set during initialization
|
||||
// to the binary found in the system path.
|
||||
tfPath string
|
||||
|
||||
// The working directory for Terraform commands.
|
||||
workDir string
|
||||
|
||||
// The Terraform state. Use the Output method to look up particular
|
||||
// outputs from the Terraform state.
|
||||
state *tfjson.State
|
||||
|
||||
// Keeps track of whether or not we have run the init command
|
||||
// during this run of Terraform. This only needs to be done once.
|
||||
// Do not use initErr directly; it stores the init error if one was
|
||||
// encountered on init.
|
||||
initOnce sync.Once
|
||||
initErr error
|
||||
}
|
||||
|
||||
// NewTestTerraformer initializes a Terraform directory. It just
|
||||
// returns an initialized project, it does not perform any actions on
|
||||
// it.
|
||||
func NewTestTerraformer(workDir string) (*TestTerraformer, error) {
|
||||
tfPath, err := exec.LookPath("terraform")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("LookPath error: %w", err)
|
||||
}
|
||||
|
||||
if workDir == "" {
|
||||
return nil, errors.New("workDir is empty")
|
||||
}
|
||||
|
||||
return &TestTerraformer{
|
||||
tfPath: tfPath,
|
||||
workDir: workDir,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Deploy runs the following commands, in order: init, apply, plan,
|
||||
// json. The output of the JSON command is then imported to the
|
||||
// internal state.
|
||||
func (t *TestTerraformer) Deploy() error {
|
||||
if err := t.init(); err != nil {
|
||||
return fmt.Errorf("error running Terraform init: %w", err)
|
||||
}
|
||||
|
||||
if err := t.apply(); err != nil {
|
||||
return fmt.Errorf("error running Terraform apply: %w", err)
|
||||
}
|
||||
|
||||
if err := t.plan(); err != nil {
|
||||
return fmt.Errorf("error running Terraform plan: %w", err)
|
||||
}
|
||||
|
||||
output, err := t.showJson()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting Terraform plan JSON data: %w", err)
|
||||
}
|
||||
|
||||
newState := new(tfjson.Plan)
|
||||
if err := json.Unmarshal(output, newState); err != nil {
|
||||
return fmt.Errorf("error reading new Terraform plan JSON data: %w", err)
|
||||
}
|
||||
|
||||
t.state = newState.PriorState
|
||||
return nil
|
||||
}
|
||||
|
||||
// Destroy runs the following commands, in order: init, destroy. The
|
||||
// state is also cleared.
|
||||
func (t *TestTerraformer) Destroy() error {
|
||||
if err := t.init(); err != nil {
|
||||
return fmt.Errorf("error running Terraform init: %w", err)
|
||||
}
|
||||
|
||||
if err := t.destroy(); err != nil {
|
||||
return fmt.Errorf("error running Terraform destroy: %w", err)
|
||||
}
|
||||
|
||||
t.state = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetOutput returns the value of the output located at key.
|
||||
//
|
||||
// Outputs for the root module are supported only. It's an error to
|
||||
// run this when no state exists.
|
||||
func (t *TestTerraformer) GetOutput(key string) (interface{}, error) {
|
||||
if key == "" {
|
||||
return nil, errors.New("key must not be empty")
|
||||
}
|
||||
|
||||
if t.state == nil {
|
||||
return nil, errors.New("state is nil")
|
||||
}
|
||||
|
||||
if t.state.Values == nil {
|
||||
return nil, errors.New("state integrity error: no state values")
|
||||
}
|
||||
|
||||
if t.state.Values.Outputs == nil {
|
||||
return nil, errors.New("state integrity error: outputs is nil")
|
||||
}
|
||||
|
||||
output, ok := t.state.Values.Outputs[key]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("output with key %q not found", key)
|
||||
}
|
||||
|
||||
if output == nil {
|
||||
return nil, fmt.Errorf("state integrity error: output at key %q is nil", key)
|
||||
}
|
||||
|
||||
return output.Value, nil
|
||||
}
|
||||
|
||||
// init runs "terraform init" in the project's working directory.
|
||||
//
|
||||
// This is only ever done once.
|
||||
func (t *TestTerraformer) init() error {
|
||||
t.initOnce.Do(func() {
|
||||
cmd := exec.Command(t.tfPath, "init")
|
||||
cmd.Dir = t.workDir
|
||||
stdoutStderr, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.initErr = fmt.Errorf("%s\n%s", stdoutStderr, err)
|
||||
}
|
||||
})
|
||||
|
||||
return t.initErr
|
||||
}
|
||||
|
||||
// apply runs "terraform apply" in the project's working directory.
|
||||
func (t *TestTerraformer) apply() error {
|
||||
cmd := exec.Command(t.tfPath, "apply", "-input=false", "-auto-approve")
|
||||
cmd.Dir = t.workDir
|
||||
stdoutStderr, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s\n%s", stdoutStderr, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// destroy runs "terraform destroy" in the project's working directory.
|
||||
func (t *TestTerraformer) destroy() error {
|
||||
cmd := exec.Command(t.tfPath, "destroy", "-input=false", "-auto-approve")
|
||||
cmd.Dir = t.workDir
|
||||
stdoutStderr, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s\n%s", stdoutStderr, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// plan runs "terraform plan" in the project's working directory.
|
||||
//
|
||||
// Note that plan is not run as part of the apply workflow; rather,
|
||||
// it's run to get the data for for importing the state via
|
||||
// terraform-json. The apply method ignores the plan generated here.
|
||||
func (t *TestTerraformer) plan() error {
|
||||
cmd := exec.Command(t.tfPath, "plan", "-input=false", "-out=plan.tfplan")
|
||||
cmd.Dir = t.workDir
|
||||
stdoutStderr, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s\n%s", stdoutStderr, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// showJson runs "terraform show -json". The output is returned along
|
||||
// with any error.
|
||||
//
|
||||
// Output is only the results of stdout and should be suitable for
|
||||
// parsing.
|
||||
//
|
||||
// This method expects the plan.tfplan file to be generated in the
|
||||
// working directory already. This can be done with the plan method.
|
||||
func (t *TestTerraformer) showJson() ([]byte, error) {
|
||||
cmd := exec.Command(t.tfPath, "show", "-json", "plan.tfplan")
|
||||
cmd.Dir = t.workDir
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
exitErr, ok := err.(*exec.ExitError)
|
||||
if !ok {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("%s\n%s", exitErr.Stderr, exitErr)
|
||||
}
|
||||
|
||||
return output, nil
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package testing
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestTestTerraformer(t *testing.T) {
|
||||
require := require.New(t)
|
||||
|
||||
tf, err := NewTestTerraformer("testdata")
|
||||
require.NoError(err)
|
||||
require.NotNil(tf)
|
||||
require.Nil(tf.state)
|
||||
|
||||
err = tf.Deploy()
|
||||
require.NoError(err)
|
||||
require.NotNil(tf.state)
|
||||
|
||||
data, err := tf.GetOutput("random_id_decimal")
|
||||
require.NoError(err)
|
||||
dataStr, ok := data.(string)
|
||||
require.True(ok)
|
||||
require.True(strings.HasPrefix(dataStr, "test-foo"))
|
||||
dataInt, err := strconv.Atoi(strings.TrimPrefix(dataStr, "test-foo"))
|
||||
require.NoError(err)
|
||||
require.NotZero(dataInt)
|
||||
|
||||
err = tf.Destroy()
|
||||
require.NoError(err)
|
||||
require.Nil(tf.state)
|
||||
}
|
||||
Reference in new issue
Block a user