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