github.com/cloudbase/juju-core@v0.0.0-20140504232958-a7271ac7912f/cmd/juju/destroyenvironment.go (about)

     1  // Copyright 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package main
     5  
     6  import (
     7  	"bufio"
     8  	"errors"
     9  	"fmt"
    10  	"io"
    11  	"strings"
    12  
    13  	"launchpad.net/gnuflag"
    14  
    15  	"launchpad.net/juju-core/cmd"
    16  	"launchpad.net/juju-core/environs"
    17  	"launchpad.net/juju-core/environs/configstore"
    18  	"launchpad.net/juju-core/juju"
    19  	"launchpad.net/juju-core/state/api"
    20  	"launchpad.net/juju-core/state/api/params"
    21  )
    22  
    23  var NoEnvironmentError = errors.New("no environment specified")
    24  var DoubleEnvironmentError = errors.New("you cannot supply both -e and the envname as a positional argument")
    25  
    26  // DestroyEnvironmentCommand destroys an environment.
    27  type DestroyEnvironmentCommand struct {
    28  	cmd.CommandBase
    29  	envName   string
    30  	assumeYes bool
    31  	force     bool
    32  }
    33  
    34  func (c *DestroyEnvironmentCommand) Info() *cmd.Info {
    35  	return &cmd.Info{
    36  		Name:    "destroy-environment",
    37  		Args:    "<environment name>",
    38  		Purpose: "terminate all machines and other associated resources for an environment",
    39  	}
    40  }
    41  
    42  func (c *DestroyEnvironmentCommand) SetFlags(f *gnuflag.FlagSet) {
    43  	f.BoolVar(&c.assumeYes, "y", false, "Do not ask for confirmation")
    44  	f.BoolVar(&c.assumeYes, "yes", false, "")
    45  	f.BoolVar(&c.force, "force", false, "Forcefully destroy the environment, directly through the environment provider")
    46  	f.StringVar(&c.envName, "e", "", "juju environment to operate in")
    47  	f.StringVar(&c.envName, "environment", "", "juju environment to operate in")
    48  }
    49  
    50  func (c *DestroyEnvironmentCommand) Run(ctx *cmd.Context) (result error) {
    51  	store, err := configstore.Default()
    52  	if err != nil {
    53  		return fmt.Errorf("cannot open environment info storage: %v", err)
    54  	}
    55  	environ, err := environs.NewFromName(c.envName, store)
    56  	if err != nil {
    57  		return err
    58  	}
    59  	if !c.assumeYes {
    60  		fmt.Fprintf(ctx.Stdout, destroyEnvMsg, environ.Name(), environ.Config().Type())
    61  
    62  		scanner := bufio.NewScanner(ctx.Stdin)
    63  		scanner.Scan()
    64  		err := scanner.Err()
    65  		if err != nil && err != io.EOF {
    66  			return fmt.Errorf("Environment destruction aborted: %s", err)
    67  		}
    68  		answer := strings.ToLower(scanner.Text())
    69  		if answer != "y" && answer != "yes" {
    70  			return errors.New("Environment destruction aborted")
    71  		}
    72  	}
    73  	// If --force is supplied, then don't attempt to use the API.
    74  	// This is necessary to destroy broken environments, where the
    75  	// API server is inaccessible or faulty.
    76  	if !c.force {
    77  		defer func() {
    78  			if result == nil {
    79  				return
    80  			}
    81  			logger.Errorf(`failed to destroy environment %q
    82          
    83  If the environment is unusable, then you may run
    84  
    85      juju destroy-environment --force
    86  
    87  to forcefully destroy the environment. Upon doing so, review
    88  your environment provider console for any resources that need
    89  to be cleaned up.
    90  
    91  `, c.envName)
    92  		}()
    93  		conn, err := juju.NewAPIConn(environ, api.DefaultDialOpts())
    94  		if err != nil {
    95  			return err
    96  		}
    97  		defer conn.Close()
    98  		err = conn.State.Client().DestroyEnvironment()
    99  		if err != nil && !params.IsCodeNotImplemented(err) {
   100  			return fmt.Errorf("destroying environment: %v", err)
   101  		}
   102  	}
   103  	return environs.Destroy(environ, store)
   104  }
   105  
   106  func (c *DestroyEnvironmentCommand) Init(args []string) error {
   107  	if c.envName != "" {
   108  		logger.Warningf("-e/--environment flag is deprecated in 1.18, " +
   109  			"please supply environment as a positional parameter")
   110  		// They supplied the -e flag
   111  		if len(args) == 0 {
   112  			// We're happy, we have enough information
   113  			return nil
   114  		}
   115  		// You can't supply -e ENV and ENV as a positional argument
   116  		return DoubleEnvironmentError
   117  	} else {
   118  		// No -e flag means they must supply the environment positionally
   119  		switch len(args) {
   120  		case 0:
   121  			return NoEnvironmentError
   122  		case 1:
   123  			c.envName = args[0]
   124  			return nil
   125  		default:
   126  			return cmd.CheckEmpty(args[1:])
   127  		}
   128  	}
   129  }
   130  
   131  var destroyEnvMsg = `
   132  WARNING! this command will destroy the %q environment (type: %s)
   133  This includes all machines, services, data and other resources.
   134  
   135  Continue [y/N]? `[1:]