github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/apiserver/storage/package_test.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package storage_test
     5  
     6  import (
     7  	stdtesting "testing"
     8  
     9  	"github.com/juju/errors"
    10  	"github.com/juju/names"
    11  	jc "github.com/juju/testing/checkers"
    12  	gc "gopkg.in/check.v1"
    13  	"gopkg.in/juju/charm.v5"
    14  
    15  	"github.com/juju/juju/apiserver/common"
    16  	"github.com/juju/juju/apiserver/params"
    17  	"github.com/juju/juju/apiserver/storage"
    18  	"github.com/juju/juju/apiserver/testing"
    19  	"github.com/juju/juju/state"
    20  	jujustorage "github.com/juju/juju/storage"
    21  	coretesting "github.com/juju/juju/testing"
    22  )
    23  
    24  func TestAll(t *stdtesting.T) {
    25  	gc.TestingT(t)
    26  }
    27  
    28  type baseStorageSuite struct {
    29  	coretesting.BaseSuite
    30  
    31  	resources  *common.Resources
    32  	authorizer testing.FakeAuthorizer
    33  
    34  	api   *storage.API
    35  	state *mockState
    36  
    37  	storageTag      names.StorageTag
    38  	storageInstance *mockStorageInstance
    39  	unitTag         names.UnitTag
    40  	machineTag      names.MachineTag
    41  
    42  	volumeTag        names.VolumeTag
    43  	volume           state.Volume
    44  	volumeAttachment state.VolumeAttachment
    45  	calls            []string
    46  
    47  	poolManager *mockPoolManager
    48  	pools       map[string]*jujustorage.Config
    49  
    50  	blocks map[state.BlockType]state.Block
    51  }
    52  
    53  func (s *baseStorageSuite) SetUpTest(c *gc.C) {
    54  	s.BaseSuite.SetUpTest(c)
    55  	s.resources = common.NewResources()
    56  	s.authorizer = testing.FakeAuthorizer{names.NewUserTag("testuser"), true}
    57  	s.calls = []string{}
    58  	s.state = s.constructState(c)
    59  
    60  	s.pools = make(map[string]*jujustorage.Config)
    61  	s.poolManager = s.constructPoolManager(c)
    62  
    63  	var err error
    64  	s.api, err = storage.CreateAPI(s.state, s.poolManager, s.resources, s.authorizer)
    65  	c.Assert(err, jc.ErrorIsNil)
    66  }
    67  
    68  func (s *baseStorageSuite) assertCalls(c *gc.C, expectedCalls []string) {
    69  	c.Assert(s.calls, jc.SameContents, expectedCalls)
    70  }
    71  
    72  const (
    73  	allStorageInstancesCall                 = "allStorageInstances"
    74  	storageInstanceAttachmentsCall          = "storageInstanceAttachments"
    75  	unitAssignedMachineCall                 = "UnitAssignedMachine"
    76  	storageInstanceCall                     = "StorageInstance"
    77  	storageInstanceFilesystemCall           = "StorageInstanceFilesystem"
    78  	storageInstanceFilesystemAttachmentCall = "storageInstanceFilesystemAttachment"
    79  	storageInstanceVolumeCall               = "storageInstanceVolume"
    80  	volumeCall                              = "volumeCall"
    81  	machineVolumeAttachmentsCall            = "machineVolumeAttachments"
    82  	volumeAttachmentsCall                   = "volumeAttachments"
    83  	allVolumesCall                          = "allVolumes"
    84  	addStorageForUnitCall                   = "addStorageForUnit"
    85  	getBlockForTypeCall                     = "getBlockForType"
    86  )
    87  
    88  func (s *baseStorageSuite) constructState(c *gc.C) *mockState {
    89  	s.unitTag = names.NewUnitTag("mysql/0")
    90  	s.storageTag = names.NewStorageTag("data/0")
    91  
    92  	s.storageInstance = &mockStorageInstance{
    93  		kind:       state.StorageKindFilesystem,
    94  		owner:      s.unitTag,
    95  		storageTag: s.storageTag,
    96  	}
    97  
    98  	storageInstanceAttachment := &mockStorageAttachment{storage: s.storageInstance}
    99  
   100  	s.machineTag = names.NewMachineTag("66")
   101  	filesystemTag := names.NewFilesystemTag("104")
   102  	s.volumeTag = names.NewVolumeTag("22")
   103  	filesystem := &mockFilesystem{tag: filesystemTag}
   104  	filesystemAttachment := &mockFilesystemAttachment{}
   105  	s.volume = &mockVolume{tag: s.volumeTag, storage: s.storageTag}
   106  	s.volumeAttachment = &mockVolumeAttachment{
   107  		VolumeTag:  s.volumeTag,
   108  		MachineTag: s.machineTag,
   109  	}
   110  
   111  	s.blocks = make(map[state.BlockType]state.Block)
   112  	return &mockState{
   113  		allStorageInstances: func() ([]state.StorageInstance, error) {
   114  			s.calls = append(s.calls, allStorageInstancesCall)
   115  			return []state.StorageInstance{s.storageInstance}, nil
   116  		},
   117  		storageInstance: func(sTag names.StorageTag) (state.StorageInstance, error) {
   118  			s.calls = append(s.calls, storageInstanceCall)
   119  			c.Assert(sTag, gc.DeepEquals, s.storageTag)
   120  			return s.storageInstance, nil
   121  		},
   122  		storageInstanceAttachments: func(tag names.StorageTag) ([]state.StorageAttachment, error) {
   123  			s.calls = append(s.calls, storageInstanceAttachmentsCall)
   124  			c.Assert(tag, gc.DeepEquals, s.storageTag)
   125  			return []state.StorageAttachment{storageInstanceAttachment}, nil
   126  		},
   127  		storageInstanceFilesystem: func(sTag names.StorageTag) (state.Filesystem, error) {
   128  			s.calls = append(s.calls, storageInstanceFilesystemCall)
   129  			c.Assert(sTag, gc.DeepEquals, s.storageTag)
   130  			return filesystem, nil
   131  		},
   132  		storageInstanceFilesystemAttachment: func(m names.MachineTag, f names.FilesystemTag) (state.FilesystemAttachment, error) {
   133  			s.calls = append(s.calls, storageInstanceFilesystemAttachmentCall)
   134  			c.Assert(m, gc.DeepEquals, s.machineTag)
   135  			c.Assert(f, gc.DeepEquals, filesystemTag)
   136  			return filesystemAttachment, nil
   137  		},
   138  		storageInstanceVolume: func(t names.StorageTag) (state.Volume, error) {
   139  			s.calls = append(s.calls, storageInstanceVolumeCall)
   140  			c.Assert(t, gc.DeepEquals, s.storageTag)
   141  			return s.volume, nil
   142  		},
   143  		unitAssignedMachine: func(u names.UnitTag) (names.MachineTag, error) {
   144  			s.calls = append(s.calls, unitAssignedMachineCall)
   145  			c.Assert(u, gc.DeepEquals, s.unitTag)
   146  			return s.machineTag, nil
   147  		},
   148  		volume: func(tag names.VolumeTag) (state.Volume, error) {
   149  			s.calls = append(s.calls, volumeCall)
   150  			c.Assert(tag, gc.DeepEquals, s.volumeTag)
   151  			return s.volume, nil
   152  		},
   153  		machineVolumeAttachments: func(machine names.MachineTag) ([]state.VolumeAttachment, error) {
   154  			s.calls = append(s.calls, machineVolumeAttachmentsCall)
   155  			c.Assert(machine, gc.DeepEquals, s.machineTag)
   156  			return []state.VolumeAttachment{s.volumeAttachment}, nil
   157  		},
   158  		volumeAttachments: func(volume names.VolumeTag) ([]state.VolumeAttachment, error) {
   159  			s.calls = append(s.calls, volumeAttachmentsCall)
   160  			c.Assert(volume, gc.DeepEquals, s.volumeTag)
   161  			return []state.VolumeAttachment{s.volumeAttachment}, nil
   162  		},
   163  		allVolumes: func() ([]state.Volume, error) {
   164  			s.calls = append(s.calls, allVolumesCall)
   165  			return []state.Volume{s.volume}, nil
   166  		},
   167  		envName: "storagetest",
   168  		addStorageForUnit: func(u names.UnitTag, name string, cons state.StorageConstraints) error {
   169  			s.calls = append(s.calls, addStorageForUnitCall)
   170  			return nil
   171  		},
   172  		getBlockForType: func(t state.BlockType) (state.Block, bool, error) {
   173  			s.calls = append(s.calls, getBlockForTypeCall)
   174  			val, found := s.blocks[t]
   175  			return val, found, nil
   176  		},
   177  	}
   178  }
   179  
   180  func (s *baseStorageSuite) addBlock(c *gc.C, t state.BlockType, msg string) {
   181  	s.blocks[t] = mockBlock{
   182  		t:   t,
   183  		msg: msg,
   184  	}
   185  }
   186  
   187  func (s *baseStorageSuite) blockAllChanges(c *gc.C, msg string) {
   188  	s.addBlock(c, state.ChangeBlock, msg)
   189  }
   190  
   191  func (s *baseStorageSuite) blockDestroyEnvironment(c *gc.C, msg string) {
   192  	s.addBlock(c, state.DestroyBlock, msg)
   193  }
   194  
   195  func (s *baseStorageSuite) blockRemoveObject(c *gc.C, msg string) {
   196  	s.addBlock(c, state.RemoveBlock, msg)
   197  }
   198  
   199  func (s *baseStorageSuite) assertBlocked(c *gc.C, err error, msg string) {
   200  	c.Assert(params.IsCodeOperationBlocked(err), jc.IsTrue)
   201  	c.Assert(err, gc.ErrorMatches, msg)
   202  }
   203  
   204  func (s *baseStorageSuite) constructPoolManager(c *gc.C) *mockPoolManager {
   205  	return &mockPoolManager{
   206  		getPool: func(name string) (*jujustorage.Config, error) {
   207  			if one, ok := s.pools[name]; ok {
   208  				return one, nil
   209  			}
   210  			return nil, errors.NotFoundf("mock pool manager: get pool %v", name)
   211  		},
   212  		createPool: func(name string, providerType jujustorage.ProviderType, attrs map[string]interface{}) (*jujustorage.Config, error) {
   213  			pool, err := jujustorage.NewConfig(name, providerType, attrs)
   214  			s.pools[name] = pool
   215  			return pool, err
   216  		},
   217  		deletePool: func(name string) error {
   218  			delete(s.pools, name)
   219  			return nil
   220  		},
   221  		listPools: func() ([]*jujustorage.Config, error) {
   222  			result := make([]*jujustorage.Config, len(s.pools))
   223  			i := 0
   224  			for _, v := range s.pools {
   225  				result[i] = v
   226  				i++
   227  			}
   228  			return result, nil
   229  		},
   230  	}
   231  }
   232  
   233  type mockPoolManager struct {
   234  	getPool    func(name string) (*jujustorage.Config, error)
   235  	createPool func(name string, providerType jujustorage.ProviderType, attrs map[string]interface{}) (*jujustorage.Config, error)
   236  	deletePool func(name string) error
   237  	listPools  func() ([]*jujustorage.Config, error)
   238  }
   239  
   240  func (m *mockPoolManager) Get(name string) (*jujustorage.Config, error) {
   241  	return m.getPool(name)
   242  }
   243  
   244  func (m *mockPoolManager) Create(name string, providerType jujustorage.ProviderType, attrs map[string]interface{}) (*jujustorage.Config, error) {
   245  	return m.createPool(name, providerType, attrs)
   246  }
   247  
   248  func (m *mockPoolManager) Delete(name string) error {
   249  	return m.deletePool(name)
   250  }
   251  
   252  func (m *mockPoolManager) List() ([]*jujustorage.Config, error) {
   253  	return m.listPools()
   254  }
   255  
   256  type mockState struct {
   257  	storageInstance                     func(names.StorageTag) (state.StorageInstance, error)
   258  	allStorageInstances                 func() ([]state.StorageInstance, error)
   259  	storageInstanceAttachments          func(names.StorageTag) ([]state.StorageAttachment, error)
   260  	unitAssignedMachine                 func(u names.UnitTag) (names.MachineTag, error)
   261  	storageInstanceVolume               func(names.StorageTag) (state.Volume, error)
   262  	storageInstanceVolumeAttachment     func(names.MachineTag, names.VolumeTag) (state.VolumeAttachment, error)
   263  	storageInstanceFilesystem           func(names.StorageTag) (state.Filesystem, error)
   264  	storageInstanceFilesystemAttachment func(m names.MachineTag, f names.FilesystemTag) (state.FilesystemAttachment, error)
   265  	watchStorageAttachment              func(names.StorageTag, names.UnitTag) state.NotifyWatcher
   266  	watchFilesystemAttachment           func(names.MachineTag, names.FilesystemTag) state.NotifyWatcher
   267  	watchVolumeAttachment               func(names.MachineTag, names.VolumeTag) state.NotifyWatcher
   268  	envName                             string
   269  	volume                              func(tag names.VolumeTag) (state.Volume, error)
   270  	machineVolumeAttachments            func(machine names.MachineTag) ([]state.VolumeAttachment, error)
   271  	volumeAttachments                   func(volume names.VolumeTag) ([]state.VolumeAttachment, error)
   272  	allVolumes                          func() ([]state.Volume, error)
   273  	addStorageForUnit                   func(u names.UnitTag, name string, cons state.StorageConstraints) error
   274  	getBlockForType                     func(t state.BlockType) (state.Block, bool, error)
   275  }
   276  
   277  func (st *mockState) StorageInstance(s names.StorageTag) (state.StorageInstance, error) {
   278  	return st.storageInstance(s)
   279  }
   280  
   281  func (st *mockState) AllStorageInstances() ([]state.StorageInstance, error) {
   282  	return st.allStorageInstances()
   283  }
   284  
   285  func (st *mockState) StorageAttachments(tag names.StorageTag) ([]state.StorageAttachment, error) {
   286  	return st.storageInstanceAttachments(tag)
   287  }
   288  
   289  func (st *mockState) UnitAssignedMachine(unit names.UnitTag) (names.MachineTag, error) {
   290  	return st.unitAssignedMachine(unit)
   291  }
   292  
   293  func (st *mockState) FilesystemAttachment(m names.MachineTag, f names.FilesystemTag) (state.FilesystemAttachment, error) {
   294  	return st.storageInstanceFilesystemAttachment(m, f)
   295  }
   296  
   297  func (st *mockState) StorageInstanceFilesystem(s names.StorageTag) (state.Filesystem, error) {
   298  	return st.storageInstanceFilesystem(s)
   299  }
   300  
   301  func (st *mockState) StorageInstanceVolume(s names.StorageTag) (state.Volume, error) {
   302  	return st.storageInstanceVolume(s)
   303  }
   304  
   305  func (st *mockState) VolumeAttachment(m names.MachineTag, v names.VolumeTag) (state.VolumeAttachment, error) {
   306  	return st.storageInstanceVolumeAttachment(m, v)
   307  }
   308  
   309  func (st *mockState) WatchStorageAttachment(s names.StorageTag, u names.UnitTag) state.NotifyWatcher {
   310  	return st.watchStorageAttachment(s, u)
   311  }
   312  
   313  func (st *mockState) WatchFilesystemAttachment(mtag names.MachineTag, f names.FilesystemTag) state.NotifyWatcher {
   314  	return st.watchFilesystemAttachment(mtag, f)
   315  }
   316  
   317  func (st *mockState) WatchVolumeAttachment(mtag names.MachineTag, v names.VolumeTag) state.NotifyWatcher {
   318  	return st.watchVolumeAttachment(mtag, v)
   319  }
   320  
   321  func (st *mockState) EnvName() (string, error) {
   322  	return st.envName, nil
   323  }
   324  
   325  func (st *mockState) AllVolumes() ([]state.Volume, error) {
   326  	return st.allVolumes()
   327  }
   328  
   329  func (st *mockState) VolumeAttachments(volume names.VolumeTag) ([]state.VolumeAttachment, error) {
   330  	return st.volumeAttachments(volume)
   331  }
   332  
   333  func (st *mockState) MachineVolumeAttachments(machine names.MachineTag) ([]state.VolumeAttachment, error) {
   334  	return st.machineVolumeAttachments(machine)
   335  }
   336  
   337  func (st *mockState) Volume(tag names.VolumeTag) (state.Volume, error) {
   338  	return st.volume(tag)
   339  }
   340  
   341  func (st *mockState) AddStorageForUnit(u names.UnitTag, name string, cons state.StorageConstraints) error {
   342  	return st.addStorageForUnit(u, name, cons)
   343  }
   344  
   345  func (st *mockState) GetBlockForType(t state.BlockType) (state.Block, bool, error) {
   346  	return st.getBlockForType(t)
   347  }
   348  
   349  type mockNotifyWatcher struct {
   350  	state.NotifyWatcher
   351  	changes chan struct{}
   352  }
   353  
   354  func (m *mockNotifyWatcher) Changes() <-chan struct{} {
   355  	return m.changes
   356  }
   357  
   358  type mockVolume struct {
   359  	state.Volume
   360  	tag          names.VolumeTag
   361  	storage      names.StorageTag
   362  	hasNoStorage bool
   363  }
   364  
   365  func (m *mockVolume) StorageInstance() (names.StorageTag, error) {
   366  	if m.hasNoStorage {
   367  		return names.StorageTag{}, errors.NewNotAssigned(nil, "error from mock")
   368  	}
   369  	return m.storage, nil
   370  }
   371  
   372  func (m *mockVolume) VolumeTag() names.VolumeTag {
   373  	return m.tag
   374  }
   375  
   376  func (m *mockVolume) Params() (state.VolumeParams, bool) {
   377  	return state.VolumeParams{
   378  		Pool: "loop",
   379  		Size: 1024,
   380  	}, true
   381  }
   382  
   383  func (m *mockVolume) Info() (state.VolumeInfo, error) {
   384  	return state.VolumeInfo{}, errors.NotProvisionedf("%v", m.tag)
   385  }
   386  
   387  func (m *mockVolume) Status() (state.StatusInfo, error) {
   388  	return state.StatusInfo{Status: state.StatusAttached}, nil
   389  }
   390  
   391  type mockFilesystem struct {
   392  	state.Filesystem
   393  	tag names.FilesystemTag
   394  }
   395  
   396  func (m *mockFilesystem) FilesystemTag() names.FilesystemTag {
   397  	return m.tag
   398  }
   399  
   400  type mockFilesystemAttachment struct {
   401  	state.FilesystemAttachment
   402  	tag names.FilesystemTag
   403  }
   404  
   405  func (m *mockFilesystemAttachment) Filesystem() names.FilesystemTag {
   406  	return m.tag
   407  }
   408  
   409  func (m *mockFilesystemAttachment) Info() (state.FilesystemAttachmentInfo, error) {
   410  	return state.FilesystemAttachmentInfo{}, nil
   411  }
   412  
   413  type mockStorageInstance struct {
   414  	state.StorageInstance
   415  	kind       state.StorageKind
   416  	owner      names.Tag
   417  	storageTag names.Tag
   418  }
   419  
   420  func (m *mockStorageInstance) Kind() state.StorageKind {
   421  	return m.kind
   422  }
   423  
   424  func (m *mockStorageInstance) Owner() names.Tag {
   425  	return m.owner
   426  }
   427  
   428  func (m *mockStorageInstance) Tag() names.Tag {
   429  	return m.storageTag
   430  }
   431  
   432  func (m *mockStorageInstance) StorageTag() names.StorageTag {
   433  	return m.storageTag.(names.StorageTag)
   434  }
   435  
   436  func (m *mockStorageInstance) CharmURL() *charm.URL {
   437  	panic("not implemented for test")
   438  }
   439  
   440  type mockStorageAttachment struct {
   441  	state.StorageAttachment
   442  	storage *mockStorageInstance
   443  }
   444  
   445  func (m *mockStorageAttachment) StorageInstance() names.StorageTag {
   446  	return m.storage.Tag().(names.StorageTag)
   447  }
   448  
   449  func (m *mockStorageAttachment) Unit() names.UnitTag {
   450  	return m.storage.Owner().(names.UnitTag)
   451  }
   452  
   453  type mockVolumeAttachment struct {
   454  	VolumeTag  names.VolumeTag
   455  	MachineTag names.MachineTag
   456  }
   457  
   458  func (va *mockVolumeAttachment) Volume() names.VolumeTag {
   459  	return va.VolumeTag
   460  }
   461  
   462  func (va *mockVolumeAttachment) Machine() names.MachineTag {
   463  	return va.MachineTag
   464  }
   465  
   466  func (va *mockVolumeAttachment) Life() state.Life {
   467  	panic("not implemented for test")
   468  }
   469  
   470  func (va *mockVolumeAttachment) Info() (state.VolumeAttachmentInfo, error) {
   471  	return state.VolumeAttachmentInfo{}, errors.New("not interested yet")
   472  }
   473  
   474  func (va *mockVolumeAttachment) Params() (state.VolumeAttachmentParams, bool) {
   475  	panic("not implemented for test")
   476  }
   477  
   478  type mockBlock struct {
   479  	state.Block
   480  	t   state.BlockType
   481  	msg string
   482  }
   483  
   484  func (b mockBlock) Type() state.BlockType {
   485  	return b.t
   486  }
   487  
   488  func (b mockBlock) Message() string {
   489  	return b.msg
   490  }