Browse Source

Merge 9cabe5144b into 082b4073ad

pull/63/merge
Jonathan Wright 7 years ago
committed by GitHub
parent
commit
17b79f60ee
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 12
      .drone.yml
  2. 2
      Dockerfile
  3. 25
      README.md
  4. 92
      main.go
  5. 215
      plugin.go
  6. 227
      plugin_test.go

12
.drone.yml

@ -1,12 +1,20 @@
workspace: workspace:
base: /go base: /go
path: src/github.com/drone-plugins/drone-terraform
pipeline: pipeline:
test: test:
image: golang:1.8 image: golang:1.9
environment: environment:
- CGO_ENABLED=0 - CGO_ENABLED=0
commands: commands:
- go test -cover -coverprofile=coverage.out - go test -cover -coverprofile=coverage.out
- go build -ldflags "-s -w -X main.revision=$(git rev-parse HEAD)" -a - go build -ldflags "-s -w -X main.revision=$(git rev-parse HEAD)" -a
build-container:
image: plugins/docker
secrets: [ docker_username, docker_password ]
repo: jonathanio/drone-terraform
auto_tag: true
when:
branch: master

2
Dockerfile

@ -16,7 +16,7 @@ RUN apk -U add \
wget && \ wget && \
rm -rf /var/cache/apk/* rm -rf /var/cache/apk/*
ENV TERRAFORM_VERSION 0.11.3 ENV TERRAFORM_VERSION 0.11.7
RUN wget -q https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip -O terraform.zip && \ RUN wget -q https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip -O terraform.zip && \
unzip terraform.zip -d /bin && \ unzip terraform.zip -d /bin && \
rm -f terraform.zip rm -f terraform.zip

25
README.md

@ -1,15 +1,16 @@
# drone-terraform # drone-terraform
[![Build Status](http://beta.drone.io/api/badges/jmccann/drone-terraform/status.svg)](http://beta.drone.io/jmccann/drone-terraform) [![Build Status](https://drone.nwk.io/api/badges/jonathanio/drone-terraform/status.svg)](https://drone.nwk.io/jonathanio/drone-terraform)
Drone plugin to execute Terraform plan and apply. For the usage information and Drone plugin to execute Terraform. For the usage information and a listing of
a listing of the available options please take a look at [the docs](https://github.com/jmccann/drone-terraform/blob/master/DOCS.md). the available options please take a look at [the
docs](https://github.com/jonathanio/drone-terraform/blob/master/DOCS.md).
## Build ## Build
Build the binary with the following commands: Build the binary with the following commands:
``` ```bash
go build go build
go test go test
``` ```
@ -18,15 +19,15 @@ go test
Build the docker image with the following commands: Build the docker image with the following commands:
``` ```bash
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -tags netgo CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -tags netgo
docker build --rm=true -t jmccann/drone-terraform . docker build --rm=true -t jonathanio/drone-terraform .
``` ```
Please note incorrectly building the image for the correct x64 linux and with Please note incorrectly building the image for the correct x64 linux and with
GCO disabled will result in an error when running the Docker image: GCO disabled will result in an error when running the Docker image:
``` ```text
docker: Error response from daemon: Container command docker: Error response from daemon: Container command
'/bin/drone-terraform' not found or does not exist. '/bin/drone-terraform' not found or does not exist.
``` ```
@ -35,13 +36,15 @@ docker: Error response from daemon: Container command
Execute from the working directory: Execute from the working directory:
``` ```bash
docker run --rm \ docker run --rm \
-v $(pwd):$(pwd) \ -v $(pwd):$(pwd) \
-w $(pwd) \ -w $(pwd) \
jmccann/drone-terraform:latest --plan jonathanio/drone-terraform:latest --plan
``` ```
## Drone 0.4 ## Legacy and Upstream
Legacy `drone-terraform` plugin exists @ `jmccann/drone-terraform:0.4` Access to older versions and upstream versions of `drone-terraform` is
available from the master repository at
[jmccann/drone-terraform](https://github.com/jmccann/drone-terraform).

92
main.go

@ -23,35 +23,45 @@ func main() {
// plugin args // plugin args
// //
cli.BoolFlag{ cli.StringSliceFlag{
Name: "plan", Name: "actions",
Usage: "calculates a plan but does NOT apply it", Usage: "a list of actions to have terraform perform",
EnvVar: "PLUGIN_PLAN", EnvVar: "PLUGIN_ACTIONS",
Value: &cli.StringSlice{"validate", "plan", "apply"},
},
cli.StringFlag{
Name: "ca_cert",
Usage: "ca cert to add to your environment to allow terraform to use internal/private resources",
EnvVar: "PLUGIN_CA_CERT",
},
cli.StringFlag{
Name: "env-file",
Usage: "source env file",
}, },
cli.StringFlag{ cli.StringFlag{
Name: "init_options", Name: "init_options",
Usage: "options for the init command. See https://www.terraform.io/docs/commands/init.html", Usage: "options for the init command. See https://www.terraform.io/docs/commands/init.html",
EnvVar: "PLUGIN_INIT_OPTIONS", EnvVar: "PLUGIN_INIT_OPTIONS",
}, },
cli.StringFlag{ cli.IntFlag{
Name: "vars", Name: "parallelism",
Usage: "a map of variables to pass to the Terraform `plan` and `apply` commands. Each value is passed as a `<key>=<value>` option", Usage: "The number of concurrent operations as Terraform walks its graph",
EnvVar: "PLUGIN_VARS", EnvVar: "PLUGIN_PARALLELISM",
}, },
cli.StringFlag{ cli.StringFlag{
Name: "secrets", Name: "netrc.machine",
Usage: "a map of secrets to pass to the Terraform `plan` and `apply` commands. Each value is passed as a `<key>=<ENV>` option", Usage: "netrc machine",
EnvVar: "PLUGIN_SECRETS", EnvVar: "DRONE_NETRC_MACHINE",
}, },
cli.StringFlag{ cli.StringFlag{
Name: "ca_cert", Name: "netrc.username",
Usage: "ca cert to add to your environment to allow terraform to use internal/private resources", Usage: "netrc username",
EnvVar: "PLUGIN_CA_CERT", EnvVar: "DRONE_NETRC_USERNAME",
}, },
cli.BoolFlag{ cli.StringFlag{
Name: "sensitive", Name: "netrc.password",
Usage: "whether or not to suppress terraform commands to stdout", Usage: "netrc password",
EnvVar: "PLUGIN_SENSITIVE", EnvVar: "DRONE_NETRC_PASSWORD",
}, },
cli.StringFlag{ cli.StringFlag{
Name: "role_arn_to_assume", Name: "role_arn_to_assume",
@ -63,38 +73,36 @@ func main() {
Usage: "The root directory where the terraform files live. When unset, the top level directory will be assumed", Usage: "The root directory where the terraform files live. When unset, the top level directory will be assumed",
EnvVar: "PLUGIN_ROOT_DIR", EnvVar: "PLUGIN_ROOT_DIR",
}, },
cli.IntFlag{
Name: "parallelism",
Usage: "The number of concurrent operations as Terraform walks its graph",
EnvVar: "PLUGIN_PARALLELISM",
},
cli.StringFlag{ cli.StringFlag{
Name: "env-file", Name: "secrets",
Usage: "source env file", Usage: "a map of secrets to pass to the Terraform `plan` and `apply` commands. Each value is passed as a `<key>=<ENV>` option",
EnvVar: "PLUGIN_SECRETS",
},
cli.BoolFlag{
Name: "sensitive",
Usage: "whether or not to suppress terraform commands to stdout",
EnvVar: "PLUGIN_SENSITIVE",
}, },
cli.StringSliceFlag{ cli.StringSliceFlag{
Name: "targets", Name: "targets",
Usage: "targets to run apply or plan on", Usage: "targets to run apply or plan on",
EnvVar: "PLUGIN_TARGETS", EnvVar: "PLUGIN_TARGETS",
}, },
cli.StringSliceFlag{
Name: "var_files",
Usage: "a list of var files to use. Each value is passed as -var-file=<value>",
EnvVar: "PLUGIN_VAR_FILES",
},
cli.BoolFlag{
Name: "destroy",
Usage: "destory all resurces",
EnvVar: "PLUGIN_DESTROY",
},
cli.StringFlag{ cli.StringFlag{
Name: "tf.version", Name: "tf.version",
Usage: "terraform version to use", Usage: "terraform version to use",
EnvVar: "PLUGIN_TF_VERSION", EnvVar: "PLUGIN_TF_VERSION",
}, },
cli.StringFlag{
Name: "vars",
Usage: "a map of variables to pass to the Terraform `plan` and `apply` commands. Each value is passed as a `<key>=<value>` option",
EnvVar: "PLUGIN_VARS",
},
cli.StringSliceFlag{
Name: "var_files",
Usage: "a list of var files to use. Each value is passed as -var-file=<value>",
EnvVar: "PLUGIN_VAR_FILES",
},
} }
if err := app.Run(os.Args); err != nil { if err := app.Run(os.Args); err != nil {
@ -129,7 +137,7 @@ func run(c *cli.Context) error {
plugin := Plugin{ plugin := Plugin{
Config: Config{ Config: Config{
Plan: c.Bool("plan"), Actions: c.StringSlice("actions"),
Vars: vars, Vars: vars,
Secrets: secrets, Secrets: secrets,
InitOptions: initOptions, InitOptions: initOptions,
@ -140,7 +148,11 @@ func run(c *cli.Context) error {
Parallelism: c.Int("parallelism"), Parallelism: c.Int("parallelism"),
Targets: c.StringSlice("targets"), Targets: c.StringSlice("targets"),
VarFiles: c.StringSlice("var_files"), VarFiles: c.StringSlice("var_files"),
Destroy: c.Bool("destroy"), },
Netrc: Netrc{
Login: c.String("netrc.username"),
Machine: c.String("netrc.machine"),
Password: c.String("netrc.password"),
}, },
Terraform: Terraform{ Terraform: Terraform{
Version: c.String("tf.version"), Version: c.String("tf.version"),

215
plugin.go

@ -5,6 +5,8 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"os/exec" "os/exec"
"os/user"
"path/filepath"
"regexp" "regexp"
"strings" "strings"
"time" "time"
@ -19,7 +21,7 @@ import (
type ( type (
// Config holds input parameters for the plugin // Config holds input parameters for the plugin
Config struct { Config struct {
Plan bool Actions []string
Vars map[string]string Vars map[string]string
Secrets map[string]string Secrets map[string]string
InitOptions InitOptions InitOptions InitOptions
@ -30,7 +32,12 @@ type (
Parallelism int Parallelism int
Targets []string Targets []string
VarFiles []string VarFiles []string
Destroy bool }
Netrc struct {
Machine string
Login string
Password string
} }
// InitOptions include options for the Terraform's init command // InitOptions include options for the Terraform's init command
@ -43,6 +50,7 @@ type (
// Plugin represents the plugin instance to be executed // Plugin represents the plugin instance to be executed
Plugin struct { Plugin struct {
Config Config Config Config
Netrc Netrc
Terraform Terraform Terraform Terraform
} }
) )
@ -62,6 +70,12 @@ func (p Plugin) Exec() error {
assumeRole(p.Config.RoleARN) assumeRole(p.Config.RoleARN)
} }
// writing the .netrc file with Github credentials in it.
err := writeNetrc(p.Netrc.Machine, p.Netrc.Login, p.Netrc.Password)
if err != nil {
return err
}
var commands []*exec.Cmd var commands []*exec.Cmd
commands = append(commands, exec.Command("terraform", "version")) commands = append(commands, exec.Command("terraform", "version"))
@ -73,15 +87,27 @@ func (p Plugin) Exec() error {
} }
commands = append(commands, deleteCache()) commands = append(commands, deleteCache())
commands = append(commands, initCommand(p.Config.InitOptions)) commands = append(commands, initCommand(p.Config.InitOptions))
commands = append(commands, getModules()) commands = append(commands, getModules())
commands = append(commands, validateCommand(p.Config))
commands = append(commands, planCommand(p.Config)) // Add commands listed from Actions
if !p.Config.Plan { for _, action := range p.Config.Actions {
commands = append(commands, terraformCommand(p.Config)) switch action {
case "validate":
commands = append(commands, tfValidate(p.Config))
case "plan":
commands = append(commands, tfPlan(p.Config, false))
case "plan-destroy":
commands = append(commands, tfPlan(p.Config, true))
case "apply":
commands = append(commands, tfApply(p.Config))
case "destroy":
commands = append(commands, tfDestroy(p.Config))
default:
return fmt.Errorf("valid actions are: validate, plan, apply, plan-destroy, destroy. You provided %s", action)
}
} }
commands = append(commands, deleteCache()) commands = append(commands, deleteCache())
for _, c := range commands { for _, c := range commands {
@ -112,13 +138,7 @@ func (p Plugin) Exec() error {
return nil return nil
} }
func installCaCert(cacert string) *exec.Cmd { // CopyTfEnv creates copies of TF_VAR_ to lowercase
ioutil.WriteFile("/usr/local/share/ca-certificates/ca_cert.crt", []byte(cacert), 0644)
return exec.Command(
"update-ca-certificates",
)
}
func CopyTfEnv() { func CopyTfEnv() {
tfVar := regexp.MustCompile(`^TF_VAR_.*$`) tfVar := regexp.MustCompile(`^TF_VAR_.*$`)
for _, e := range os.Environ() { for _, e := range os.Environ() {
@ -130,6 +150,27 @@ func CopyTfEnv() {
} }
} }
func assumeRole(roleArn string) {
client := sts.New(session.New())
duration := time.Hour * 1
stsProvider := &stscreds.AssumeRoleProvider{
Client: client,
Duration: duration,
RoleARN: roleArn,
RoleSessionName: "drone",
}
value, err := credentials.NewCredentials(stsProvider).Get()
if err != nil {
logrus.WithFields(logrus.Fields{
"error": err,
}).Fatal("Error assuming role!")
}
os.Setenv("AWS_ACCESS_KEY_ID", value.AccessKeyID)
os.Setenv("AWS_SECRET_ACCESS_KEY", value.SecretAccessKey)
os.Setenv("AWS_SESSION_TOKEN", value.SessionToken)
}
func deleteCache() *exec.Cmd { func deleteCache() *exec.Cmd {
return exec.Command( return exec.Command(
"rm", "rm",
@ -138,6 +179,13 @@ func deleteCache() *exec.Cmd {
) )
} }
func getModules() *exec.Cmd {
return exec.Command(
"terraform",
"get",
)
}
func initCommand(config InitOptions) *exec.Cmd { func initCommand(config InitOptions) *exec.Cmd {
args := []string{ args := []string{
"init", "init",
@ -166,50 +214,24 @@ func initCommand(config InitOptions) *exec.Cmd {
) )
} }
func getModules() *exec.Cmd { func installCaCert(cacert string) *exec.Cmd {
ioutil.WriteFile("/usr/local/share/ca-certificates/ca_cert.crt", []byte(cacert), 0644)
return exec.Command( return exec.Command(
"terraform", "update-ca-certificates",
"get",
) )
} }
func validateCommand(config Config) *exec.Cmd { func trace(cmd *exec.Cmd) {
args := []string{ fmt.Println("$", strings.Join(cmd.Args, " "))
"validate",
}
for _, v := range config.VarFiles {
args = append(args, "-var-file", fmt.Sprintf("%s", v))
}
for k, v := range config.Vars {
args = append(args, "-var")
args = append(args, fmt.Sprintf("%s=%s", k, v))
}
return exec.Command(
"terraform",
args...,
)
} }
func planCommand(config Config) *exec.Cmd { func tfApply(config Config) *exec.Cmd {
args := []string{ args := []string{
"plan", "apply",
}
if config.Destroy {
args = append(args, "-destroy")
} else {
args = append(args, "-out=plan.tfout")
} }
for _, v := range config.Targets { for _, v := range config.Targets {
args = append(args, "--target", fmt.Sprintf("%s", v)) args = append(args, "--target", fmt.Sprintf("%s", v))
} }
for _, v := range config.VarFiles {
args = append(args, "-var-file", fmt.Sprintf("%s", v))
}
for k, v := range config.Vars {
args = append(args, "-var")
args = append(args, fmt.Sprintf("%s=%s", k, v))
}
if config.Parallelism > 0 { if config.Parallelism > 0 {
args = append(args, fmt.Sprintf("-parallelism=%d", config.Parallelism)) args = append(args, fmt.Sprintf("-parallelism=%d", config.Parallelism))
} }
@ -219,26 +241,19 @@ func planCommand(config Config) *exec.Cmd {
if config.InitOptions.LockTimeout != "" { if config.InitOptions.LockTimeout != "" {
args = append(args, fmt.Sprintf("-lock-timeout=%s", config.InitOptions.LockTimeout)) args = append(args, fmt.Sprintf("-lock-timeout=%s", config.InitOptions.LockTimeout))
} }
args = append(args, "plan.tfout")
return exec.Command( return exec.Command(
"terraform", "terraform",
args..., args...,
) )
} }
func terraformCommand(config Config) *exec.Cmd { func tfDestroy(config Config) *exec.Cmd {
if config.Destroy {
return destroyCommand(config)
}
return applyCommand(config)
}
func applyCommand(config Config) *exec.Cmd {
args := []string{ args := []string{
"apply", "destroy",
} }
for _, v := range config.Targets { for _, v := range config.Targets {
args = append(args, "--target", fmt.Sprintf("%s", v)) args = append(args, fmt.Sprintf("-target=%s", v))
} }
if config.Parallelism > 0 { if config.Parallelism > 0 {
args = append(args, fmt.Sprintf("-parallelism=%d", config.Parallelism)) args = append(args, fmt.Sprintf("-parallelism=%d", config.Parallelism))
@ -249,19 +264,33 @@ func applyCommand(config Config) *exec.Cmd {
if config.InitOptions.LockTimeout != "" { if config.InitOptions.LockTimeout != "" {
args = append(args, fmt.Sprintf("-lock-timeout=%s", config.InitOptions.LockTimeout)) args = append(args, fmt.Sprintf("-lock-timeout=%s", config.InitOptions.LockTimeout))
} }
args = append(args, "plan.tfout") args = append(args, "-force")
return exec.Command( return exec.Command(
"terraform", "terraform",
args..., args...,
) )
} }
func destroyCommand(config Config) *exec.Cmd { func tfPlan(config Config, destroy bool) *exec.Cmd {
args := []string{ args := []string{
"destroy", "plan",
} }
if destroy {
args = append(args, "-destroy")
} else {
args = append(args, "-out=plan.tfout")
}
for _, v := range config.Targets { for _, v := range config.Targets {
args = append(args, fmt.Sprintf("-target=%s", v)) args = append(args, "--target", fmt.Sprintf("%s", v))
}
for _, v := range config.VarFiles {
args = append(args, "-var-file", fmt.Sprintf("%s", v))
}
for k, v := range config.Vars {
args = append(args, "-var")
args = append(args, fmt.Sprintf("%s=%s", k, v))
} }
if config.Parallelism > 0 { if config.Parallelism > 0 {
args = append(args, fmt.Sprintf("-parallelism=%d", config.Parallelism)) args = append(args, fmt.Sprintf("-parallelism=%d", config.Parallelism))
@ -272,34 +301,54 @@ func destroyCommand(config Config) *exec.Cmd {
if config.InitOptions.LockTimeout != "" { if config.InitOptions.LockTimeout != "" {
args = append(args, fmt.Sprintf("-lock-timeout=%s", config.InitOptions.LockTimeout)) args = append(args, fmt.Sprintf("-lock-timeout=%s", config.InitOptions.LockTimeout))
} }
args = append(args, "-force")
return exec.Command( return exec.Command(
"terraform", "terraform",
args..., args...,
) )
} }
func assumeRole(roleArn string) { func tfValidate(config Config) *exec.Cmd {
client := sts.New(session.New()) args := []string{
duration := time.Hour * 1 "validate",
stsProvider := &stscreds.AssumeRoleProvider{
Client: client,
Duration: duration,
RoleARN: roleArn,
RoleSessionName: "drone",
} }
for _, v := range config.VarFiles {
value, err := credentials.NewCredentials(stsProvider).Get() args = append(args, "-var-file", fmt.Sprintf("%s", v))
if err != nil {
logrus.WithFields(logrus.Fields{
"error": err,
}).Fatal("Error assuming role!")
} }
os.Setenv("AWS_ACCESS_KEY_ID", value.AccessKeyID) for k, v := range config.Vars {
os.Setenv("AWS_SECRET_ACCESS_KEY", value.SecretAccessKey) args = append(args, "-var")
os.Setenv("AWS_SESSION_TOKEN", value.SessionToken) args = append(args, fmt.Sprintf("%s=%s", k, v))
}
return exec.Command(
"terraform",
args...,
)
} }
func trace(cmd *exec.Cmd) { // helper function to write a netrc file.
fmt.Println("$", strings.Join(cmd.Args, " ")) // The following code comes from the official Git plugin for Drone:
// https://github.com/drone-plugins/drone-git/blob/8386effd2fe8c8695cf979427f8e1762bd805192/utils.go#L43-L68
func writeNetrc(machine, login, password string) error {
if machine == "" {
return nil
}
out := fmt.Sprintf(
netrcFile,
machine,
login,
password,
)
home := "/root"
u, err := user.Current()
if err == nil {
home = u.HomeDir
}
path := filepath.Join(home, ".netrc")
return ioutil.WriteFile(path, []byte(out), 0600)
} }
const netrcFile = `
machine %s
login %s
password %s
`

227
plugin_test.go

@ -3,138 +3,11 @@ package main
import ( import (
"os" "os"
"os/exec" "os/exec"
"reflect"
"testing" "testing"
. "github.com/franela/goblin" . "github.com/franela/goblin"
) )
func Test_destroyCommand(t *testing.T) {
type args struct {
config Config
}
tests := []struct {
name string
args args
want *exec.Cmd
}{
{
"default",
args{config: Config{}},
exec.Command("terraform", "destroy", "-force"),
},
{
"with targets",
args{config: Config{Targets: []string{"target1", "target2"}}},
exec.Command("terraform", "destroy", "-target=target1", "-target=target2", "-force"),
},
{
"with parallelism",
args{config: Config{Parallelism: 5}},
exec.Command("terraform", "destroy", "-parallelism=5", "-force"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := destroyCommand(tt.args.config); !reflect.DeepEqual(got, tt.want) {
t.Errorf("destroyCommand() = %v, want %v", got, tt.want)
}
})
}
}
func Test_applyCommand(t *testing.T) {
type args struct {
config Config
}
tests := []struct {
name string
args args
want *exec.Cmd
}{
{
"default",
args{config: Config{}},
exec.Command("terraform", "apply", "plan.tfout"),
},
{
"with targets",
args{config: Config{Targets: []string{"target1", "target2"}}},
exec.Command("terraform", "apply", "--target", "target1", "--target", "target2", "plan.tfout"),
},
{
"with parallelism",
args{config: Config{Parallelism: 5}},
exec.Command("terraform", "apply", "-parallelism=5", "plan.tfout"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := applyCommand(tt.args.config); !reflect.DeepEqual(got, tt.want) {
t.Errorf("applyCommand() = %v, want %v", got, tt.want)
}
})
}
}
func Test_terraformCommand(t *testing.T) {
type args struct {
config Config
}
tests := []struct {
name string
args args
want *exec.Cmd
}{
{
"default",
args{config: Config{}},
exec.Command("terraform", "apply", "plan.tfout"),
},
{
"destroy",
args{config: Config{Destroy: true}},
exec.Command("terraform", "destroy", "-force"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := terraformCommand(tt.args.config); !reflect.DeepEqual(got, tt.want) {
t.Errorf("terraformCommand() = %v, want %v", got, tt.want)
}
})
}
}
func Test_planCommand(t *testing.T) {
type args struct {
config Config
}
tests := []struct {
name string
args args
want *exec.Cmd
}{
{
"default",
args{config: Config{}},
exec.Command("terraform", "plan", "-out=plan.tfout"),
},
{
"destroy",
args{config: Config{Destroy: true}},
exec.Command("terraform", "plan", "-destroy"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := planCommand(tt.args.config); !reflect.DeepEqual(got, tt.want) {
t.Errorf("planCommand() = %v, want %v", got, tt.want)
}
})
}
}
func TestPlugin(t *testing.T) { func TestPlugin(t *testing.T) {
g := Goblin(t) g := Goblin(t)
@ -153,4 +26,104 @@ func TestPlugin(t *testing.T) {
g.Assert(os.Getenv("TF_VAR_base64")).Equal("dGVzdA==") g.Assert(os.Getenv("TF_VAR_base64")).Equal("dGVzdA==")
}) })
}) })
g.Describe("tfApply", func() {
g.It("Should return correct apply commands given the arguments", func() {
type args struct {
config Config
}
tests := []struct {
name string
args args
want *exec.Cmd
}{
{
"default",
args{config: Config{}},
exec.Command("terraform", "apply", "plan.tfout"),
},
{
"with targets",
args{config: Config{Targets: []string{"target1", "target2"}}},
exec.Command("terraform", "apply", "--target", "target1", "--target", "target2", "plan.tfout"),
},
{
"with parallelism",
args{config: Config{Parallelism: 5}},
exec.Command("terraform", "apply", "-parallelism=5", "plan.tfout"),
},
}
for _, tt := range tests {
g.Assert(tfApply(tt.args.config)).Equal(tt.want)
}
})
})
g.Describe("tfDestroy", func() {
g.It("Should return correct destroy commands given the arguments", func() {
type args struct {
config Config
}
tests := []struct {
name string
args args
want *exec.Cmd
}{
{
"default",
args{config: Config{}},
exec.Command("terraform", "destroy", "-force"),
},
{
"with targets",
args{config: Config{Targets: []string{"target1", "target2"}}},
exec.Command("terraform", "destroy", "-target=target1", "-target=target2", "-force"),
},
{
"with parallelism",
args{config: Config{Parallelism: 5}},
exec.Command("terraform", "destroy", "-parallelism=5", "-force"),
},
}
for _, tt := range tests {
g.Assert(tfDestroy(tt.args.config)).Equal(tt.want)
}
})
})
g.Describe("tfPlan", func() {
g.It("Should return correct plan commands given the arguments", func() {
type args struct {
config Config
}
tests := []struct {
name string
args args
destroy bool
want *exec.Cmd
}{
{
"default",
args{config: Config{}},
false,
exec.Command("terraform", "plan", "-out=plan.tfout"),
},
{
"destroy",
args{config: Config{}},
true,
exec.Command("terraform", "plan", "-destroy"),
},
}
for _, tt := range tests {
g.Assert(tfPlan(tt.args.config, tt.destroy)).Equal(tt.want)
}
})
})
} }

Loading…
Cancel
Save