github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/facades/client/controller/destroy.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package controller 5 6 import ( 7 "github.com/juju/errors" 8 9 "github.com/juju/juju/apiserver/common" 10 "github.com/juju/juju/apiserver/facade" 11 "github.com/juju/juju/apiserver/params" 12 "github.com/juju/juju/permission" 13 "github.com/juju/juju/state" 14 ) 15 16 // DestroyController destroys the controller. 17 // 18 // The v3 implementation of DestroyController ignores the DestroyStorage 19 // field of the arguments, and unconditionally destroys all storage in 20 // the controller. 21 // 22 // See ControllerAPIv4.DestroyController for more details. 23 func (c *ControllerAPIv3) DestroyController(args params.DestroyControllerArgs) error { 24 if args.DestroyStorage != nil { 25 return errors.New("destroy-storage unexpected on the v3 API") 26 } 27 destroyStorage := true 28 args.DestroyStorage = &destroyStorage 29 return destroyController(c.state, c.statePool, c.authorizer, args) 30 } 31 32 // DestroyController destroys the controller. 33 // 34 // If the args specify the destruction of the models, this method will 35 // attempt to do so. Otherwise, if the controller has any non-empty, 36 // non-Dead hosted models, then an error with the code 37 // params.CodeHasHostedModels will be transmitted. 38 func (c *ControllerAPI) DestroyController(args params.DestroyControllerArgs) error { 39 return destroyController(c.state, c.statePool, c.authorizer, args) 40 } 41 42 func destroyController( 43 st *state.State, 44 pool *state.StatePool, 45 authorizer facade.Authorizer, 46 args params.DestroyControllerArgs, 47 ) error { 48 hasPermission, err := authorizer.HasPermission(permission.SuperuserAccess, st.ControllerTag()) 49 if err != nil { 50 return errors.Trace(err) 51 } 52 if !hasPermission { 53 return errors.Trace(common.ErrPerm) 54 } 55 if err := ensureNotBlocked(st); err != nil { 56 return errors.Trace(err) 57 } 58 59 model, err := st.Model() 60 if err != nil { 61 return errors.Trace(err) 62 } 63 64 // If we are destroying models, we need to tolerate living 65 // models but set the controller to dying to prevent new 66 // models sneaking in. If we are not destroying hosted models, 67 // this will fail if any hosted models are found. 68 backend := common.NewModelManagerBackend(model, pool) 69 return errors.Trace(common.DestroyController( 70 backend, args.DestroyModels, args.DestroyStorage, 71 )) 72 } 73 74 func ensureNotBlocked(st *state.State) error { 75 // If there are blocks let the user know. 76 blocks, err := st.AllBlocksForController() 77 if err != nil { 78 logger.Debugf("Unable to get blocks for controller: %s", err) 79 return errors.Trace(err) 80 } 81 if len(blocks) > 0 { 82 return common.OperationBlockedError("found blocks in controller models") 83 } 84 return nil 85 }