Skip to content

Commit

Permalink
extract builders and command from main.go
Browse files Browse the repository at this point in the history
Still to refactor: exit errors and trapping SIGINT

Signed-off-by: Henry Stanley <[email protected]>
  • Loading branch information
tinygrasshopper authored and Henry Stanley committed Sep 26, 2017
1 parent 2d3bbbe commit cd43158
Show file tree
Hide file tree
Showing 28 changed files with 949 additions and 590 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main_test
package command

import (
. "github.com/onsi/ginkgo"
Expand Down
3 changes: 1 addition & 2 deletions cmd/bbr/bbr_test.go → cli/command/command_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package main_test
package command

import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/cloudfoundry-incubator/bosh-backup-and-restore/cmd/bbr"
)

var _ = Describe("bbr", func() {
Expand Down
58 changes: 58 additions & 0 deletions cli/command/deployment_backup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package command

import (
"github.com/cloudfoundry-incubator/bosh-backup-and-restore/factory"
"github.com/cloudfoundry-incubator/bosh-backup-and-restore/orchestrator"
"github.com/pkg/errors"
"github.com/urfave/cli"
)

type DeploymentBackupCommand struct {
}

func NewDeploymentBackupCommand() DeploymentBackupCommand {
return DeploymentBackupCommand{}
}

func (d DeploymentBackupCommand) Cli() cli.Command {
return cli.Command{
Name: "backup",
Aliases: []string{"b"},
Usage: "Backup a deployment",
Action: d.Action,
Flags: []cli.Flag{cli.BoolFlag{
Name: "with-manifest",
Usage: "Download the deployment manifest",
}},
}
}

func (d DeploymentBackupCommand) Action(c *cli.Context) error {
trapSigint(true)

backuper, err := factory.BuildDeploymentBackuper(c.Parent().String("target"),
c.Parent().String("username"),
c.Parent().String("password"),
c.Parent().String("ca-cert"),
c.Bool("with-manifest"),
c.GlobalBool("debug"),
)

if err != nil {
return redCliError(err)
}

deployment := c.Parent().String("deployment")
backupErr := backuper.Backup(deployment)

errorCode, errorMessage, errorWithStackTrace := orchestrator.ProcessError(backupErr)
if err := writeStackTrace(errorWithStackTrace); err != nil {
return errors.Wrap(backupErr, err.Error())
}

if backupErr.ContainsUnlockOrCleanup() {
errorMessage = errorMessage + "\n" + backupCleanupAdvisedNotice
}

return cli.NewExitError(errorMessage, errorCode)
}
42 changes: 42 additions & 0 deletions cli/command/deployment_backup_cleanup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package command

import (
"github.com/cloudfoundry-incubator/bosh-backup-and-restore/factory"
"github.com/urfave/cli"
)

type DeploymentBackupCleanupCommand struct {
}

func NewDeploymentBackupCleanupCommand() DeploymentBackupCleanupCommand {
return DeploymentBackupCleanupCommand{}
}

func (d DeploymentBackupCleanupCommand) Cli() cli.Command {
return cli.Command{
Name: "backup-cleanup",
Usage: "Cleanup a deployment after a backup was interrupted",
Action: d.Action,
}
}

func (d DeploymentBackupCleanupCommand) Action(c *cli.Context) error {
trapSigint(true)

cleaner, err := factory.BuildDeploymentBackupCleanuper(
c.Parent().String("target"),
c.Parent().String("username"),
c.Parent().String("password"),
c.Parent().String("ca-cert"),
c.Bool("with-manifest"),
c.GlobalBool("debug"),
)
if err != nil {
return redCliError(err)
}

deployment := c.Parent().String("deployment")
cleanupErr := cleaner.Cleanup(deployment)

return processError(cleanupErr)
}
52 changes: 52 additions & 0 deletions cli/command/deployment_pre_backup_check.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package command

import (
"fmt"

"github.com/cloudfoundry-incubator/bosh-backup-and-restore/factory"
"github.com/mgutz/ansi"
"github.com/urfave/cli"
)

type DeploymentPreBackupCheck struct{}

func NewDeploymentPreBackupCheckCommand() DeploymentPreBackupCheck {
return DeploymentPreBackupCheck{}
}
func (d DeploymentPreBackupCheck) Cli() cli.Command {
return cli.Command{
Name: "pre-backup-check",
Aliases: []string{"c"},
Usage: "Check a deployment can be backed up",
Action: d.Action,
}
}
func (d DeploymentPreBackupCheck) Action(c *cli.Context) error {
var deployment = c.Parent().String("deployment")
backuper, err := factory.BuildDeploymentBackupChecker(
c.Parent().String("target"),
c.Parent().String("username"),
c.Parent().String("password"),
c.Parent().String("ca-cert"),
c.GlobalBool("debug"),
c.Bool("with-manifest"))

if err != nil {
return redCliError(err)
}

backupable, checkErr := backuper.CanBeBackedUp(deployment)

if backupable {
fmt.Printf("Deployment '%s' can be backed up.\n", deployment)
return cli.NewExitError("", 0)
} else {
fmt.Printf("Deployment '%s' cannot be backed up.\n", deployment)
writeStackTrace(checkErr.PrettyError(true))
return cli.NewExitError(checkErr.Error(), 1)
}
}

func redCliError(err error) *cli.ExitError {
return cli.NewExitError(ansi.Color(err.Error(), "red"), 1)
}
50 changes: 50 additions & 0 deletions cli/command/deployment_restore.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package command

import (
"github.com/cloudfoundry-incubator/bosh-backup-and-restore/cli/flags"
"github.com/cloudfoundry-incubator/bosh-backup-and-restore/factory"
"github.com/urfave/cli"
)

type DeploymentRestoreCommand struct {
}

func NewDeploymentRestoreCommand() DeploymentRestoreCommand {
return DeploymentRestoreCommand{}
}

func (d DeploymentRestoreCommand) Cli() cli.Command {
return cli.Command{
Name: "restore",
Aliases: []string{"r"},
Usage: "Restore a deployment from backup",
Action: d.Action,
Flags: []cli.Flag{cli.StringFlag{
Name: "artifact-path",
Usage: "Path to the artifact to restore",
}},
}
}

func (d DeploymentRestoreCommand) Action(c *cli.Context) error {
trapSigint(false)

if err := flags.Validate([]string{"artifact-path"}, c); err != nil {
return redCliError(err)
}

deployment := c.Parent().String("deployment")
artifactPath := c.String("artifact-path")

restorer, err := factory.BuildDeploymentRestorer(c.Parent().String("target"),
c.Parent().String("username"),
c.Parent().String("password"),
c.Parent().String("ca-cert"),
c.GlobalBool("debug"))
if err != nil {
return redCliError(err)
}

restoreErr := restorer.Restore(deployment, artifactPath)
return processError(restoreErr)
}
40 changes: 40 additions & 0 deletions cli/command/deployment_restore_cleanup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package command

import (
"github.com/cloudfoundry-incubator/bosh-backup-and-restore/factory"
"github.com/urfave/cli"
)

type DeploymentRestoreCleanupCommand struct {
}

func NewDeploymentRestoreCleanupCommand() DeploymentRestoreCleanupCommand {
return DeploymentRestoreCleanupCommand{}
}

func (d DeploymentRestoreCleanupCommand) Cli() cli.Command {
return cli.Command{
Name: "restore-cleanup",
Usage: "Cleanup a deployment after a restore was interrupted",
Action: d.Action,
}
}

func (d DeploymentRestoreCleanupCommand) Action(c *cli.Context) error {
trapSigint(true)

cleaner, err := factory.BuildDeploymentRestoreCleanuper(c.Parent().String("target"),
c.Parent().String("username"),
c.Parent().String("password"),
c.Parent().String("ca-cert"),
c.Bool("with-manifest"),
c.GlobalBool("debug"))
if err != nil {
return redCliError(err)
}

deployment := c.Parent().String("deployment")
cleanupErr := cleaner.Cleanup(deployment)

return processError(cleanupErr)
}
88 changes: 88 additions & 0 deletions cli/command/director_backup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package command

import (
"bufio"
"fmt"
"os"
"os/signal"
"strings"

"github.com/cloudfoundry-incubator/bosh-backup-and-restore/factory"
"github.com/cloudfoundry-incubator/bosh-backup-and-restore/orchestrator"
"github.com/pkg/errors"
"github.com/urfave/cli"
)

type DirectorBackupCommand struct {
}

func NewDirectorBackupCommand() DirectorBackupCommand {
return DirectorBackupCommand{}
}
func (checkCommand DirectorBackupCommand) Cli() cli.Command {
return cli.Command{
Name: "backup",
Aliases: []string{"b"},
Usage: "Backup a BOSH Director",
Action: checkCommand.Action,
}

}
func (checkCommand DirectorBackupCommand) Action(c *cli.Context) error {
trapSigint(true)

directorName := ExtractNameFromAddress(c.Parent().String("host"))

backuper := factory.BuildDirectorBackuper(
c.Parent().String("host"),
c.Parent().String("username"),
c.Parent().String("private-key-path"),
c.GlobalBool("debug"))

backupErr := backuper.Backup(directorName)

errorCode, errorMessage, errorWithStackTrace := orchestrator.ProcessError(backupErr)
if err := writeStackTrace(errorWithStackTrace); err != nil {
return errors.Wrap(backupErr, err.Error())
}

if backupErr.ContainsUnlockOrCleanup() {
errorMessage = errorMessage + "\n" + backupCleanupAdvisedNotice
}

return cli.NewExitError(errorMessage, errorCode)
}

func trapSigint(backup bool) {
sigintChan := make(chan os.Signal, 1)
signal.Notify(sigintChan, os.Interrupt)

var sigintQuestion, stdInErrorMessage, cleanupAdvisedNotice string
if backup {
sigintQuestion = backupSigintQuestion
stdInErrorMessage = backupStdinErrorMessage
cleanupAdvisedNotice = backupCleanupAdvisedNotice
} else {
sigintQuestion = restoreSigintQuestion
stdInErrorMessage = restoreStdinErrorMessage
cleanupAdvisedNotice = restoreCleanupAdvisedNotice
}

go func() {
for range sigintChan {
stdinReader := bufio.NewReader(os.Stdin)
factory.ApplicationLoggerStdout.Pause()
factory.ApplicationLoggerStderr.Pause()
fmt.Fprintln(os.Stdout, "\n"+sigintQuestion)
input, err := stdinReader.ReadString('\n')
if err != nil {
fmt.Println("\n" + stdInErrorMessage)
} else if strings.ToLower(strings.TrimSpace(input)) == "yes" {
fmt.Println(cleanupAdvisedNotice)
os.Exit(1)
}
factory.ApplicationLoggerStdout.Resume()
factory.ApplicationLoggerStderr.Resume()
}
}()
}
36 changes: 36 additions & 0 deletions cli/command/director_backup_cleanup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package command

import (
"github.com/cloudfoundry-incubator/bosh-backup-and-restore/factory"
"github.com/urfave/cli"
)

type DirectorBackupCleanupCommand struct {
}

func NewDirectorBackupCleanupCommand() DirectorBackupCleanupCommand {
return DirectorBackupCleanupCommand{}
}
func (d DirectorBackupCleanupCommand) Cli() cli.Command {
return cli.Command{
Name: "backup-cleanup",
Usage: "Cleanup a director after a backup was interrupted",
Action: d.Action,
}
}

func (d DirectorBackupCleanupCommand) Action(c *cli.Context) error {
trapSigint(true)

directorName := ExtractNameFromAddress(c.Parent().String("host"))

cleaner := factory.BuildDirectorBackupCleaner(c.Parent().String("host"),
c.Parent().String("username"),
c.Parent().String("private-key-path"),
c.GlobalBool("debug"),
)

cleanupErr := cleaner.Cleanup(directorName)

return processError(cleanupErr)
}
Loading

0 comments on commit cd43158

Please sign in to comment.