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  }