github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/facades/client/controller/destroy_test.go (about)

     1  // Copyright 2012-2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package controller_test
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	jc "github.com/juju/testing/checkers"
     9  	gc "gopkg.in/check.v1"
    10  	"gopkg.in/juju/names.v2"
    11  
    12  	"github.com/juju/juju/apiserver/common"
    13  	commontesting "github.com/juju/juju/apiserver/common/testing"
    14  	"github.com/juju/juju/apiserver/facade/facadetest"
    15  	"github.com/juju/juju/apiserver/facades/client/controller"
    16  	"github.com/juju/juju/apiserver/params"
    17  	apiservertesting "github.com/juju/juju/apiserver/testing"
    18  	jujutesting "github.com/juju/juju/juju/testing"
    19  	"github.com/juju/juju/state"
    20  	"github.com/juju/juju/testing"
    21  	"github.com/juju/juju/testing/factory"
    22  )
    23  
    24  // NOTE: the testing of the general model destruction code
    25  // is found in apiserver/common/modeldestroy_test.go.
    26  //
    27  // The tests here are around the validation and behaviour of
    28  // the flags passed in to the destroy controller call.
    29  
    30  type destroyControllerSuite struct {
    31  	jujutesting.JujuConnSuite
    32  	commontesting.BlockHelper
    33  
    34  	authorizer apiservertesting.FakeAuthorizer
    35  	resources  *common.Resources
    36  	controller *controller.ControllerAPI
    37  
    38  	otherState      *state.State
    39  	otherModel      *state.Model
    40  	otherModelOwner names.UserTag
    41  	otherModelUUID  string
    42  }
    43  
    44  var _ = gc.Suite(&destroyControllerSuite{})
    45  
    46  func (s *destroyControllerSuite) SetUpTest(c *gc.C) {
    47  	s.JujuConnSuite.SetUpTest(c)
    48  
    49  	s.BlockHelper = commontesting.NewBlockHelper(s.APIState)
    50  	s.AddCleanup(func(*gc.C) { s.BlockHelper.Close() })
    51  
    52  	s.resources = common.NewResources()
    53  	s.AddCleanup(func(_ *gc.C) { s.resources.StopAll() })
    54  
    55  	s.authorizer = apiservertesting.FakeAuthorizer{
    56  		Tag: s.AdminUserTag(c),
    57  	}
    58  	controller, err := controller.NewControllerAPIv7(
    59  		facadetest.Context{
    60  			State_:     s.State,
    61  			StatePool_: s.StatePool,
    62  			Resources_: s.resources,
    63  			Auth_:      s.authorizer,
    64  		})
    65  	c.Assert(err, jc.ErrorIsNil)
    66  	s.controller = controller
    67  
    68  	s.otherModelOwner = names.NewUserTag("jess@dummy")
    69  	s.otherState = s.Factory.MakeModel(c, &factory.ModelParams{
    70  		Name:  "dummytoo",
    71  		Owner: s.otherModelOwner,
    72  		ConfigAttrs: testing.Attrs{
    73  			"controller": false,
    74  		},
    75  	})
    76  	s.AddCleanup(func(c *gc.C) { s.otherState.Close() })
    77  	s.otherModelUUID = s.otherState.ModelUUID()
    78  
    79  	s.otherModel, err = s.otherState.Model()
    80  	c.Assert(err, jc.ErrorIsNil)
    81  }
    82  
    83  func (s *destroyControllerSuite) TestDestroyControllerKillErrsOnHostedModelsWithBlocks(c *gc.C) {
    84  	s.BlockDestroyModel(c, "TestBlockDestroyModel")
    85  	s.BlockRemoveObject(c, "TestBlockRemoveObject")
    86  	s.otherState.SwitchBlockOn(state.DestroyBlock, "TestBlockDestroyModel")
    87  	s.otherState.SwitchBlockOn(state.ChangeBlock, "TestChangeBlock")
    88  
    89  	err := s.controller.DestroyController(params.DestroyControllerArgs{
    90  		DestroyModels: true,
    91  	})
    92  	c.Assert(err, gc.ErrorMatches, "found blocks in controller models")
    93  
    94  	model, err := s.State.Model()
    95  	c.Assert(err, jc.ErrorIsNil)
    96  	c.Assert(model.Life(), gc.Equals, state.Alive)
    97  }
    98  
    99  func (s *destroyControllerSuite) TestDestroyControllerReturnsBlockedModelErr(c *gc.C) {
   100  	s.BlockDestroyModel(c, "TestBlockDestroyModel")
   101  	s.BlockRemoveObject(c, "TestBlockRemoveObject")
   102  	s.otherState.SwitchBlockOn(state.DestroyBlock, "TestBlockDestroyModel")
   103  	s.otherState.SwitchBlockOn(state.ChangeBlock, "TestChangeBlock")
   104  
   105  	err := s.controller.DestroyController(params.DestroyControllerArgs{
   106  		DestroyModels: true,
   107  	})
   108  	c.Assert(params.IsCodeOperationBlocked(err), jc.IsTrue)
   109  
   110  	numBlocks, err := s.State.AllBlocksForController()
   111  	c.Assert(err, jc.ErrorIsNil)
   112  	c.Assert(len(numBlocks), gc.Equals, 4)
   113  
   114  	_, err = s.otherState.Model()
   115  	c.Assert(err, jc.ErrorIsNil)
   116  }
   117  
   118  func (s *destroyControllerSuite) TestDestroyControllerKillsHostedModels(c *gc.C) {
   119  	err := s.controller.DestroyController(params.DestroyControllerArgs{
   120  		DestroyModels: true,
   121  	})
   122  	c.Assert(err, jc.ErrorIsNil)
   123  
   124  	model, err := s.State.Model()
   125  	c.Assert(err, jc.ErrorIsNil)
   126  	c.Assert(model.Life(), gc.Equals, state.Dying)
   127  }
   128  
   129  func (s *destroyControllerSuite) TestDestroyControllerLeavesBlocksIfNotKillAll(c *gc.C) {
   130  	s.BlockDestroyModel(c, "TestBlockDestroyModel")
   131  	s.BlockRemoveObject(c, "TestBlockRemoveObject")
   132  	s.otherState.SwitchBlockOn(state.DestroyBlock, "TestBlockDestroyModel")
   133  	s.otherState.SwitchBlockOn(state.ChangeBlock, "TestChangeBlock")
   134  
   135  	err := s.controller.DestroyController(params.DestroyControllerArgs{})
   136  	c.Assert(err, gc.ErrorMatches, "found blocks in controller models")
   137  
   138  	numBlocks, err := s.State.AllBlocksForController()
   139  	c.Assert(err, jc.ErrorIsNil)
   140  	c.Assert(len(numBlocks), gc.Equals, 4)
   141  }
   142  
   143  func (s *destroyControllerSuite) TestDestroyControllerNoHostedModels(c *gc.C) {
   144  	err := common.DestroyModel(common.NewModelManagerBackend(s.otherModel, s.StatePool), nil)
   145  	c.Assert(err, jc.ErrorIsNil)
   146  	c.Assert(s.otherModel.Refresh(), jc.ErrorIsNil)
   147  	c.Assert(s.otherModel.Life(), gc.Equals, state.Dying)
   148  	c.Assert(s.otherModel.State().RemoveDyingModel(), jc.ErrorIsNil)
   149  	c.Assert(s.otherModel.Refresh(), jc.Satisfies, errors.IsNotFound)
   150  
   151  	err = s.controller.DestroyController(params.DestroyControllerArgs{})
   152  	c.Assert(err, jc.ErrorIsNil)
   153  
   154  	model, err := s.State.Model()
   155  	c.Assert(err, jc.ErrorIsNil)
   156  	c.Assert(model.Life(), gc.Equals, state.Dying)
   157  }
   158  
   159  func (s *destroyControllerSuite) TestDestroyControllerErrsOnNoHostedModelsWithBlock(c *gc.C) {
   160  	err := common.DestroyModel(common.NewModelManagerBackend(s.otherModel, s.StatePool), nil)
   161  	c.Assert(err, jc.ErrorIsNil)
   162  
   163  	s.BlockDestroyModel(c, "TestBlockDestroyModel")
   164  	s.BlockRemoveObject(c, "TestBlockRemoveObject")
   165  
   166  	err = s.controller.DestroyController(params.DestroyControllerArgs{})
   167  	c.Assert(err, gc.ErrorMatches, "found blocks in controller models")
   168  	models, err := s.State.Model()
   169  	c.Assert(err, jc.ErrorIsNil)
   170  	c.Assert(models.Life(), gc.Equals, state.Alive)
   171  }
   172  
   173  func (s *destroyControllerSuite) TestDestroyControllerNoHostedModelsWithBlockFail(c *gc.C) {
   174  	err := common.DestroyModel(common.NewModelManagerBackend(s.otherModel, s.StatePool), nil)
   175  	c.Assert(err, jc.ErrorIsNil)
   176  
   177  	s.BlockDestroyModel(c, "TestBlockDestroyModel")
   178  	s.BlockRemoveObject(c, "TestBlockRemoveObject")
   179  
   180  	err = s.controller.DestroyController(params.DestroyControllerArgs{})
   181  	c.Assert(params.IsCodeOperationBlocked(err), jc.IsTrue)
   182  
   183  	numBlocks, err := s.State.AllBlocksForController()
   184  	c.Assert(err, jc.ErrorIsNil)
   185  	c.Assert(len(numBlocks), gc.Equals, 2)
   186  }
   187  
   188  func (s *destroyControllerSuite) TestDestroyControllerDestroyStorageNotSpecified(c *gc.C) {
   189  	f := factory.NewFactory(s.otherState, s.StatePool)
   190  	f.MakeUnit(c, &factory.UnitParams{
   191  		Application: f.MakeApplication(c, &factory.ApplicationParams{
   192  			Charm: f.MakeCharm(c, &factory.CharmParams{
   193  				Name: "storage-block",
   194  			}),
   195  			Storage: map[string]state.StorageConstraints{
   196  				"data": {Pool: "modelscoped"},
   197  			},
   198  		}),
   199  	})
   200  
   201  	err := s.controller.DestroyController(params.DestroyControllerArgs{
   202  		DestroyModels: true,
   203  	})
   204  	c.Assert(err, jc.Satisfies, state.IsHasPersistentStorageError)
   205  
   206  	model, err := s.State.Model()
   207  	c.Assert(err, jc.ErrorIsNil)
   208  	c.Assert(model.Life(), gc.Equals, state.Alive)
   209  }
   210  
   211  func (s *destroyControllerSuite) TestDestroyControllerDestroyStorageSpecified(c *gc.C) {
   212  	f := factory.NewFactory(s.otherState, s.StatePool)
   213  	f.MakeUnit(c, &factory.UnitParams{
   214  		Application: f.MakeApplication(c, &factory.ApplicationParams{
   215  			Charm: f.MakeCharm(c, &factory.CharmParams{
   216  				Name: "storage-block",
   217  			}),
   218  			Storage: map[string]state.StorageConstraints{
   219  				"data": {Pool: "modelscoped"},
   220  			},
   221  		}),
   222  	})
   223  
   224  	destroyStorage := false
   225  	err := s.controller.DestroyController(params.DestroyControllerArgs{
   226  		DestroyModels:  true,
   227  		DestroyStorage: &destroyStorage,
   228  	})
   229  	c.Assert(err, jc.ErrorIsNil)
   230  
   231  	model, err := s.State.Model()
   232  	c.Assert(err, jc.ErrorIsNil)
   233  	c.Assert(model.Life(), gc.Equals, state.Dying)
   234  }
   235  
   236  func (s *destroyControllerSuite) TestDestroyControllerDestroyStorageNotSpecifiedV3(c *gc.C) {
   237  	controller, err := controller.NewControllerAPIv3(facadetest.Context{
   238  		State_:     s.State,
   239  		StatePool_: s.StatePool,
   240  		Resources_: s.resources,
   241  		Auth_:      s.authorizer,
   242  	})
   243  	c.Assert(err, jc.ErrorIsNil)
   244  
   245  	f := factory.NewFactory(s.otherState, s.StatePool)
   246  	f.MakeUnit(c, &factory.UnitParams{
   247  		Application: f.MakeApplication(c, &factory.ApplicationParams{
   248  			Charm: f.MakeCharm(c, &factory.CharmParams{
   249  				Name: "storage-block",
   250  			}),
   251  			Storage: map[string]state.StorageConstraints{
   252  				"data": {Pool: "modelscoped"},
   253  			},
   254  		}),
   255  	})
   256  
   257  	err = controller.DestroyController(params.DestroyControllerArgs{
   258  		DestroyModels: true,
   259  	})
   260  	c.Assert(err, jc.ErrorIsNil)
   261  
   262  	model, err := s.State.Model()
   263  	c.Assert(err, jc.ErrorIsNil)
   264  	c.Assert(model.Life(), gc.Equals, state.Dying)
   265  }
   266  
   267  func (s *destroyControllerSuite) TestDestroyControllerDestroyStorageSpecifiedV3(c *gc.C) {
   268  	controller, err := controller.NewControllerAPIv3(facadetest.Context{
   269  		State_:     s.State,
   270  		StatePool_: s.StatePool,
   271  		Resources_: s.resources,
   272  		Auth_:      s.authorizer,
   273  	})
   274  	c.Assert(err, jc.ErrorIsNil)
   275  
   276  	destroyStorage := true
   277  	err = controller.DestroyController(params.DestroyControllerArgs{
   278  		DestroyModels:  true,
   279  		DestroyStorage: &destroyStorage,
   280  	})
   281  	c.Assert(err, gc.ErrorMatches, "destroy-storage unexpected on the v3 API")
   282  }