github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/worker/uniter/runner/context/unitStorage_test.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package context_test
     5  
     6  import (
     7  	jc "github.com/juju/testing/checkers"
     8  	"github.com/juju/utils"
     9  	"github.com/juju/utils/set"
    10  	gc "gopkg.in/check.v1"
    11  	"gopkg.in/juju/names.v2"
    12  
    13  	"github.com/juju/juju/apiserver/params"
    14  	"github.com/juju/juju/provider/dummy"
    15  	"github.com/juju/juju/state"
    16  	"github.com/juju/juju/storage/poolmanager"
    17  	"github.com/juju/juju/storage/provider"
    18  	"github.com/juju/juju/worker/uniter/runner/context"
    19  )
    20  
    21  type unitStorageSuite struct {
    22  	HookContextSuite
    23  	expectedStorageNames         set.Strings
    24  	charmName                    string
    25  	initCons                     map[string]state.StorageConstraints
    26  	ch                           *state.Charm
    27  	initialStorageInstancesCount int
    28  }
    29  
    30  var _ = gc.Suite(&unitStorageSuite{})
    31  
    32  const (
    33  	testPool           = "block"
    34  	testPersistentPool = "block-persistent"
    35  )
    36  
    37  func (s *unitStorageSuite) SetUpTest(c *gc.C) {
    38  	s.HookContextSuite.SetUpTest(c)
    39  	setupTestStorageSupport(c, s.State)
    40  }
    41  
    42  func (s *unitStorageSuite) TestAddUnitStorage(c *gc.C) {
    43  	s.createStorageBlockUnit(c)
    44  	count := uint64(1)
    45  	s.assertUnitStorageAdded(c,
    46  		map[string]params.StorageConstraints{
    47  			"allecto": params.StorageConstraints{Count: &count}})
    48  }
    49  
    50  func (s *unitStorageSuite) TestAddUnitStorageIgnoresBlocks(c *gc.C) {
    51  	s.createStorageBlockUnit(c)
    52  	count := uint64(1)
    53  	s.BlockDestroyModel(c, "TestAddUnitStorageIgnoresBlocks")
    54  	s.BlockRemoveObject(c, "TestAddUnitStorageIgnoresBlocks")
    55  	s.BlockAllChanges(c, "TestAddUnitStorageIgnoresBlocks")
    56  	s.assertUnitStorageAdded(c,
    57  		map[string]params.StorageConstraints{
    58  			"allecto": params.StorageConstraints{Count: &count}})
    59  }
    60  
    61  func (s *unitStorageSuite) TestAddUnitStorageZeroCount(c *gc.C) {
    62  	s.createStorageBlockUnit(c)
    63  	cons := map[string]params.StorageConstraints{
    64  		"allecto": params.StorageConstraints{}}
    65  
    66  	ctx := s.addUnitStorage(c, cons)
    67  
    68  	// Flush the context with a success.
    69  	err := ctx.Flush("success", nil)
    70  	c.Assert(err, gc.ErrorMatches, `.*count must be specified.*`)
    71  
    72  	// Make sure no storage instances was added
    73  	after, err := s.State.AllStorageInstances()
    74  	c.Assert(err, jc.ErrorIsNil)
    75  	c.Assert(len(after)-s.initialStorageInstancesCount, gc.Equals, 0)
    76  	s.assertExistingStorage(c, after)
    77  }
    78  
    79  func (s *unitStorageSuite) TestAddUnitStorageWithSize(c *gc.C) {
    80  	s.createStorageBlockUnit(c)
    81  	size := uint64(1)
    82  	cons := map[string]params.StorageConstraints{
    83  		"allecto": params.StorageConstraints{Size: &size}}
    84  
    85  	ctx := s.addUnitStorage(c, cons)
    86  
    87  	// Flush the context with a success.
    88  	err := ctx.Flush("success", nil)
    89  	c.Assert(err, gc.ErrorMatches, `.*only count can be specified.*`)
    90  
    91  	// Make sure no storage instances was added
    92  	after, err := s.State.AllStorageInstances()
    93  	c.Assert(err, jc.ErrorIsNil)
    94  	c.Assert(len(after)-s.initialStorageInstancesCount, gc.Equals, 0)
    95  	s.assertExistingStorage(c, after)
    96  }
    97  
    98  func (s *unitStorageSuite) TestAddUnitStorageWithPool(c *gc.C) {
    99  	s.createStorageBlockUnit(c)
   100  	cons := map[string]params.StorageConstraints{
   101  		"allecto": params.StorageConstraints{Pool: "loop"}}
   102  
   103  	ctx := s.addUnitStorage(c, cons)
   104  
   105  	// Flush the context with a success.
   106  	err := ctx.Flush("success", nil)
   107  	c.Assert(err, gc.ErrorMatches, `.*only count can be specified.*`)
   108  
   109  	// Make sure no storage instances was added
   110  	after, err := s.State.AllStorageInstances()
   111  	c.Assert(err, jc.ErrorIsNil)
   112  	c.Assert(len(after)-s.initialStorageInstancesCount, gc.Equals, 0)
   113  	s.assertExistingStorage(c, after)
   114  }
   115  
   116  func (s *unitStorageSuite) TestAddUnitStorageAccumulated(c *gc.C) {
   117  	s.createStorageBlock2Unit(c)
   118  	count := uint64(1)
   119  	s.assertUnitStorageAdded(c,
   120  		map[string]params.StorageConstraints{
   121  			"multi2up": params.StorageConstraints{Count: &count}},
   122  		map[string]params.StorageConstraints{
   123  			"multi1to10": params.StorageConstraints{Count: &count}})
   124  }
   125  
   126  func (s *unitStorageSuite) TestAddUnitStorageAccumulatedSame(c *gc.C) {
   127  	s.createStorageBlock2Unit(c)
   128  	count := uint64(1)
   129  	s.assertUnitStorageAdded(c,
   130  		map[string]params.StorageConstraints{
   131  			"multi2up": params.StorageConstraints{Count: &count}},
   132  		map[string]params.StorageConstraints{
   133  			"multi2up": params.StorageConstraints{Count: &count}})
   134  }
   135  
   136  func setupTestStorageSupport(c *gc.C, s *state.State) {
   137  	stsetts := state.NewStateSettings(s)
   138  	poolManager := poolmanager.New(stsetts, dummy.StorageProviders())
   139  	_, err := poolManager.Create(testPool, provider.LoopProviderType, map[string]interface{}{"it": "works"})
   140  	c.Assert(err, jc.ErrorIsNil)
   141  	_, err = poolManager.Create(testPersistentPool, "environscoped", map[string]interface{}{"persistent": true})
   142  	c.Assert(err, jc.ErrorIsNil)
   143  }
   144  
   145  func (s *unitStorageSuite) createStorageEnabledUnit(c *gc.C) {
   146  	s.ch = s.AddTestingCharm(c, s.charmName)
   147  	s.service = s.AddTestingServiceWithStorage(c, s.charmName, s.ch, s.initCons)
   148  	s.unit = s.AddUnit(c, s.service)
   149  
   150  	s.assertStorageCreated(c)
   151  	s.createHookSupport(c)
   152  }
   153  
   154  func (s *unitStorageSuite) createStorageBlockUnit(c *gc.C) {
   155  	s.charmName = "storage-block"
   156  	s.initCons = map[string]state.StorageConstraints{
   157  		"data": makeStorageCons("block", 1024, 1),
   158  	}
   159  	s.createStorageEnabledUnit(c)
   160  	s.assertStorageCreated(c)
   161  	s.createHookSupport(c)
   162  }
   163  
   164  func (s *unitStorageSuite) createStorageBlock2Unit(c *gc.C) {
   165  	s.charmName = "storage-block2"
   166  	s.initCons = map[string]state.StorageConstraints{
   167  		"multi1to10": makeStorageCons("loop", 0, 3),
   168  	}
   169  	s.createStorageEnabledUnit(c)
   170  	s.assertStorageCreated(c)
   171  	s.createHookSupport(c)
   172  }
   173  
   174  func (s *unitStorageSuite) assertStorageCreated(c *gc.C) {
   175  	all, err := s.State.AllStorageInstances()
   176  	c.Assert(err, jc.ErrorIsNil)
   177  	s.initialStorageInstancesCount = len(all)
   178  	s.expectedStorageNames = set.NewStrings()
   179  	for _, one := range all {
   180  		s.expectedStorageNames.Add(one.StorageName())
   181  	}
   182  }
   183  
   184  func (s *unitStorageSuite) createHookSupport(c *gc.C) {
   185  	password, err := utils.RandomPassword()
   186  	err = s.unit.SetPassword(password)
   187  	c.Assert(err, jc.ErrorIsNil)
   188  	s.st = s.OpenAPIAs(c, s.unit.Tag(), password)
   189  	s.uniter, err = s.st.Uniter()
   190  	c.Assert(err, jc.ErrorIsNil)
   191  	c.Assert(s.uniter, gc.NotNil)
   192  	s.apiUnit, err = s.uniter.Unit(s.unit.Tag().(names.UnitTag))
   193  	c.Assert(err, jc.ErrorIsNil)
   194  
   195  	err = s.unit.SetCharmURL(s.ch.URL())
   196  	c.Assert(err, jc.ErrorIsNil)
   197  }
   198  
   199  func makeStorageCons(pool string, size, count uint64) state.StorageConstraints {
   200  	return state.StorageConstraints{Pool: pool, Size: size, Count: count}
   201  }
   202  
   203  func (s *unitStorageSuite) addUnitStorage(c *gc.C, cons ...map[string]params.StorageConstraints) *context.HookContext {
   204  	// Get the context.
   205  	ctx := s.getHookContext(c, s.State.ModelUUID(), -1, "", noProxies)
   206  	c.Assert(ctx.UnitName(), gc.Equals, s.unit.Name())
   207  
   208  	for _, one := range cons {
   209  		for storage, _ := range one {
   210  			s.expectedStorageNames.Add(storage)
   211  		}
   212  		ctx.AddUnitStorage(one)
   213  	}
   214  	return ctx
   215  }
   216  
   217  func (s *unitStorageSuite) assertUnitStorageAdded(c *gc.C, cons ...map[string]params.StorageConstraints) {
   218  	ctx := s.addUnitStorage(c, cons...)
   219  
   220  	// Flush the context with a success.
   221  	err := ctx.Flush("success", nil)
   222  	c.Assert(err, jc.ErrorIsNil)
   223  
   224  	after, err := s.State.AllStorageInstances()
   225  	c.Assert(err, jc.ErrorIsNil)
   226  	c.Assert(len(after)-s.initialStorageInstancesCount, gc.Equals, len(cons))
   227  	s.assertExistingStorage(c, after)
   228  }
   229  
   230  func (s *unitStorageSuite) assertExistingStorage(c *gc.C, all []state.StorageInstance) {
   231  	for _, one := range all {
   232  		c.Assert(s.expectedStorageNames.Contains(one.StorageName()), jc.IsTrue)
   233  	}
   234  }