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:]