github.com/Pankov404/juju@v0.0.0-20150703034450-be266991dceb/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{t, msg}
   182  }
   183  
   184  func (s *baseStorageSuite) blockAllChanges(c *gc.C, msg string) {
   185  	s.addBlock(c, state.ChangeBlock, msg)
   186  }
   187  
   188  func (s *baseStorageSuite) blockDestroyEnvironment(c *gc.C, msg string) {
   189  	s.addBlock(c, state.DestroyBlock, msg)
   190  }
   191  
   192  func (s *baseStorageSuite) blockRemoveObject(c *gc.C, msg string) {
   193  	s.addBlock(c, state.RemoveBlock, msg)
   194  }
   195  
   196  func (s *baseStorageSuite) assertBlocked(c *gc.C, err error, msg string) {
   197  	c.Assert(params.IsCodeOperationBlocked(err), jc.IsTrue)
   198  	c.Assert(err, gc.ErrorMatches, msg)
   199  }
   200  
   201  func (s *baseStorageSuite) constructPoolManager(c *gc.C) *mockPoolManager {
   202  	return &mockPoolManager{
   203  		getPool: func(name string) (*jujustorage.Config, error) {
   204  			if one, ok := s.pools[name]; ok {
   205  				return one, nil
   206  			}
   207  			return nil, errors.NotFoundf("mock pool manager: get pool %v", name)
   208  		},
   209  		createPool: func(name string, providerType jujustorage.ProviderType, attrs map[string]interface{}) (*jujustorage.Config, error) {
   210  			pool, err := jujustorage.NewConfig(name, providerType, attrs)
   211  			s.pools[name] = pool
   212  			return pool, err
   213  		},
   214  		deletePool: func(name string) error {
   215  			delete(s.pools, name)
   216  			return nil
   217  		},
   218  		listPools: func() ([]*jujustorage.Config, error) {
   219  			result := make([]*jujustorage.Config, len(s.pools))
   220  			i := 0
   221  			for _, v := range s.pools {
   222  				result[i] = v
   223  				i++
   224  			}
   225  			return result, nil
   226  		},
   227  	}
   228  }
   229  
   230  type mockPoolManager struct {
   231  	getPool    func(name string) (*jujustorage.Config, error)
   232  	createPool func(name string, providerType jujustorage.ProviderType, attrs map[string]interface{}) (*jujustorage.Config, error)
   233  	deletePool func(name string) error
   234  	listPools  func() ([]*jujustorage.Config, error)
   235  }
   236  
   237  func (m *mockPoolManager) Get(name string) (*jujustorage.Config, error) {
   238  	return m.getPool(name)
   239  }
   240  
   241  func (m *mockPoolManager) Create(name string, providerType jujustorage.ProviderType, attrs map[string]interface{}) (*jujustorage.Config, error) {
   242  	return m.createPool(name, providerType, attrs)
   243  }
   244  
   245  func (m *mockPoolManager) Delete(name string) error {
   246  	return m.deletePool(name)
   247  }
   248  
   249  func (m *mockPoolManager) List() ([]*jujustorage.Config, error) {
   250  	return m.listPools()
   251  }
   252  
   253  type mockState struct {
   254  	storageInstance                     func(names.StorageTag) (state.StorageInstance, error)
   255  	allStorageInstances                 func() ([]state.StorageInstance, error)
   256  	storageInstanceAttachments          func(names.StorageTag) ([]state.StorageAttachment, error)
   257  	unitAssignedMachine                 func(u names.UnitTag) (names.MachineTag, error)
   258  	storageInstanceVolume               func(names.StorageTag) (state.Volume, error)
   259  	storageInstanceVolumeAttachment     func(names.MachineTag, names.VolumeTag) (state.VolumeAttachment, error)
   260  	storageInstanceFilesystem           func(names.StorageTag) (state.Filesystem, error)
   261  	storageInstanceFilesystemAttachment func(m names.MachineTag, f names.FilesystemTag) (state.FilesystemAttachment, error)
   262  	watchStorageAttachment              func(names.StorageTag, names.UnitTag) state.NotifyWatcher
   263  	watchFilesystemAttachment           func(names.MachineTag, names.FilesystemTag) state.NotifyWatcher
   264  	watchVolumeAttachment               func(names.MachineTag, names.VolumeTag) state.NotifyWatcher
   265  	envName                             string
   266  	volume                              func(tag names.VolumeTag) (state.Volume, error)
   267  	machineVolumeAttachments            func(machine names.MachineTag) ([]state.VolumeAttachment, error)
   268  	volumeAttachments                   func(volume names.VolumeTag) ([]state.VolumeAttachment, error)
   269  	allVolumes                          func() ([]state.Volume, error)
   270  	addStorageForUnit                   func(u names.UnitTag, name string, cons state.StorageConstraints) error
   271  	getBlockForType                     func(t state.BlockType) (state.Block, bool, error)
   272  }
   273  
   274  func (st *mockState) StorageInstance(s names.StorageTag) (state.StorageInstance, error) {
   275  	return st.storageInstance(s)
   276  }
   277  
   278  func (st *mockState) AllStorageInstances() ([]state.StorageInstance, error) {
   279  	return st.allStorageInstances()
   280  }
   281  
   282  func (st *mockState) StorageAttachments(tag names.StorageTag) ([]state.StorageAttachment, error) {
   283  	return st.storageInstanceAttachments(tag)
   284  }
   285  
   286  func (st *mockState) UnitAssignedMachine(unit names.UnitTag) (names.MachineTag, error) {
   287  	return st.unitAssignedMachine(unit)
   288  }
   289  
   290  func (st *mockState) FilesystemAttachment(m names.MachineTag, f names.FilesystemTag) (state.FilesystemAttachment, error) {
   291  	return st.storageInstanceFilesystemAttachment(m, f)
   292  }
   293  
   294  func (st *mockState) StorageInstanceFilesystem(s names.StorageTag) (state.Filesystem, error) {
   295  	return st.storageInstanceFilesystem(s)
   296  }
   297  
   298  func (st *mockState) StorageInstanceVolume(s names.StorageTag) (state.Volume, error) {
   299  	return st.storageInstanceVolume(s)
   300  }
   301  
   302  func (st *mockState) VolumeAttachment(m names.MachineTag, v names.VolumeTag) (state.VolumeAttachment, error) {
   303  	return st.storageInstanceVolumeAttachment(m, v)
   304  }
   305  
   306  func (st *mockState) WatchStorageAttachment(s names.StorageTag, u names.UnitTag) state.NotifyWatcher {
   307  	return st.watchStorageAttachment(s, u)
   308  }
   309  
   310  func (st *mockState) WatchFilesystemAttachment(mtag names.MachineTag, f names.FilesystemTag) state.NotifyWatcher {
   311  	return st.watchFilesystemAttachment(mtag, f)
   312  }
   313  
   314  func (st *mockState) WatchVolumeAttachment(mtag names.MachineTag, v names.VolumeTag) state.NotifyWatcher {
   315  	return st.watchVolumeAttachment(mtag, v)
   316  }
   317  
   318  func (st *mockState) EnvName() (string, error) {
   319  	return st.envName, nil
   320  }
   321  
   322  func (st *mockState) AllVolumes() ([]state.Volume, error) {
   323  	return st.allVolumes()
   324  }
   325  
   326  func (st *mockState) VolumeAttachments(volume names.VolumeTag) ([]state.VolumeAttachment, error) {
   327  	return st.volumeAttachments(volume)
   328  }
   329  
   330  func (st *mockState) MachineVolumeAttachments(machine names.MachineTag) ([]state.VolumeAttachment, error) {
   331  	return st.machineVolumeAttachments(machine)
   332  }
   333  
   334  func (st *mockState) Volume(tag names.VolumeTag) (state.Volume, error) {
   335  	return st.volume(tag)
   336  }
   337  
   338  func (st *mockState) AddStorageForUnit(u names.UnitTag, name string, cons state.StorageConstraints) error {
   339  	return st.addStorageForUnit(u, name, cons)
   340  }
   341  
   342  func (st *mockState) GetBlockForType(t state.BlockType) (state.Block, bool, error) {
   343  	return st.getBlockForType(t)
   344  }
   345  
   346  type mockNotifyWatcher struct {
   347  	state.NotifyWatcher
   348  	changes chan struct{}
   349  }
   350  
   351  func (m *mockNotifyWatcher) Changes() <-chan struct{} {
   352  	return m.changes
   353  }
   354  
   355  type mockVolume struct {
   356  	state.Volume
   357  	tag          names.VolumeTag
   358  	storage      names.StorageTag
   359  	hasNoStorage bool
   360  }
   361  
   362  func (m *mockVolume) StorageInstance() (names.StorageTag, error) {
   363  	if m.hasNoStorage {
   364  		return names.StorageTag{}, errors.NewNotAssigned(nil, "error from mock")
   365  	}
   366  	return m.storage, nil
   367  }
   368  
   369  func (m *mockVolume) VolumeTag() names.VolumeTag {
   370  	return m.tag
   371  }
   372  
   373  func (m *mockVolume) Params() (state.VolumeParams, bool) {
   374  	return state.VolumeParams{
   375  		Pool: "loop",
   376  		Size: 1024,
   377  	}, true
   378  }
   379  
   380  func (m *mockVolume) Info() (state.VolumeInfo, error) {
   381  	return state.VolumeInfo{}, errors.NotProvisionedf("%v", m.tag)
   382  }
   383  
   384  type mockFilesystem struct {
   385  	state.Filesystem
   386  	tag names.FilesystemTag
   387  }
   388  
   389  func (m *mockFilesystem) FilesystemTag() names.FilesystemTag {
   390  	return m.tag
   391  }
   392  
   393  type mockFilesystemAttachment struct {
   394  	state.FilesystemAttachment
   395  	tag names.FilesystemTag
   396  }
   397  
   398  func (m *mockFilesystemAttachment) Filesystem() names.FilesystemTag {
   399  	return m.tag
   400  }
   401  
   402  func (m *mockFilesystemAttachment) Info() (state.FilesystemAttachmentInfo, error) {
   403  	return state.FilesystemAttachmentInfo{}, nil
   404  }
   405  
   406  type mockStorageInstance struct {
   407  	state.StorageInstance
   408  	kind       state.StorageKind
   409  	owner      names.Tag
   410  	storageTag names.Tag
   411  }
   412  
   413  func (m *mockStorageInstance) Kind() state.StorageKind {
   414  	return m.kind
   415  }
   416  
   417  func (m *mockStorageInstance) Owner() names.Tag {
   418  	return m.owner
   419  }
   420  
   421  func (m *mockStorageInstance) Tag() names.Tag {
   422  	return m.storageTag
   423  }
   424  
   425  func (m *mockStorageInstance) StorageTag() names.StorageTag {
   426  	return m.storageTag.(names.StorageTag)
   427  }
   428  
   429  func (m *mockStorageInstance) CharmURL() *charm.URL {
   430  	panic("not implemented for test")
   431  }
   432  
   433  type mockStorageAttachment struct {
   434  	state.StorageAttachment
   435  	storage *mockStorageInstance
   436  }
   437  
   438  func (m *mockStorageAttachment) StorageInstance() names.StorageTag {
   439  	return m.storage.Tag().(names.StorageTag)
   440  }
   441  
   442  func (m *mockStorageAttachment) Unit() names.UnitTag {
   443  	return m.storage.Owner().(names.UnitTag)
   444  }
   445  
   446  type mockVolumeAttachment struct {
   447  	VolumeTag  names.VolumeTag
   448  	MachineTag names.MachineTag
   449  }
   450  
   451  func (va *mockVolumeAttachment) Volume() names.VolumeTag {
   452  	return va.VolumeTag
   453  }
   454  
   455  func (va *mockVolumeAttachment) Machine() names.MachineTag {
   456  	return va.MachineTag
   457  }
   458  
   459  func (va *mockVolumeAttachment) Life() state.Life {
   460  	panic("not implemented for test")
   461  }
   462  
   463  func (va *mockVolumeAttachment) Info() (state.VolumeAttachmentInfo, error) {
   464  	return state.VolumeAttachmentInfo{}, errors.New("not interested yet")
   465  }
   466  
   467  func (va *mockVolumeAttachment) Params() (state.VolumeAttachmentParams, bool) {
   468  	panic("not implemented for test")
   469  }
   470  
   471  type mockBlock struct {
   472  	t   state.BlockType
   473  	msg string
   474  }
   475  
   476  func (b mockBlock) Id() string {
   477  	panic("not implemented for test")
   478  }
   479  
   480  func (b mockBlock) Tag() (names.Tag, error) {
   481  	panic("not implemented for test")
   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  }