github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/cmd/juju/environment/destroy.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for infos.
     3  
     4  package environment
     5  
     6  import (
     7  	"fmt"
     8  
     9  	"github.com/juju/cmd"
    10  	"github.com/juju/errors"
    11  	"launchpad.net/gnuflag"
    12  
    13  	"github.com/juju/juju/apiserver/params"
    14  	jujucmd "github.com/juju/juju/cmd"
    15  	"github.com/juju/juju/cmd/envcmd"
    16  	"github.com/juju/juju/cmd/juju/block"
    17  	"github.com/juju/juju/environs"
    18  	"github.com/juju/juju/environs/configstore"
    19  )
    20  
    21  // DestroyCommand destroys the specified environment.
    22  type DestroyCommand struct {
    23  	envcmd.EnvCommandBase
    24  	envName   string
    25  	assumeYes bool
    26  	api       DestroyEnvironmentAPI
    27  }
    28  
    29  var destroyDoc = `Destroys the specified environment`
    30  var destroyEnvMsg = `
    31  WARNING! This command will destroy the %q environment.
    32  This includes all machines, services, data and other resources.
    33  
    34  Continue [y/N]? `[1:]
    35  
    36  // DestroyEnvironmentAPI defines the methods on the environmentmanager
    37  // API that the destroy command calls. It is exported for mocking in tests.
    38  type DestroyEnvironmentAPI interface {
    39  	Close() error
    40  	DestroyEnvironment() error
    41  }
    42  
    43  // Info implements Command.Info.
    44  func (c *DestroyCommand) Info() *cmd.Info {
    45  	return &cmd.Info{
    46  		Name:    "destroy",
    47  		Args:    "<environment name>",
    48  		Purpose: "terminate all machines and other associated resources for a non-system environment",
    49  		Doc:     destroyDoc,
    50  	}
    51  }
    52  
    53  // SetFlags implements Command.SetFlags.
    54  func (c *DestroyCommand) SetFlags(f *gnuflag.FlagSet) {
    55  	f.BoolVar(&c.assumeYes, "y", false, "Do not ask for confirmation")
    56  	f.BoolVar(&c.assumeYes, "yes", false, "")
    57  }
    58  
    59  // Init implements Command.Init.
    60  func (c *DestroyCommand) Init(args []string) error {
    61  	switch len(args) {
    62  	case 0:
    63  		return errors.New("no environment specified")
    64  	case 1:
    65  		c.envName = args[0]
    66  		c.SetEnvName(c.envName)
    67  		return nil
    68  	default:
    69  		return cmd.CheckEmpty(args[1:])
    70  	}
    71  }
    72  
    73  func (c *DestroyCommand) getAPI() (DestroyEnvironmentAPI, error) {
    74  	if c.api != nil {
    75  		return c.api, nil
    76  	}
    77  	return c.NewAPIClient()
    78  }
    79  
    80  // Run implements Command.Run
    81  func (c *DestroyCommand) Run(ctx *cmd.Context) error {
    82  	store, err := configstore.Default()
    83  	if err != nil {
    84  		return errors.Annotate(err, "cannot open environment info storage")
    85  	}
    86  
    87  	cfgInfo, err := store.ReadInfo(c.envName)
    88  	if err != nil {
    89  		return errors.Annotate(err, "cannot read environment info")
    90  	}
    91  
    92  	// Verify that we're not destroying a system
    93  	apiEndpoint := cfgInfo.APIEndpoint()
    94  	if apiEndpoint.ServerUUID != "" && apiEndpoint.EnvironUUID == apiEndpoint.ServerUUID {
    95  		return errors.Errorf("%q is a system; use 'juju system destroy' to destroy it", c.envName)
    96  	}
    97  
    98  	if !c.assumeYes {
    99  		fmt.Fprintf(ctx.Stdout, destroyEnvMsg, c.envName)
   100  
   101  		if err := jujucmd.UserConfirmYes(ctx); err != nil {
   102  			return errors.Annotate(err, "environment destruction")
   103  		}
   104  	}
   105  
   106  	// Attempt to connect to the API.  If we can't, fail the destroy.
   107  	api, err := c.getAPI()
   108  	if err != nil {
   109  		return errors.Annotate(err, "cannot connect to API")
   110  	}
   111  	defer api.Close()
   112  
   113  	// Attempt to destroy the environment.
   114  	err = api.DestroyEnvironment()
   115  	if err != nil {
   116  		return c.handleError(errors.Annotate(err, "cannot destroy environment"))
   117  	}
   118  
   119  	return environs.DestroyInfo(c.envName, store)
   120  }
   121  
   122  func (c *DestroyCommand) handleError(err error) error {
   123  	if err == nil {
   124  		return nil
   125  	}
   126  	if params.IsCodeOperationBlocked(err) {
   127  		return block.ProcessBlockedError(err, block.BlockDestroy)
   128  	}
   129  	logger.Errorf(`failed to destroy environment %q`, c.envName)
   130  	return err
   131  }