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