github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/apiserver/facades/controller/caasunitprovisioner/mock_test.go (about)

     1  // Copyright 2017 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package caasunitprovisioner_test
     5  
     6  import (
     7  	"strings"
     8  	"time"
     9  
    10  	"github.com/juju/charm/v12"
    11  	"github.com/juju/errors"
    12  	"github.com/juju/names/v5"
    13  	"github.com/juju/testing"
    14  
    15  	charmscommon "github.com/juju/juju/apiserver/common/charms"
    16  	"github.com/juju/juju/apiserver/facades/controller/caasunitprovisioner"
    17  	k8sconstants "github.com/juju/juju/caas/kubernetes/provider/constants"
    18  	"github.com/juju/juju/controller"
    19  	coreconfig "github.com/juju/juju/core/config"
    20  	"github.com/juju/juju/core/constraints"
    21  	"github.com/juju/juju/core/network"
    22  	"github.com/juju/juju/core/status"
    23  	"github.com/juju/juju/environs/config"
    24  	"github.com/juju/juju/state"
    25  	statetesting "github.com/juju/juju/state/testing"
    26  	"github.com/juju/juju/storage"
    27  	"github.com/juju/juju/storage/poolmanager"
    28  	coretesting "github.com/juju/juju/testing"
    29  	jujuversion "github.com/juju/juju/version"
    30  )
    31  
    32  type mockState struct {
    33  	testing.Stub
    34  	application         mockApplication
    35  	applicationsWatcher *statetesting.MockStringsWatcher
    36  	model               mockModel
    37  	unit                mockUnit
    38  }
    39  
    40  func (st *mockState) WatchApplications() state.StringsWatcher {
    41  	st.MethodCall(st, "WatchApplications")
    42  	return st.applicationsWatcher
    43  }
    44  
    45  func (st *mockState) Application(name string) (caasunitprovisioner.Application, error) {
    46  	st.MethodCall(st, "Application", name)
    47  	if name != st.application.tag.Id() {
    48  		return nil, errors.NotFoundf("application %v", name)
    49  	}
    50  	return &st.application, st.NextErr()
    51  }
    52  
    53  func (st *mockState) FindEntity(tag names.Tag) (state.Entity, error) {
    54  	st.MethodCall(st, "FindEntity", tag)
    55  	if err := st.NextErr(); err != nil {
    56  		return nil, err
    57  	}
    58  	switch tag.(type) {
    59  	case names.ApplicationTag:
    60  		return &st.application, nil
    61  	case names.UnitTag:
    62  		return &st.unit, nil
    63  	default:
    64  		return nil, errors.NotFoundf("%s", names.ReadableString(tag))
    65  	}
    66  }
    67  
    68  func (st *mockState) ControllerConfig() (controller.Config, error) {
    69  	st.MethodCall(st, "ControllerConfig")
    70  	return coretesting.FakeControllerConfig(), nil
    71  }
    72  
    73  func (st *mockState) Model() (caasunitprovisioner.Model, error) {
    74  	st.MethodCall(st, "Model")
    75  	if err := st.NextErr(); err != nil {
    76  		return nil, err
    77  	}
    78  	return &st.model, nil
    79  }
    80  
    81  func (st *mockState) ResolveConstraints(cons constraints.Value) (constraints.Value, error) {
    82  	st.MethodCall(st, "ResolveConstraints", cons)
    83  	if err := st.NextErr(); err != nil {
    84  		return constraints.Value{}, err
    85  	}
    86  	return cons, nil
    87  }
    88  
    89  func (m *mockState) AllSpaceInfos() (network.SpaceInfos, error) {
    90  	m.MethodCall(m, "AllSpaceInfos")
    91  	return network.SpaceInfos{}, nil
    92  }
    93  
    94  type mockModel struct {
    95  	testing.Stub
    96  	podSpecWatcher *statetesting.MockNotifyWatcher
    97  	containers     []state.CloudContainer
    98  	isRawK8sSpec   *bool
    99  }
   100  
   101  func (m *mockModel) ModelConfig() (*config.Config, error) {
   102  	m.MethodCall(m, "ModelConfig")
   103  	attrs := coretesting.FakeConfig()
   104  	attrs["workload-storage"] = "k8s-storage"
   105  	ver := jujuversion.Current
   106  	ver.Build = 666
   107  	attrs["agent-version"] = ver.String()
   108  	return config.New(config.UseDefaults, attrs)
   109  }
   110  
   111  func (m *mockModel) PodSpec(tag names.ApplicationTag) (string, error) {
   112  	m.MethodCall(m, "PodSpec", tag)
   113  	if err := m.NextErr(); err != nil {
   114  		return "", err
   115  	}
   116  	if *m.isRawK8sSpec {
   117  		return "", nil
   118  	}
   119  	return "spec(" + tag.Id() + ")", nil
   120  }
   121  
   122  func (m *mockModel) RawK8sSpec(tag names.ApplicationTag) (string, error) {
   123  	m.MethodCall(m, "RawK8sSpec", tag)
   124  	if err := m.NextErr(); err != nil {
   125  		return "", err
   126  	}
   127  	if *m.isRawK8sSpec {
   128  		return "raw spec(" + tag.Id() + ")", nil
   129  	}
   130  	return "", nil
   131  }
   132  
   133  func (m *mockModel) WatchPodSpec(tag names.ApplicationTag) (state.NotifyWatcher, error) {
   134  	m.MethodCall(m, "WatchPodSpec", tag)
   135  	if err := m.NextErr(); err != nil {
   136  		return nil, err
   137  	}
   138  	return m.podSpecWatcher, nil
   139  }
   140  
   141  func (m *mockModel) Containers(providerIds ...string) ([]state.CloudContainer, error) {
   142  	m.MethodCall(m, "Containers", providerIds)
   143  	return m.containers, nil
   144  }
   145  
   146  type mockApplication struct {
   147  	testing.Stub
   148  	life            state.Life
   149  	scaleWatcher    *statetesting.MockNotifyWatcher
   150  	settingsWatcher *statetesting.MockStringsWatcher
   151  
   152  	tag        names.Tag
   153  	scale      int
   154  	units      []caasunitprovisioner.Unit
   155  	ops        *state.UpdateUnitsOperation
   156  	providerId string
   157  	addresses  []network.SpaceAddress
   158  	charm      *mockCharm
   159  }
   160  
   161  func (a *mockApplication) Tag() names.Tag {
   162  	return a.tag
   163  }
   164  
   165  func (a *mockApplication) Name() string {
   166  	a.MethodCall(a, "Name")
   167  	return a.tag.Id()
   168  }
   169  
   170  func (a *mockApplication) Life() state.Life {
   171  	a.MethodCall(a, "Life")
   172  	return a.life
   173  }
   174  
   175  func (a *mockApplication) WatchScale() state.NotifyWatcher {
   176  	a.MethodCall(a, "WatchScale")
   177  	return a.scaleWatcher
   178  }
   179  
   180  func (a *mockApplication) GetScale() int {
   181  	a.MethodCall(a, "GetScale")
   182  	return a.scale
   183  }
   184  
   185  func (a *mockApplication) SetScale(scale int, generation int64, force bool) error {
   186  	a.MethodCall(a, "SetScale", scale)
   187  	a.scale = scale
   188  	return nil
   189  }
   190  
   191  func (a *mockApplication) WatchConfigSettingsHash() state.StringsWatcher {
   192  	a.MethodCall(a, "WatchConfigSettingsHash")
   193  	return a.settingsWatcher
   194  }
   195  
   196  func (a *mockApplication) ClearResources() error {
   197  	a.MethodCall(a, "ClearResources")
   198  	return nil
   199  }
   200  
   201  func (a *mockApplication) CharmModifiedVersion() int {
   202  	a.MethodCall(a, "CharmModifiedVersion")
   203  	return 888
   204  }
   205  
   206  func (a *mockApplication) StorageConstraints() (map[string]state.StorageConstraints, error) {
   207  	return map[string]state.StorageConstraints{
   208  		"data": {
   209  			Size:  100,
   210  			Count: 1,
   211  		},
   212  		"logs": {
   213  			Size:  200,
   214  			Pool:  "rootfs",
   215  			Count: 1,
   216  		},
   217  	}, nil
   218  }
   219  
   220  type mockCharm struct {
   221  	charmscommon.Charm
   222  	meta charm.Meta
   223  }
   224  
   225  func (m *mockCharm) Meta() *charm.Meta {
   226  	return &m.meta
   227  }
   228  
   229  func (a *mockApplication) Charm() (charmscommon.Charm, bool, error) {
   230  	a.MethodCall(a, "Charm")
   231  	return a.charm, false, nil
   232  }
   233  
   234  func (a *mockApplication) GetPlacement() string {
   235  	a.MethodCall(a, "GetPlacement")
   236  	return "placement"
   237  }
   238  
   239  func (a *mockApplication) ApplicationConfig() (coreconfig.ConfigAttributes, error) {
   240  	a.MethodCall(a, "ApplicationConfig")
   241  	return coreconfig.ConfigAttributes{"foo": "bar"}, a.NextErr()
   242  }
   243  
   244  func (m *mockApplication) AllUnits() (units []caasunitprovisioner.Unit, err error) {
   245  	return m.units, nil
   246  }
   247  
   248  func (m *mockApplication) UpdateUnits(ops *state.UpdateUnitsOperation) error {
   249  	m.ops = ops
   250  	return nil
   251  }
   252  
   253  func (m *mockApplication) DeviceConstraints() (map[string]state.DeviceConstraints, error) {
   254  	return map[string]state.DeviceConstraints{
   255  		"bitcoinminer": {Type: "nvidia.com/gpu",
   256  			Count:      3,
   257  			Attributes: map[string]string{"gpu": "nvidia-tesla-p100"},
   258  		},
   259  	}, nil
   260  }
   261  
   262  func (m *mockApplication) Constraints() (constraints.Value, error) {
   263  	return constraints.MustParse("mem=64G"), nil
   264  }
   265  
   266  func (m *mockApplication) UpdateCloudService(providerId string, addresses []network.SpaceAddress) error {
   267  	m.providerId = providerId
   268  	m.addresses = addresses
   269  	return nil
   270  }
   271  
   272  var addOp = &state.AddUnitOperation{}
   273  
   274  func (m *mockApplication) AddOperation(props state.UnitUpdateProperties) *state.AddUnitOperation {
   275  	m.MethodCall(m, "AddOperation", props)
   276  	return addOp
   277  }
   278  
   279  func (m *mockApplication) SetOperatorStatus(sInfo status.StatusInfo) error {
   280  	m.MethodCall(m, "SetOperatorStatus", sInfo)
   281  	return nil
   282  }
   283  
   284  func (m *mockApplication) SetStatus(sInfo status.StatusInfo) error {
   285  	m.MethodCall(m, "SetStatus", sInfo)
   286  	return nil
   287  }
   288  
   289  type mockContainerInfo struct {
   290  	state.CloudContainer
   291  	providerId string
   292  	unitName   string
   293  }
   294  
   295  func (m *mockContainerInfo) ProviderId() string {
   296  	return m.providerId
   297  }
   298  
   299  func (m *mockContainerInfo) Unit() string {
   300  	return m.unitName
   301  }
   302  
   303  type mockUnit struct {
   304  	testing.Stub
   305  	name          string
   306  	life          state.Life
   307  	containerInfo *mockContainerInfo
   308  }
   309  
   310  func (*mockUnit) Tag() names.Tag {
   311  	panic("should not be called")
   312  }
   313  
   314  func (u *mockUnit) UnitTag() names.UnitTag {
   315  	return names.NewUnitTag(u.name)
   316  }
   317  
   318  func (u *mockUnit) Life() state.Life {
   319  	u.MethodCall(u, "Life")
   320  	return u.life
   321  }
   322  
   323  func (m *mockUnit) Name() string {
   324  	return m.name
   325  }
   326  
   327  func (m *mockUnit) ContainerInfo() (state.CloudContainer, error) {
   328  	if m.containerInfo == nil {
   329  		return nil, errors.NotFoundf("container info")
   330  	}
   331  	return m.containerInfo, nil
   332  }
   333  
   334  func (m *mockUnit) AgentStatus() (status.StatusInfo, error) {
   335  	return status.StatusInfo{Status: status.Allocating}, nil
   336  }
   337  
   338  var updateOp = &state.UpdateUnitOperation{}
   339  
   340  func (m *mockUnit) UpdateOperation(props state.UnitUpdateProperties) *state.UpdateUnitOperation {
   341  	m.MethodCall(m, "UpdateOperation", props)
   342  	return updateOp
   343  }
   344  
   345  var destroyOp = &state.DestroyUnitOperation{}
   346  
   347  func (m *mockUnit) DestroyOperation() *state.DestroyUnitOperation {
   348  	m.MethodCall(m, "DestroyOperation")
   349  	return destroyOp
   350  }
   351  
   352  type mockStorage struct {
   353  	testing.Stub
   354  	storageFilesystems map[names.StorageTag]names.FilesystemTag
   355  	storageVolumes     map[names.StorageTag]names.VolumeTag
   356  	storageAttachments map[names.UnitTag]names.StorageTag
   357  	backingVolume      names.VolumeTag
   358  }
   359  
   360  func (m *mockStorage) StorageInstance(tag names.StorageTag) (state.StorageInstance, error) {
   361  	m.MethodCall(m, "StorageInstance", tag)
   362  	return &mockStorageInstance{
   363  		tag:   tag,
   364  		owner: names.NewUserTag("fred"),
   365  	}, nil
   366  }
   367  
   368  func (m *mockStorage) AllFilesystems() ([]state.Filesystem, error) {
   369  	m.MethodCall(m, "AllFilesystems")
   370  	var result []state.Filesystem
   371  	for _, fsTag := range m.storageFilesystems {
   372  		result = append(result, &mockFilesystem{Stub: &m.Stub, tag: fsTag, volTag: m.backingVolume})
   373  	}
   374  	return result, nil
   375  }
   376  
   377  func (m *mockStorage) DestroyStorageInstance(tag names.StorageTag, destroyAttachments bool, force bool, maxWait time.Duration) (err error) {
   378  	m.MethodCall(m, "DestroyStorageInstance", tag, destroyAttachments, force)
   379  	return nil
   380  }
   381  
   382  func (m *mockStorage) DestroyFilesystem(tag names.FilesystemTag, force bool) (err error) {
   383  	m.MethodCall(m, "DestroyFilesystem", tag)
   384  	return nil
   385  }
   386  
   387  func (m *mockStorage) DestroyVolume(tag names.VolumeTag) (err error) {
   388  	m.MethodCall(m, "DestroyVolume", tag)
   389  	return nil
   390  }
   391  
   392  func (m *mockStorage) Filesystem(fsTag names.FilesystemTag) (state.Filesystem, error) {
   393  	m.MethodCall(m, "Filesystem", fsTag)
   394  	return &mockFilesystem{Stub: &m.Stub, tag: fsTag, volTag: m.backingVolume}, nil
   395  }
   396  
   397  func (m *mockStorage) StorageInstanceFilesystem(tag names.StorageTag) (state.Filesystem, error) {
   398  	return &mockFilesystem{Stub: &m.Stub, tag: m.storageFilesystems[tag], volTag: m.backingVolume}, nil
   399  }
   400  
   401  func (m *mockStorage) UnitStorageAttachments(unit names.UnitTag) ([]state.StorageAttachment, error) {
   402  	m.MethodCall(m, "UnitStorageAttachments", unit)
   403  	return []state.StorageAttachment{
   404  		&mockStorageAttachment{
   405  			unit:    unit,
   406  			storage: m.storageAttachments[unit],
   407  		},
   408  	}, nil
   409  }
   410  
   411  func (m *mockStorage) SetFilesystemInfo(fsTag names.FilesystemTag, fsInfo state.FilesystemInfo) error {
   412  	m.MethodCall(m, "SetFilesystemInfo", fsTag, fsInfo)
   413  	return nil
   414  }
   415  
   416  func (m *mockStorage) SetFilesystemAttachmentInfo(host names.Tag, fsTag names.FilesystemTag, info state.FilesystemAttachmentInfo) error {
   417  	m.MethodCall(m, "SetFilesystemAttachmentInfo", host, fsTag, info)
   418  	return nil
   419  }
   420  
   421  func (m *mockStorage) Volume(volTag names.VolumeTag) (state.Volume, error) {
   422  	m.MethodCall(m, "Volume", volTag)
   423  	return &mockVolume{Stub: &m.Stub, tag: volTag}, nil
   424  }
   425  
   426  func (m *mockStorage) StorageInstanceVolume(tag names.StorageTag) (state.Volume, error) {
   427  	return &mockVolume{Stub: &m.Stub, tag: m.storageVolumes[tag]}, nil
   428  }
   429  
   430  func (m *mockStorage) SetVolumeInfo(volTag names.VolumeTag, volInfo state.VolumeInfo) error {
   431  	m.MethodCall(m, "SetVolumeInfo", volTag, volInfo)
   432  	return nil
   433  }
   434  
   435  func (m *mockStorage) SetVolumeAttachmentInfo(host names.Tag, volTag names.VolumeTag, info state.VolumeAttachmentInfo) error {
   436  	m.MethodCall(m, "SetVolumeAttachmentInfo", host, volTag, info)
   437  	return nil
   438  }
   439  
   440  type mockDeviceBackend struct {
   441  	testing.Stub
   442  }
   443  
   444  func (d *mockDeviceBackend) DeviceConstraints(id string) (map[string]state.DeviceConstraints, error) {
   445  	d.MethodCall(d, "DeviceConstraints", id)
   446  	return map[string]state.DeviceConstraints{
   447  		"bitcoinminer": {Type: "nvidia.com/gpu",
   448  			Count:      3,
   449  			Attributes: map[string]string{"gpu": "nvidia-tesla-p100"},
   450  		}}, nil
   451  }
   452  
   453  type mockStorageInstance struct {
   454  	state.StorageInstance
   455  	tag   names.StorageTag
   456  	owner names.Tag
   457  }
   458  
   459  func (a *mockStorageInstance) Kind() state.StorageKind {
   460  	return state.StorageKindFilesystem
   461  }
   462  
   463  func (a *mockStorageInstance) Tag() names.Tag {
   464  	return a.tag
   465  }
   466  
   467  func (a *mockStorageInstance) StorageName() string {
   468  	id := a.tag.Id()
   469  	return strings.Split(id, "/")[0]
   470  }
   471  
   472  type mockStorageAttachment struct {
   473  	state.StorageAttachment
   474  	testing.Stub
   475  	unit    names.UnitTag
   476  	storage names.StorageTag
   477  }
   478  
   479  func (a *mockStorageAttachment) StorageInstance() names.StorageTag {
   480  	return a.storage
   481  }
   482  
   483  type mockFilesystem struct {
   484  	*testing.Stub
   485  	state.Filesystem
   486  	tag    names.FilesystemTag
   487  	volTag names.VolumeTag
   488  }
   489  
   490  func (f *mockFilesystem) Tag() names.Tag {
   491  	return f.FilesystemTag()
   492  }
   493  
   494  func (f *mockFilesystem) FilesystemTag() names.FilesystemTag {
   495  	return f.tag
   496  }
   497  
   498  func (f *mockFilesystem) Volume() (names.VolumeTag, error) {
   499  	if f.volTag.Id() == "" {
   500  		return f.volTag, state.ErrNoBackingVolume
   501  	}
   502  	return f.volTag, nil
   503  }
   504  
   505  func (f *mockFilesystem) SetStatus(statusInfo status.StatusInfo) error {
   506  	f.MethodCall(f, "SetStatus", statusInfo)
   507  	return nil
   508  }
   509  
   510  func (f *mockFilesystem) Info() (state.FilesystemInfo, error) {
   511  	return state.FilesystemInfo{}, errors.NotProvisionedf("filesystem")
   512  }
   513  
   514  type mockVolume struct {
   515  	*testing.Stub
   516  	state.Volume
   517  	tag names.VolumeTag
   518  }
   519  
   520  func (v *mockVolume) Tag() names.Tag {
   521  	return v.VolumeTag()
   522  }
   523  
   524  func (v *mockVolume) VolumeTag() names.VolumeTag {
   525  	return v.tag
   526  }
   527  
   528  func (v *mockVolume) SetStatus(statusInfo status.StatusInfo) error {
   529  	v.MethodCall(v, "SetStatus", statusInfo)
   530  	return nil
   531  }
   532  
   533  func (v *mockVolume) Info() (state.VolumeInfo, error) {
   534  	return state.VolumeInfo{}, errors.NotProvisionedf("volume")
   535  }
   536  
   537  type mockStoragePoolManager struct {
   538  	testing.Stub
   539  	poolmanager.PoolManager
   540  }
   541  
   542  func (m *mockStoragePoolManager) Get(name string) (*storage.Config, error) {
   543  	m.MethodCall(m, "Get", name)
   544  	if name == "rootfs" {
   545  		return nil, errors.NotFoundf("pool %q", name)
   546  	}
   547  	return storage.NewConfig(name, k8sconstants.StorageProviderType, map[string]interface{}{"foo": "bar"})
   548  }
   549  
   550  type mockStorageRegistry struct {
   551  	testing.Stub
   552  	storage.ProviderRegistry
   553  }
   554  
   555  type mockProvider struct {
   556  	storage.Provider
   557  }
   558  
   559  func (m *mockProvider) Supports(kind storage.StorageKind) bool {
   560  	return kind == storage.StorageKindFilesystem
   561  }
   562  
   563  func (m *mockStorageRegistry) StorageProvider(p storage.ProviderType) (storage.Provider, error) {
   564  	if p != "rootfs" {
   565  		return nil, errors.NotFoundf("provider %q", p)
   566  	}
   567  	return &mockProvider{}, nil
   568  }