You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
191 lines
3.9 KiB
191 lines
3.9 KiB
8 years ago
|
package main
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
||
|
"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
|
||
|
"github.com/aws/aws-sdk-go/aws/session"
|
||
|
"github.com/aws/aws-sdk-go/service/sts"
|
||
|
"io/ioutil"
|
||
|
"os"
|
||
|
"os/exec"
|
||
|
"strings"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
buildCommit string
|
||
|
)
|
||
|
|
||
|
type (
|
||
|
Config struct {
|
||
|
Remote Remote
|
||
|
Plan bool
|
||
|
Vars map[string]string
|
||
|
Secrets map[string]string
|
||
|
Cacert string
|
||
|
Sensitive bool
|
||
|
RoleARN string
|
||
|
RootDir string
|
||
|
Parallelism int
|
||
|
}
|
||
|
|
||
|
Remote struct {
|
||
|
Backend string `json:"backend"`
|
||
|
Config map[string]string `json:"config"`
|
||
|
}
|
||
|
|
||
|
Plugin struct {
|
||
|
Config Config
|
||
|
}
|
||
|
)
|
||
|
|
||
|
func (p Plugin) Exec() error {
|
||
|
fmt.Printf("Drone Terraform Plugin built from %s\n", buildCommit)
|
||
|
|
||
|
if p.Config.RoleARN != "" {
|
||
|
assumeRole(p.Config.RoleARN)
|
||
|
}
|
||
|
|
||
|
var commands []*exec.Cmd
|
||
|
remote := p.Config.Remote
|
||
|
if p.Config.Cacert != "" {
|
||
|
commands = append(commands, installCaCert(p.Config.Cacert))
|
||
|
}
|
||
|
if remote.Backend != "" {
|
||
|
commands = append(commands, deleteCache())
|
||
|
commands = append(commands, remoteConfigCommand(remote))
|
||
|
}
|
||
|
commands = append(commands, getModules())
|
||
|
commands = append(commands, planCommand(p.Config.Vars, p.Config.Secrets, p.Config.Parallelism))
|
||
|
if !p.Config.Plan {
|
||
|
commands = append(commands, applyCommand(p.Config.Parallelism))
|
||
|
}
|
||
|
commands = append(commands, deleteCache())
|
||
|
|
||
|
for _, c := range commands {
|
||
|
if c.Dir == "" {
|
||
|
wd, err := os.Getwd()
|
||
|
if err == nil {
|
||
|
c.Dir = wd
|
||
|
}
|
||
|
}
|
||
|
if p.Config.RootDir != "" {
|
||
|
c.Dir = c.Dir + "/" + p.Config.RootDir
|
||
|
}
|
||
|
c.Stdout = os.Stdout
|
||
|
c.Stderr = os.Stderr
|
||
|
if !p.Config.Sensitive {
|
||
|
trace(c)
|
||
|
}
|
||
|
|
||
|
err := c.Run()
|
||
|
if err != nil {
|
||
|
fmt.Println("Error!")
|
||
|
fmt.Println(err)
|
||
|
os.Exit(1)
|
||
|
}
|
||
|
fmt.Println("Command completed successfully")
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func installCaCert(cacert string) *exec.Cmd {
|
||
|
ioutil.WriteFile("/usr/local/share/ca-certificates/ca_cert.crt", []byte(cacert), 0644)
|
||
|
return exec.Command(
|
||
|
"update-ca-certificates",
|
||
|
)
|
||
|
}
|
||
|
|
||
|
func deleteCache() *exec.Cmd {
|
||
|
return exec.Command(
|
||
|
"rm",
|
||
|
"-rf",
|
||
|
".terraform",
|
||
|
)
|
||
|
}
|
||
|
|
||
|
func remoteConfigCommand(config Remote) *exec.Cmd {
|
||
|
args := []string{
|
||
|
"remote",
|
||
|
"config",
|
||
|
fmt.Sprintf("-backend=%s", config.Backend),
|
||
|
}
|
||
|
for k, v := range config.Config {
|
||
|
args = append(args, fmt.Sprintf("-backend-config=%s=%s", k, v))
|
||
|
}
|
||
|
return exec.Command(
|
||
|
"terraform",
|
||
|
args...,
|
||
|
)
|
||
|
}
|
||
|
|
||
|
func getModules() *exec.Cmd {
|
||
|
return exec.Command(
|
||
|
"terraform",
|
||
|
"get",
|
||
|
)
|
||
|
}
|
||
|
|
||
|
func planCommand(variables map[string]string, secrets map[string]string, parallelism int) *exec.Cmd {
|
||
|
args := []string{
|
||
|
"plan",
|
||
|
"-out=plan.tfout",
|
||
|
}
|
||
|
for k, v := range variables {
|
||
|
args = append(args, "-var")
|
||
|
args = append(args, fmt.Sprintf("%s=%s", k, v))
|
||
|
}
|
||
|
for k, v := range secrets {
|
||
|
args = append(args, "-var")
|
||
|
args = append(args, fmt.Sprintf("%s=%s", k, os.Getenv(v)))
|
||
|
}
|
||
|
if parallelism > 0 {
|
||
|
args = append(args, fmt.Sprintf("-parallelism=%d", parallelism))
|
||
|
}
|
||
|
return exec.Command(
|
||
|
"terraform",
|
||
|
args...,
|
||
|
)
|
||
|
}
|
||
|
|
||
|
func applyCommand(parallelism int) *exec.Cmd {
|
||
|
args := []string{
|
||
|
"apply",
|
||
|
}
|
||
|
if parallelism > 0 {
|
||
|
args = append(args, fmt.Sprintf("-parallelism=%d", parallelism))
|
||
|
}
|
||
|
args = append(args, "plan.tfout")
|
||
|
return exec.Command(
|
||
|
"terraform",
|
||
|
args...,
|
||
|
)
|
||
|
}
|
||
|
|
||
|
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 {
|
||
|
fmt.Println("Error assuming role!")
|
||
|
fmt.Println(err)
|
||
|
os.Exit(1)
|
||
|
}
|
||
|
os.Setenv("AWS_ACCESS_KEY_ID", value.AccessKeyID)
|
||
|
os.Setenv("AWS_SECRET_ACCESS_KEY", value.SecretAccessKey)
|
||
|
os.Setenv("AWS_SESSION_TOKEN", value.SessionToken)
|
||
|
}
|
||
|
|
||
|
func trace(cmd *exec.Cmd) {
|
||
|
fmt.Println("$", strings.Join(cmd.Args, " "))
|
||
|
}
|