Skip to content

Commit

Permalink
Merge pull request #9 from leapfrogtechnology/destroy-infra
Browse files Browse the repository at this point in the history
destroy existing infrastructure
  • Loading branch information
pratishshr authored Oct 24, 2019
2 parents e7512a0 + 99b265c commit 6bebf94
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 40 deletions.
10 changes: 9 additions & 1 deletion cli/cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,20 @@ func Initialize(info *Info) error {
Name: "deploy",
Action: func(ctx *cli.Context) error {
environment := ctx.Args().Get(0)

Deploy(environment)

return nil
},
},
cli.Command{
Name: "destroy",
Action: func(ctx *cli.Context) error {
environment := ctx.Args().Get(0)
Destroy(environment)

return nil
},
},
cli.Command{
Name: "add",
Subcommands: []cli.Command{
Expand Down
8 changes: 8 additions & 0 deletions cli/cmd/destroy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package cmd

import "github.com/leapfrogtechnology/shift/cli/internals/destroy"

// Destroy deletes existing infrastructure
func Destroy(environment string) {
destroy.Run(environment)
}
55 changes: 55 additions & 0 deletions cli/internals/destroy/destroy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package destroy

import (
"errors"
"path/filepath"
"strings"

"github.com/AlecAivazis/survey/v2"
"github.com/leapfrogtechnology/shift/core/services/storage"
"github.com/leapfrogtechnology/shift/core/utils/file"
"github.com/leapfrogtechnology/shift/core/utils/system/exit"
"github.com/leapfrogtechnology/shift/infrastructure/internals/terraform"
)

func askConfirmation(environment, projectName string) string {
confirmation := ""
prompt := &survey.Input{
Message: "Are you sure you want to destroy " + environment + " environment from " + projectName + " ?(Y/N): ",
}
survey.AskOne(prompt, &confirmation)

return confirmation
}

// Run initializes destruction of infrastructure
func Run(environment string) {
project := storage.Read()
_, env := project.Env[environment]

if !env {
const message = "Unknown Environment type "
exit.Error(errors.New(message+"'"+environment+"'"), "Error")
}

confirmation := askConfirmation(environment, project.Name)

if strings.EqualFold(confirmation, "Y") || strings.EqualFold(confirmation, "yes") {

workspaceRoot := "/tmp"
workspaceDir := filepath.Join(workspaceRoot, project.Name, project.Type, environment)
terraformFile := workspaceDir + "/infrastructure.tf"

exists := file.Exists(terraformFile)

if exists {
terraform.DestroyInfrastructure(workspaceDir)
} else {
terraform.MakeTempAndDestroy(project, environment, workspaceDir)
}

} else {
const message = "Operation aborted"
exit.Error(errors.New(message), "Cancelled")
}
}
9 changes: 9 additions & 0 deletions core/utils/file/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package file

import (
"mime"
"os"
"strings"
)

Expand All @@ -17,3 +18,11 @@ func GetFileContentType(filename string) string {

return mime.TypeByExtension("." + ext)
}

// Exists check existence of file
func Exists(filepath string) bool {
if _, err := os.Stat(filepath); err == nil {
return true
}
return false
}
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190530182044-ad28b68e88f1 h1:R4dVlxdmKenVdMRS/tTspEpSTRWINYrHD8ySIU9yCIU=
golang.org/x/sys v0.0.0-20190530182044-ad28b68e88f1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
Expand Down
113 changes: 74 additions & 39 deletions infrastructure/internals/terraform/terraform.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,79 +2,80 @@ package terraform

import (
"bytes"
"fmt"
"errors"
"os"
"os/exec"
"time"

"github.com/briandowns/spinner"
"github.com/leapfrogtechnology/shift/core/structs"
"github.com/leapfrogtechnology/shift/core/utils/logger"
"github.com/leapfrogtechnology/shift/core/utils/spinner"
"github.com/leapfrogtechnology/shift/infrastructure/internals/terraform/templates/providers/aws/template"
"github.com/leapfrogtechnology/shift/infrastructure/services/terraform"
)

// TODO use terraform Library to remove the dependency of installing terraform

func initTerraform(workspaceDir string) error {
s := spinner.New(spinner.CharSets[11], 100*time.Millisecond) // Build our new spinner
s.Prefix = " "
s.Suffix = " Initializing"
_ = s.Color("cyan", "bold")
s.Start()
logger.LogInfo(" Initializing")
spinner.Start(" ")

cmd := exec.Command("terraform", "init")
cmd.Dir = workspaceDir
var stdout bytes.Buffer
var stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr

cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr

err := cmd.Run()
if err != nil {
fmt.Println()
s.Stop()
logger.LogError(err, "")
spinner.Stop()
return err
}
s.Stop()
spinner.Stop()

return nil
}

func applyTerraform(workspaceDir string) error {
s := spinner.New(spinner.CharSets[11], 100*time.Millisecond) // Build our new spinner
s.Prefix = " "
s.Suffix = " Applying Changes"
_ = s.Color("cyan", "bold")
s.Start()
logger.LogInfo(" Applying Changes")
spinner.Start(" ")

cmd := exec.Command("terraform", "apply", "--auto-approve")
cmd.Dir = workspaceDir
var stdout bytes.Buffer
var stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr

cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr

err := cmd.Run()
if err != nil {
logger.LogError(err, stderr.String())
s.Stop()
logger.LogError(err, "Error While terraform apply")
spinner.Stop()
return err
}
s.Stop()
spinner.Stop()

return nil
}

func getTerraformOutput(workspaceDir string) (string, error) {
s := spinner.New(spinner.CharSets[11], 100*time.Millisecond) // Build our new spinner
s.Prefix = " "
s.Suffix = " Generating Output"
_ = s.Color("cyan", "bold")
s.Start()
logger.LogInfo(" Generating Output")
spinner.Start(" ")

cmd := exec.Command("terraform", "output", "-json")
cmd.Dir = workspaceDir
var stdout bytes.Buffer
var stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()

if err != nil {
logger.LogError(err, stderr.String())
s.Stop()
spinner.Stop()
return "", err
}
s.Stop()

spinner.Stop()

return stdout.String(), err
}
Expand All @@ -86,7 +87,6 @@ func RunInfrastructureChanges(workspaceDir string, workspaceName string) (string

// Set local execution instead of remote.
terraform.ActivateLocalRun(workspaceName)

if err != nil {
logger.LogError(err, "Couldnot initialize")

Expand All @@ -95,15 +95,13 @@ func RunInfrastructureChanges(workspaceDir string, workspaceName string) (string

logger.LogInfo("Applying")
err = applyTerraform(workspaceDir)

if err != nil {
logger.LogError(err, "Failed to apply changes")

return "", err
}

out, err := getTerraformOutput(workspaceDir)

if err != nil {
logger.LogError(err, "Failed to get terraform output")

Expand All @@ -112,3 +110,40 @@ func RunInfrastructureChanges(workspaceDir string, workspaceName string) (string

return out, err
}

// DestroyInfrastructure destroys existing infrastructure
func DestroyInfrastructure(workspaceDir string) error {
logger.LogInfo("Destroying Infrastructure...")
spinner.Start(" ")
cmd := exec.Command("terraform", "destroy", "--auto-approve")
cmd.Dir = workspaceDir

cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()

const message = " ERROR While Destroying Infrastructure"
if err != nil {
logger.LogError(err, message)
spinner.Stop()
return errors.New(err.Error() + message)
}
spinner.Stop()

return nil
}

// MakeTempAndDestroy create infrastructure template and distroy the infrastructure
func MakeTempAndDestroy(project structs.Project, environment, workspaceDir string) error {
logger.LogInfo("Generating Templates....")

if project.Type == "Frontend" {
template.GenerateFrontendTemplate(project, workspaceDir, environment)
} else {
// TODO backend
}
initTerraform(workspaceDir)
err := DestroyInfrastructure(workspaceDir)

return err
}

0 comments on commit 6bebf94

Please sign in to comment.