github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/state/migration_import_test.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package state_test
     5  
     6  import (
     7  	"fmt"
     8  	"time" // only uses time.Time values
     9  
    10  	"github.com/juju/errors"
    11  	jc "github.com/juju/testing/checkers"
    12  	"github.com/juju/utils"
    13  	"github.com/juju/version"
    14  	gc "gopkg.in/check.v1"
    15  	"gopkg.in/juju/charm.v6-unstable"
    16  	"gopkg.in/juju/names.v2"
    17  
    18  	"github.com/juju/juju/constraints"
    19  	"github.com/juju/juju/core/description"
    20  	"github.com/juju/juju/network"
    21  	"github.com/juju/juju/payload"
    22  	"github.com/juju/juju/permission"
    23  	"github.com/juju/juju/state"
    24  	"github.com/juju/juju/state/cloudimagemetadata"
    25  	"github.com/juju/juju/status"
    26  	"github.com/juju/juju/storage/poolmanager"
    27  	"github.com/juju/juju/storage/provider"
    28  	coretesting "github.com/juju/juju/testing"
    29  	"github.com/juju/juju/testing/factory"
    30  )
    31  
    32  type MigrationImportSuite struct {
    33  	MigrationBaseSuite
    34  }
    35  
    36  var _ = gc.Suite(&MigrationImportSuite{})
    37  
    38  func (s *MigrationImportSuite) checkStatusHistory(c *gc.C, exported, imported status.StatusHistoryGetter, size int) {
    39  	exportedHistory, err := exported.StatusHistory(status.StatusHistoryFilter{Size: size})
    40  	c.Assert(err, jc.ErrorIsNil)
    41  	importedHistory, err := imported.StatusHistory(status.StatusHistoryFilter{Size: size})
    42  	c.Assert(err, jc.ErrorIsNil)
    43  	for i := 0; i < size; i++ {
    44  		c.Check(importedHistory[i].Status, gc.Equals, exportedHistory[i].Status)
    45  		c.Check(importedHistory[i].Message, gc.Equals, exportedHistory[i].Message)
    46  		c.Check(importedHistory[i].Data, jc.DeepEquals, exportedHistory[i].Data)
    47  		c.Check(importedHistory[i].Since, jc.DeepEquals, exportedHistory[i].Since)
    48  	}
    49  }
    50  
    51  func (s *MigrationImportSuite) TestExisting(c *gc.C) {
    52  	out, err := s.State.Export()
    53  	c.Assert(err, jc.ErrorIsNil)
    54  
    55  	_, _, err = s.State.Import(out)
    56  	c.Assert(err, jc.Satisfies, errors.IsAlreadyExists)
    57  }
    58  
    59  func (s *MigrationImportSuite) importModel(c *gc.C) (*state.Model, *state.State) {
    60  	out, err := s.State.Export()
    61  	c.Assert(err, jc.ErrorIsNil)
    62  
    63  	uuid := utils.MustNewUUID().String()
    64  	in := newModel(out, uuid, "new")
    65  
    66  	newModel, newSt, err := s.State.Import(in)
    67  	c.Assert(err, jc.ErrorIsNil)
    68  	// add the cleanup here to close the model.
    69  	s.AddCleanup(func(c *gc.C) {
    70  		c.Check(newSt.Close(), jc.ErrorIsNil)
    71  	})
    72  	return newModel, newSt
    73  }
    74  
    75  func (s *MigrationImportSuite) assertAnnotations(c *gc.C, newSt *state.State, entity state.GlobalEntity) {
    76  	annotations, err := newSt.Annotations(entity)
    77  	c.Assert(err, jc.ErrorIsNil)
    78  	c.Assert(annotations, jc.DeepEquals, testAnnotations)
    79  }
    80  
    81  func (s *MigrationImportSuite) TestNewModel(c *gc.C) {
    82  	cons := constraints.MustParse("arch=amd64 mem=8G")
    83  	latestTools := version.MustParse("2.0.1")
    84  	s.setLatestTools(c, latestTools)
    85  	c.Assert(s.State.SetModelConstraints(cons), jc.ErrorIsNil)
    86  	machineSeq := s.setRandSequenceValue(c, "machine")
    87  	fooSeq := s.setRandSequenceValue(c, "application-foo")
    88  	s.State.SwitchBlockOn(state.ChangeBlock, "locked down")
    89  
    90  	original, err := s.State.Model()
    91  	c.Assert(err, jc.ErrorIsNil)
    92  
    93  	err = s.State.SetAnnotations(original, testAnnotations)
    94  	c.Assert(err, jc.ErrorIsNil)
    95  
    96  	out, err := s.State.Export()
    97  	c.Assert(err, jc.ErrorIsNil)
    98  
    99  	uuid := utils.MustNewUUID().String()
   100  	in := newModel(out, uuid, "new")
   101  
   102  	newModel, newSt, err := s.State.Import(in)
   103  	c.Assert(err, jc.ErrorIsNil)
   104  	defer newSt.Close()
   105  
   106  	c.Assert(newModel.Owner(), gc.Equals, original.Owner())
   107  	c.Assert(newModel.LatestToolsVersion(), gc.Equals, latestTools)
   108  	c.Assert(newModel.MigrationMode(), gc.Equals, state.MigrationModeImporting)
   109  	s.assertAnnotations(c, newSt, newModel)
   110  
   111  	originalConfig, err := original.Config()
   112  	c.Assert(err, jc.ErrorIsNil)
   113  	originalAttrs := originalConfig.AllAttrs()
   114  
   115  	newConfig, err := newModel.Config()
   116  	c.Assert(err, jc.ErrorIsNil)
   117  	newAttrs := newConfig.AllAttrs()
   118  
   119  	c.Assert(newAttrs["uuid"], gc.Equals, uuid)
   120  	c.Assert(newAttrs["name"], gc.Equals, "new")
   121  
   122  	// Now drop the uuid and name and the rest of the attributes should match.
   123  	delete(newAttrs, "uuid")
   124  	delete(newAttrs, "name")
   125  	delete(originalAttrs, "uuid")
   126  	delete(originalAttrs, "name")
   127  	c.Assert(newAttrs, jc.DeepEquals, originalAttrs)
   128  
   129  	newCons, err := newSt.ModelConstraints()
   130  	c.Assert(err, jc.ErrorIsNil)
   131  	// Can't test the constraints directly, so go through the string repr.
   132  	c.Assert(newCons.String(), gc.Equals, cons.String())
   133  
   134  	seq, err := state.Sequence(newSt, "machine")
   135  	c.Assert(err, jc.ErrorIsNil)
   136  	c.Assert(seq, gc.Equals, machineSeq)
   137  	seq, err = state.Sequence(newSt, "application-foo")
   138  	c.Assert(err, jc.ErrorIsNil)
   139  	c.Assert(seq, gc.Equals, fooSeq)
   140  
   141  	blocks, err := newSt.AllBlocks()
   142  	c.Assert(err, jc.ErrorIsNil)
   143  	c.Assert(blocks, gc.HasLen, 1)
   144  	c.Assert(blocks[0].Type(), gc.Equals, state.ChangeBlock)
   145  	c.Assert(blocks[0].Message(), gc.Equals, "locked down")
   146  }
   147  
   148  func (s *MigrationImportSuite) newModelUser(c *gc.C, name string, readOnly bool, lastConnection time.Time) permission.UserAccess {
   149  	access := permission.AdminAccess
   150  	if readOnly {
   151  		access = permission.ReadAccess
   152  	}
   153  	user, err := s.State.AddModelUser(s.State.ModelUUID(), state.UserAccessSpec{
   154  		User:      names.NewUserTag(name),
   155  		CreatedBy: s.Owner,
   156  		Access:    access,
   157  	})
   158  	c.Assert(err, jc.ErrorIsNil)
   159  	if !lastConnection.IsZero() {
   160  		err = state.UpdateModelUserLastConnection(s.State, user, lastConnection)
   161  		c.Assert(err, jc.ErrorIsNil)
   162  	}
   163  	return user
   164  }
   165  
   166  func (s *MigrationImportSuite) AssertUserEqual(c *gc.C, newUser, oldUser permission.UserAccess) {
   167  	c.Assert(newUser.UserName, gc.Equals, oldUser.UserName)
   168  	c.Assert(newUser.DisplayName, gc.Equals, oldUser.DisplayName)
   169  	c.Assert(newUser.CreatedBy, gc.Equals, oldUser.CreatedBy)
   170  	c.Assert(newUser.DateCreated, gc.Equals, oldUser.DateCreated)
   171  	c.Assert(newUser.Access, gc.Equals, newUser.Access)
   172  
   173  	connTime, err := s.State.LastModelConnection(oldUser.UserTag)
   174  	if state.IsNeverConnectedError(err) {
   175  		_, err := s.State.LastModelConnection(newUser.UserTag)
   176  		// The new user should also return an error for last connection.
   177  		c.Assert(err, jc.Satisfies, state.IsNeverConnectedError)
   178  	} else {
   179  		c.Assert(err, jc.ErrorIsNil)
   180  		newTime, err := s.State.LastModelConnection(newUser.UserTag)
   181  		c.Assert(err, jc.ErrorIsNil)
   182  		c.Assert(newTime, gc.Equals, connTime)
   183  	}
   184  }
   185  
   186  func (s *MigrationImportSuite) TestModelUsers(c *gc.C) {
   187  	// To be sure with this test, we create three env users, and remove
   188  	// the owner.
   189  	err := s.State.RemoveUserAccess(s.Owner, s.modelTag)
   190  	c.Assert(err, jc.ErrorIsNil)
   191  
   192  	lastConnection := s.State.NowToTheSecond()
   193  
   194  	bravo := s.newModelUser(c, "bravo@external", false, lastConnection)
   195  	charlie := s.newModelUser(c, "charlie@external", true, lastConnection)
   196  	delta := s.newModelUser(c, "delta@external", true, coretesting.ZeroTime())
   197  
   198  	newModel, newSt := s.importModel(c)
   199  
   200  	// Check the import values of the users.
   201  	for _, user := range []permission.UserAccess{bravo, charlie, delta} {
   202  		newUser, err := newSt.UserAccess(user.UserTag, newModel.Tag())
   203  		c.Assert(err, jc.ErrorIsNil)
   204  		s.AssertUserEqual(c, newUser, user)
   205  	}
   206  
   207  	// Also make sure that there aren't any more.
   208  	allUsers, err := newModel.Users()
   209  	c.Assert(err, jc.ErrorIsNil)
   210  	c.Assert(allUsers, gc.HasLen, 3)
   211  }
   212  
   213  func (s *MigrationImportSuite) AssertMachineEqual(c *gc.C, newMachine, oldMachine *state.Machine) {
   214  	c.Assert(newMachine.Id(), gc.Equals, oldMachine.Id())
   215  	c.Assert(newMachine.Principals(), jc.DeepEquals, oldMachine.Principals())
   216  	c.Assert(newMachine.Series(), gc.Equals, oldMachine.Series())
   217  	c.Assert(newMachine.ContainerType(), gc.Equals, oldMachine.ContainerType())
   218  	newHardware, err := newMachine.HardwareCharacteristics()
   219  	c.Assert(err, jc.ErrorIsNil)
   220  	oldHardware, err := oldMachine.HardwareCharacteristics()
   221  	c.Assert(err, jc.ErrorIsNil)
   222  	c.Assert(newHardware, jc.DeepEquals, oldHardware)
   223  	c.Assert(newMachine.Jobs(), jc.DeepEquals, oldMachine.Jobs())
   224  	c.Assert(newMachine.Life(), gc.Equals, oldMachine.Life())
   225  	newTools, err := newMachine.AgentTools()
   226  	c.Assert(err, jc.ErrorIsNil)
   227  	oldTools, err := oldMachine.AgentTools()
   228  	c.Assert(err, jc.ErrorIsNil)
   229  	c.Assert(newTools, jc.DeepEquals, oldTools)
   230  }
   231  
   232  func (s *MigrationImportSuite) TestMachines(c *gc.C) {
   233  	// Let's add a machine with an LXC container.
   234  	cons := constraints.MustParse("arch=amd64 mem=8G")
   235  	machine1 := s.Factory.MakeMachine(c, &factory.MachineParams{
   236  		Constraints: cons,
   237  	})
   238  	err := s.State.SetAnnotations(machine1, testAnnotations)
   239  	c.Assert(err, jc.ErrorIsNil)
   240  	s.primeStatusHistory(c, machine1, status.Started, 5)
   241  
   242  	// machine1 should have some instance data.
   243  	hardware, err := machine1.HardwareCharacteristics()
   244  	c.Assert(err, jc.ErrorIsNil)
   245  	c.Assert(hardware, gc.NotNil)
   246  
   247  	_ = s.Factory.MakeMachineNested(c, machine1.Id(), nil)
   248  
   249  	allMachines, err := s.State.AllMachines()
   250  	c.Assert(err, jc.ErrorIsNil)
   251  	c.Assert(allMachines, gc.HasLen, 2)
   252  
   253  	_, newSt := s.importModel(c)
   254  
   255  	importedMachines, err := newSt.AllMachines()
   256  	c.Assert(err, jc.ErrorIsNil)
   257  	c.Assert(importedMachines, gc.HasLen, 2)
   258  
   259  	// AllMachines returns the machines in the same order, yay us.
   260  	for i, newMachine := range importedMachines {
   261  		s.AssertMachineEqual(c, newMachine, allMachines[i])
   262  	}
   263  
   264  	// And a few extra checks.
   265  	parent := importedMachines[0]
   266  	container := importedMachines[1]
   267  	containers, err := parent.Containers()
   268  	c.Assert(err, jc.ErrorIsNil)
   269  	c.Assert(containers, jc.DeepEquals, []string{container.Id()})
   270  	parentId, isContainer := container.ParentId()
   271  	c.Assert(parentId, gc.Equals, parent.Id())
   272  	c.Assert(isContainer, jc.IsTrue)
   273  
   274  	s.assertAnnotations(c, newSt, parent)
   275  	s.checkStatusHistory(c, machine1, parent, 5)
   276  
   277  	newCons, err := parent.Constraints()
   278  	c.Assert(err, jc.ErrorIsNil)
   279  	// Can't test the constraints directly, so go through the string repr.
   280  	c.Assert(newCons.String(), gc.Equals, cons.String())
   281  }
   282  
   283  func (s *MigrationImportSuite) TestMachineDevices(c *gc.C) {
   284  	machine := s.Factory.MakeMachine(c, nil)
   285  	// Create two devices, first with all fields set, second just to show that
   286  	// we do both.
   287  	sda := state.BlockDeviceInfo{
   288  		DeviceName:     "sda",
   289  		DeviceLinks:    []string{"some", "data"},
   290  		Label:          "sda-label",
   291  		UUID:           "some-uuid",
   292  		HardwareId:     "magic",
   293  		BusAddress:     "bus stop",
   294  		Size:           16 * 1024 * 1024 * 1024,
   295  		FilesystemType: "ext4",
   296  		InUse:          true,
   297  		MountPoint:     "/",
   298  	}
   299  	sdb := state.BlockDeviceInfo{DeviceName: "sdb", MountPoint: "/var/lib/lxd"}
   300  	err := machine.SetMachineBlockDevices(sda, sdb)
   301  	c.Assert(err, jc.ErrorIsNil)
   302  
   303  	_, newSt := s.importModel(c)
   304  
   305  	imported, err := newSt.Machine(machine.Id())
   306  	c.Assert(err, jc.ErrorIsNil)
   307  
   308  	devices, err := newSt.BlockDevices(imported.MachineTag())
   309  	c.Assert(err, jc.ErrorIsNil)
   310  
   311  	c.Check(devices, jc.DeepEquals, []state.BlockDeviceInfo{sda, sdb})
   312  }
   313  
   314  func (s *MigrationImportSuite) TestApplications(c *gc.C) {
   315  	// Add a application with both settings and leadership settings.
   316  	cons := constraints.MustParse("arch=amd64 mem=8G")
   317  	application := s.Factory.MakeApplication(c, &factory.ApplicationParams{
   318  		Settings: map[string]interface{}{
   319  			"foo": "bar",
   320  		},
   321  		Constraints: cons,
   322  	})
   323  	err := application.UpdateLeaderSettings(&goodToken{}, map[string]string{
   324  		"leader": "true",
   325  	})
   326  	c.Assert(err, jc.ErrorIsNil)
   327  	err = application.SetMetricCredentials([]byte("sekrit"))
   328  	c.Assert(err, jc.ErrorIsNil)
   329  	// Expose the application.
   330  	c.Assert(application.SetExposed(), jc.ErrorIsNil)
   331  	err = s.State.SetAnnotations(application, testAnnotations)
   332  	c.Assert(err, jc.ErrorIsNil)
   333  	s.primeStatusHistory(c, application, status.Active, 5)
   334  
   335  	allApplications, err := s.State.AllApplications()
   336  	c.Assert(err, jc.ErrorIsNil)
   337  	c.Assert(allApplications, gc.HasLen, 1)
   338  
   339  	_, newSt := s.importModel(c)
   340  
   341  	importedApplications, err := newSt.AllApplications()
   342  	c.Assert(err, jc.ErrorIsNil)
   343  	c.Assert(importedApplications, gc.HasLen, 1)
   344  
   345  	exported := allApplications[0]
   346  	imported := importedApplications[0]
   347  
   348  	c.Assert(imported.ApplicationTag(), gc.Equals, exported.ApplicationTag())
   349  	c.Assert(imported.Series(), gc.Equals, exported.Series())
   350  	c.Assert(imported.IsExposed(), gc.Equals, exported.IsExposed())
   351  	c.Assert(imported.MetricCredentials(), jc.DeepEquals, exported.MetricCredentials())
   352  
   353  	exportedConfig, err := exported.ConfigSettings()
   354  	c.Assert(err, jc.ErrorIsNil)
   355  	importedConfig, err := imported.ConfigSettings()
   356  	c.Assert(err, jc.ErrorIsNil)
   357  	c.Assert(importedConfig, jc.DeepEquals, exportedConfig)
   358  
   359  	exportedLeaderSettings, err := exported.LeaderSettings()
   360  	c.Assert(err, jc.ErrorIsNil)
   361  	importedLeaderSettings, err := imported.LeaderSettings()
   362  	c.Assert(err, jc.ErrorIsNil)
   363  	c.Assert(importedLeaderSettings, jc.DeepEquals, exportedLeaderSettings)
   364  
   365  	s.assertAnnotations(c, newSt, imported)
   366  	s.checkStatusHistory(c, application, imported, 5)
   367  
   368  	newCons, err := imported.Constraints()
   369  	c.Assert(err, jc.ErrorIsNil)
   370  	// Can't test the constraints directly, so go through the string repr.
   371  	c.Assert(newCons.String(), gc.Equals, cons.String())
   372  }
   373  
   374  func (s *MigrationImportSuite) TestApplicationLeaders(c *gc.C) {
   375  	s.makeApplicationWithLeader(c, "mysql", 2, 1)
   376  	s.makeApplicationWithLeader(c, "wordpress", 4, 2)
   377  
   378  	_, newSt := s.importModel(c)
   379  
   380  	leaders := make(map[string]string)
   381  	leases, err := state.LeadershipLeases(newSt)
   382  	c.Assert(err, jc.ErrorIsNil)
   383  	for key, value := range leases {
   384  		leaders[key] = value.Holder
   385  	}
   386  	c.Assert(leaders, jc.DeepEquals, map[string]string{
   387  		"mysql":     "mysql/1",
   388  		"wordpress": "wordpress/2",
   389  	})
   390  }
   391  
   392  func (s *MigrationImportSuite) TestUnits(c *gc.C) {
   393  	s.assertUnitsMigrated(c, constraints.MustParse("arch=amd64 mem=8G"))
   394  }
   395  
   396  func (s *MigrationImportSuite) TestUnitsWithVirtConstraint(c *gc.C) {
   397  	s.assertUnitsMigrated(c, constraints.MustParse("arch=amd64 mem=8G virt-type=kvm"))
   398  }
   399  
   400  func (s *MigrationImportSuite) assertUnitsMigrated(c *gc.C, cons constraints.Value) {
   401  	exported, pwd := s.Factory.MakeUnitReturningPassword(c, &factory.UnitParams{
   402  		Constraints: cons,
   403  	})
   404  	err := exported.SetMeterStatus("GREEN", "some info")
   405  	c.Assert(err, jc.ErrorIsNil)
   406  	err = exported.SetWorkloadVersion("amethyst")
   407  	c.Assert(err, jc.ErrorIsNil)
   408  	err = s.State.SetAnnotations(exported, testAnnotations)
   409  	c.Assert(err, jc.ErrorIsNil)
   410  	s.primeStatusHistory(c, exported, status.Active, 5)
   411  	s.primeStatusHistory(c, exported.Agent(), status.Idle, 5)
   412  
   413  	_, newSt := s.importModel(c)
   414  
   415  	importedApplications, err := newSt.AllApplications()
   416  	c.Assert(err, jc.ErrorIsNil)
   417  	c.Assert(importedApplications, gc.HasLen, 1)
   418  
   419  	importedUnits, err := importedApplications[0].AllUnits()
   420  	c.Assert(err, jc.ErrorIsNil)
   421  	c.Assert(importedUnits, gc.HasLen, 1)
   422  	imported := importedUnits[0]
   423  
   424  	c.Assert(imported.UnitTag(), gc.Equals, exported.UnitTag())
   425  	c.Assert(imported.PasswordValid(pwd), jc.IsTrue)
   426  	version, err := imported.WorkloadVersion()
   427  	c.Assert(err, jc.ErrorIsNil)
   428  	c.Assert(version, gc.Equals, "amethyst")
   429  
   430  	exportedMachineId, err := exported.AssignedMachineId()
   431  	c.Assert(err, jc.ErrorIsNil)
   432  	importedMachineId, err := imported.AssignedMachineId()
   433  	c.Assert(err, jc.ErrorIsNil)
   434  	c.Assert(importedMachineId, gc.Equals, exportedMachineId)
   435  
   436  	// Confirm machine Principals are set.
   437  	exportedMachine, err := s.State.Machine(exportedMachineId)
   438  	c.Assert(err, jc.ErrorIsNil)
   439  	importedMachine, err := newSt.Machine(importedMachineId)
   440  	c.Assert(err, jc.ErrorIsNil)
   441  	s.AssertMachineEqual(c, importedMachine, exportedMachine)
   442  
   443  	meterStatus, err := imported.GetMeterStatus()
   444  	c.Assert(err, jc.ErrorIsNil)
   445  	c.Assert(meterStatus, gc.Equals, state.MeterStatus{state.MeterGreen, "some info"})
   446  	s.assertAnnotations(c, newSt, imported)
   447  	s.checkStatusHistory(c, exported, imported, 5)
   448  	s.checkStatusHistory(c, exported.Agent(), imported.Agent(), 5)
   449  	s.checkStatusHistory(c, exported.WorkloadVersionHistory(), imported.WorkloadVersionHistory(), 1)
   450  
   451  	newCons, err := imported.Constraints()
   452  	c.Assert(err, jc.ErrorIsNil)
   453  	// Can't test the constraints directly, so go through the string repr.
   454  	c.Assert(newCons.String(), gc.Equals, cons.String())
   455  }
   456  
   457  func (s *MigrationImportSuite) TestRelations(c *gc.C) {
   458  	wordpress := state.AddTestingService(c, s.State, "wordpress", state.AddTestingCharm(c, s.State, "wordpress"))
   459  	state.AddTestingService(c, s.State, "mysql", state.AddTestingCharm(c, s.State, "mysql"))
   460  	eps, err := s.State.InferEndpoints("mysql", "wordpress")
   461  	c.Assert(err, jc.ErrorIsNil)
   462  	rel, err := s.State.AddRelation(eps...)
   463  	c.Assert(err, jc.ErrorIsNil)
   464  	wordpress_0 := s.Factory.MakeUnit(c, &factory.UnitParams{Application: wordpress})
   465  
   466  	ru, err := rel.Unit(wordpress_0)
   467  	c.Assert(err, jc.ErrorIsNil)
   468  	relSettings := map[string]interface{}{
   469  		"name": "wordpress/0",
   470  	}
   471  	err = ru.EnterScope(relSettings)
   472  	c.Assert(err, jc.ErrorIsNil)
   473  
   474  	_, newSt := s.importModel(c)
   475  
   476  	newWordpress, err := newSt.Application("wordpress")
   477  	c.Assert(err, jc.ErrorIsNil)
   478  	c.Assert(state.RelationCount(newWordpress), gc.Equals, 1)
   479  	rels, err := newWordpress.Relations()
   480  	c.Assert(err, jc.ErrorIsNil)
   481  	c.Assert(rels, gc.HasLen, 1)
   482  	units, err := newWordpress.AllUnits()
   483  	c.Assert(err, jc.ErrorIsNil)
   484  	c.Assert(units, gc.HasLen, 1)
   485  
   486  	ru, err = rels[0].Unit(units[0])
   487  	c.Assert(err, jc.ErrorIsNil)
   488  
   489  	settings, err := ru.Settings()
   490  	c.Assert(err, jc.ErrorIsNil)
   491  	c.Assert(settings.Map(), gc.DeepEquals, relSettings)
   492  }
   493  
   494  func (s *MigrationImportSuite) TestUnitsOpenPorts(c *gc.C) {
   495  	unit := s.Factory.MakeUnit(c, nil)
   496  	err := unit.OpenPorts("tcp", 1234, 2345)
   497  	c.Assert(err, jc.ErrorIsNil)
   498  
   499  	_, newSt := s.importModel(c)
   500  
   501  	// Even though the opened ports document is stored with the
   502  	// machine, the only way to easily access it is through the units.
   503  	imported, err := newSt.Unit(unit.Name())
   504  	c.Assert(err, jc.ErrorIsNil)
   505  
   506  	ports, err := imported.OpenedPorts()
   507  	c.Assert(err, jc.ErrorIsNil)
   508  	c.Assert(ports, gc.HasLen, 1)
   509  	c.Assert(ports[0], gc.Equals, network.PortRange{
   510  		FromPort: 1234,
   511  		ToPort:   2345,
   512  		Protocol: "tcp",
   513  	})
   514  }
   515  
   516  func (s *MigrationImportSuite) TestSpaces(c *gc.C) {
   517  	space := s.Factory.MakeSpace(c, &factory.SpaceParams{
   518  		Name: "one", ProviderID: network.Id("provider"), IsPublic: true})
   519  
   520  	_, newSt := s.importModel(c)
   521  
   522  	imported, err := newSt.Space(space.Name())
   523  	c.Assert(err, jc.ErrorIsNil)
   524  
   525  	c.Assert(imported.Name(), gc.Equals, space.Name())
   526  	c.Assert(imported.ProviderId(), gc.Equals, space.ProviderId())
   527  	c.Assert(imported.IsPublic(), gc.Equals, space.IsPublic())
   528  }
   529  
   530  func (s *MigrationImportSuite) TestDestroyEmptyModel(c *gc.C) {
   531  	newModel, _ := s.importModel(c)
   532  	s.assertDestroyModelAdvancesLife(c, newModel, state.Dead)
   533  }
   534  
   535  func (s *MigrationImportSuite) TestDestroyModelWithMachine(c *gc.C) {
   536  	s.Factory.MakeMachine(c, nil)
   537  	newModel, _ := s.importModel(c)
   538  	s.assertDestroyModelAdvancesLife(c, newModel, state.Dying)
   539  }
   540  
   541  func (s *MigrationImportSuite) TestDestroyModelWithApplication(c *gc.C) {
   542  	s.Factory.MakeApplication(c, nil)
   543  	newModel, _ := s.importModel(c)
   544  	s.assertDestroyModelAdvancesLife(c, newModel, state.Dying)
   545  }
   546  
   547  func (s *MigrationImportSuite) assertDestroyModelAdvancesLife(c *gc.C, m *state.Model, life state.Life) {
   548  	err := m.Destroy()
   549  	c.Assert(err, jc.ErrorIsNil)
   550  	err = m.Refresh()
   551  	c.Assert(err, jc.ErrorIsNil)
   552  	c.Assert(m.Life(), gc.Equals, life)
   553  }
   554  
   555  func (s *MigrationImportSuite) TestLinkLayerDevice(c *gc.C) {
   556  	machine := s.Factory.MakeMachine(c, &factory.MachineParams{
   557  		Constraints: constraints.MustParse("arch=amd64 mem=8G"),
   558  	})
   559  	deviceArgs := state.LinkLayerDeviceArgs{
   560  		Name: "foo",
   561  		Type: state.EthernetDevice,
   562  	}
   563  	err := machine.SetLinkLayerDevices(deviceArgs)
   564  	c.Assert(err, jc.ErrorIsNil)
   565  	_, newSt := s.importModel(c)
   566  
   567  	devices, err := newSt.AllLinkLayerDevices()
   568  	c.Assert(err, jc.ErrorIsNil)
   569  	c.Assert(devices, gc.HasLen, 1)
   570  	device := devices[0]
   571  	c.Assert(device.Name(), gc.Equals, "foo")
   572  	c.Assert(device.Type(), gc.Equals, state.EthernetDevice)
   573  }
   574  
   575  func (s *MigrationImportSuite) TestLinkLayerDeviceMigratesReferences(c *gc.C) {
   576  	machine := s.Factory.MakeMachine(c, &factory.MachineParams{
   577  		Constraints: constraints.MustParse("arch=amd64 mem=8G"),
   578  	})
   579  	machine2 := s.Factory.MakeMachineNested(c, machine.Id(), &factory.MachineParams{
   580  		Constraints: constraints.MustParse("arch=amd64 mem=8G"),
   581  	})
   582  	deviceArgs := []state.LinkLayerDeviceArgs{{
   583  		Name: "foo",
   584  		Type: state.BridgeDevice,
   585  	}, {
   586  		Name:       "bar",
   587  		ParentName: "foo",
   588  		Type:       state.EthernetDevice,
   589  	}}
   590  	for _, args := range deviceArgs {
   591  		err := machine.SetLinkLayerDevices(args)
   592  		c.Assert(err, jc.ErrorIsNil)
   593  	}
   594  	machine2DeviceArgs := state.LinkLayerDeviceArgs{
   595  		Name:       "baz",
   596  		ParentName: fmt.Sprintf("m#%v#d#foo", machine.Id()),
   597  		Type:       state.EthernetDevice,
   598  	}
   599  	err := machine2.SetLinkLayerDevices(machine2DeviceArgs)
   600  	c.Assert(err, jc.ErrorIsNil)
   601  	_, newSt := s.importModel(c)
   602  
   603  	devices, err := newSt.AllLinkLayerDevices()
   604  	c.Assert(err, jc.ErrorIsNil)
   605  	c.Assert(devices, gc.HasLen, 3)
   606  	var parent *state.LinkLayerDevice
   607  	others := []*state.LinkLayerDevice{}
   608  	for _, device := range devices {
   609  		if device.Name() == "foo" {
   610  			parent = device
   611  		} else {
   612  			others = append(others, device)
   613  		}
   614  	}
   615  	// Assert we found the parent.
   616  	c.Assert(others, gc.HasLen, 2)
   617  	err = parent.Remove()
   618  	c.Assert(err, gc.ErrorMatches, `.*parent device "foo" has 2 children.*`)
   619  	err = others[0].Remove()
   620  	c.Assert(err, jc.ErrorIsNil)
   621  	err = parent.Remove()
   622  	c.Assert(err, gc.ErrorMatches, `.*parent device "foo" has 1 children.*`)
   623  	err = others[1].Remove()
   624  	c.Assert(err, jc.ErrorIsNil)
   625  	err = parent.Remove()
   626  	c.Assert(err, jc.ErrorIsNil)
   627  }
   628  
   629  func (s *MigrationImportSuite) TestSubnets(c *gc.C) {
   630  	original, err := s.State.AddSubnet(state.SubnetInfo{
   631  		CIDR:             "10.0.0.0/24",
   632  		ProviderId:       network.Id("foo"),
   633  		VLANTag:          64,
   634  		AvailabilityZone: "bar",
   635  		SpaceName:        "bam",
   636  	})
   637  	c.Assert(err, jc.ErrorIsNil)
   638  	_, err = s.State.AddSpace("bam", "", nil, true)
   639  	c.Assert(err, jc.ErrorIsNil)
   640  
   641  	_, newSt := s.importModel(c)
   642  
   643  	subnet, err := newSt.Subnet(original.CIDR())
   644  	c.Assert(err, jc.ErrorIsNil)
   645  
   646  	c.Assert(subnet.CIDR(), gc.Equals, "10.0.0.0/24")
   647  	c.Assert(subnet.ProviderId(), gc.Equals, network.Id("foo"))
   648  	c.Assert(subnet.VLANTag(), gc.Equals, 64)
   649  	c.Assert(subnet.AvailabilityZone(), gc.Equals, "bar")
   650  	c.Assert(subnet.SpaceName(), gc.Equals, "bam")
   651  }
   652  
   653  func (s *MigrationImportSuite) TestIPAddress(c *gc.C) {
   654  	machine := s.Factory.MakeMachine(c, &factory.MachineParams{
   655  		Constraints: constraints.MustParse("arch=amd64 mem=8G"),
   656  	})
   657  	_, err := s.State.AddSubnet(state.SubnetInfo{CIDR: "0.1.2.0/24"})
   658  	c.Assert(err, jc.ErrorIsNil)
   659  	deviceArgs := state.LinkLayerDeviceArgs{
   660  		Name: "foo",
   661  		Type: state.EthernetDevice,
   662  	}
   663  	err = machine.SetLinkLayerDevices(deviceArgs)
   664  	c.Assert(err, jc.ErrorIsNil)
   665  	args := state.LinkLayerDeviceAddress{
   666  		DeviceName:       "foo",
   667  		ConfigMethod:     state.StaticAddress,
   668  		CIDRAddress:      "0.1.2.3/24",
   669  		ProviderID:       "bar",
   670  		DNSServers:       []string{"bam", "mam"},
   671  		DNSSearchDomains: []string{"weeee"},
   672  		GatewayAddress:   "0.1.2.1",
   673  	}
   674  	err = machine.SetDevicesAddresses(args)
   675  	c.Assert(err, jc.ErrorIsNil)
   676  
   677  	_, newSt := s.importModel(c)
   678  
   679  	addresses, _ := newSt.AllIPAddresses()
   680  	c.Assert(addresses, gc.HasLen, 1)
   681  	c.Assert(err, jc.ErrorIsNil)
   682  	addr := addresses[0]
   683  	c.Assert(addr.Value(), gc.Equals, "0.1.2.3")
   684  	c.Assert(addr.MachineID(), gc.Equals, machine.Id())
   685  	c.Assert(addr.DeviceName(), gc.Equals, "foo")
   686  	c.Assert(addr.ConfigMethod(), gc.Equals, state.StaticAddress)
   687  	c.Assert(addr.SubnetCIDR(), gc.Equals, "0.1.2.0/24")
   688  	c.Assert(addr.ProviderID(), gc.Equals, network.Id("bar"))
   689  	c.Assert(addr.DNSServers(), jc.DeepEquals, []string{"bam", "mam"})
   690  	c.Assert(addr.DNSSearchDomains(), jc.DeepEquals, []string{"weeee"})
   691  	c.Assert(addr.GatewayAddress(), gc.Equals, "0.1.2.1")
   692  }
   693  
   694  func (s *MigrationImportSuite) TestSSHHostKey(c *gc.C) {
   695  	machine := s.Factory.MakeMachine(c, &factory.MachineParams{
   696  		Constraints: constraints.MustParse("arch=amd64 mem=8G"),
   697  	})
   698  	err := s.State.SetSSHHostKeys(machine.MachineTag(), []string{"bam", "mam"})
   699  	c.Assert(err, jc.ErrorIsNil)
   700  
   701  	_, newSt := s.importModel(c)
   702  
   703  	machine2, err := newSt.Machine(machine.Id())
   704  	c.Assert(err, jc.ErrorIsNil)
   705  	keys, err := newSt.GetSSHHostKeys(machine2.MachineTag())
   706  	c.Assert(err, jc.ErrorIsNil)
   707  	c.Assert(keys, jc.DeepEquals, state.SSHHostKeys{"bam", "mam"})
   708  }
   709  
   710  func (s *MigrationImportSuite) TestCloudImageMetadata(c *gc.C) {
   711  	storageSize := uint64(3)
   712  	attrs := cloudimagemetadata.MetadataAttributes{
   713  		Stream:          "stream",
   714  		Region:          "region-test",
   715  		Version:         "14.04",
   716  		Series:          "trusty",
   717  		Arch:            "arch",
   718  		VirtType:        "virtType-test",
   719  		RootStorageType: "rootStorageType-test",
   720  		RootStorageSize: &storageSize,
   721  		Source:          "test",
   722  	}
   723  	metadata := []cloudimagemetadata.Metadata{{attrs, 2, "1", 2}}
   724  
   725  	err := s.State.CloudImageMetadataStorage.SaveMetadata(metadata)
   726  	c.Assert(err, jc.ErrorIsNil)
   727  
   728  	_, newSt := s.importModel(c)
   729  	defer func() {
   730  		c.Assert(newSt.Close(), jc.ErrorIsNil)
   731  	}()
   732  
   733  	images, err := s.State.CloudImageMetadataStorage.AllCloudImageMetadata()
   734  	c.Assert(err, jc.ErrorIsNil)
   735  	c.Assert(images, gc.HasLen, 1)
   736  	image := images[0]
   737  	c.Check(image.Stream, gc.Equals, "stream")
   738  	c.Check(image.Region, gc.Equals, "region-test")
   739  	c.Check(image.Version, gc.Equals, "14.04")
   740  	c.Check(image.Arch, gc.Equals, "arch")
   741  	c.Check(image.VirtType, gc.Equals, "virtType-test")
   742  	c.Check(image.RootStorageType, gc.Equals, "rootStorageType-test")
   743  	c.Check(*image.RootStorageSize, gc.Equals, uint64(3))
   744  	c.Check(image.Source, gc.Equals, "test")
   745  	c.Check(image.Priority, gc.Equals, 2)
   746  	c.Check(image.ImageId, gc.Equals, "1")
   747  	c.Check(image.DateCreated, gc.Equals, int64(2))
   748  }
   749  
   750  func (s *MigrationImportSuite) TestAction(c *gc.C) {
   751  	machine := s.Factory.MakeMachine(c, &factory.MachineParams{
   752  		Constraints: constraints.MustParse("arch=amd64 mem=8G"),
   753  	})
   754  	_, err := s.State.EnqueueAction(machine.MachineTag(), "foo", nil)
   755  	c.Assert(err, jc.ErrorIsNil)
   756  
   757  	_, newSt := s.importModel(c)
   758  	defer func() {
   759  		c.Assert(newSt.Close(), jc.ErrorIsNil)
   760  	}()
   761  
   762  	actions, _ := newSt.AllActions()
   763  	c.Assert(actions, gc.HasLen, 1)
   764  	action := actions[0]
   765  	c.Check(action.Receiver(), gc.Equals, machine.Id())
   766  	c.Check(action.Name(), gc.Equals, "foo")
   767  	c.Check(action.Status(), gc.Equals, state.ActionPending)
   768  }
   769  
   770  func (s *MigrationImportSuite) TestVolumes(c *gc.C) {
   771  	machine := s.Factory.MakeMachine(c, &factory.MachineParams{
   772  		Volumes: []state.MachineVolumeParams{{
   773  			Volume:     state.VolumeParams{Size: 1234},
   774  			Attachment: state.VolumeAttachmentParams{ReadOnly: true},
   775  		}, {
   776  			Volume:     state.VolumeParams{Size: 4000},
   777  			Attachment: state.VolumeAttachmentParams{ReadOnly: true},
   778  		}},
   779  	})
   780  	machineTag := machine.MachineTag()
   781  
   782  	// We know that the first volume is called "0/0" - although I don't know why.
   783  	volTag := names.NewVolumeTag("0/0")
   784  	volInfo := state.VolumeInfo{
   785  		HardwareId: "magic",
   786  		Size:       1500,
   787  		Pool:       "loop",
   788  		VolumeId:   "volume id",
   789  		Persistent: true,
   790  	}
   791  	err := s.State.SetVolumeInfo(volTag, volInfo)
   792  	c.Assert(err, jc.ErrorIsNil)
   793  	volAttachmentInfo := state.VolumeAttachmentInfo{
   794  		DeviceName: "device name",
   795  		DeviceLink: "device link",
   796  		BusAddress: "bus address",
   797  		ReadOnly:   true,
   798  	}
   799  	err = s.State.SetVolumeAttachmentInfo(machineTag, volTag, volAttachmentInfo)
   800  	c.Assert(err, jc.ErrorIsNil)
   801  
   802  	_, newSt := s.importModel(c)
   803  
   804  	volume, err := newSt.Volume(volTag)
   805  	c.Assert(err, jc.ErrorIsNil)
   806  
   807  	// TODO: check status
   808  	// TODO: check storage instance
   809  	info, err := volume.Info()
   810  	c.Assert(err, jc.ErrorIsNil)
   811  	c.Check(info, jc.DeepEquals, volInfo)
   812  
   813  	attachment, err := newSt.VolumeAttachment(machineTag, volTag)
   814  	c.Assert(err, jc.ErrorIsNil)
   815  	attInfo, err := attachment.Info()
   816  	c.Assert(err, jc.ErrorIsNil)
   817  	c.Check(attInfo, jc.DeepEquals, volAttachmentInfo)
   818  
   819  	volTag = names.NewVolumeTag("0/1")
   820  	volume, err = newSt.Volume(volTag)
   821  	c.Assert(err, jc.ErrorIsNil)
   822  
   823  	params, needsProvisioning := volume.Params()
   824  	c.Check(needsProvisioning, jc.IsTrue)
   825  	c.Check(params.Pool, gc.Equals, "loop")
   826  	c.Check(params.Size, gc.Equals, uint64(4000))
   827  
   828  	attachment, err = newSt.VolumeAttachment(machineTag, volTag)
   829  	c.Assert(err, jc.ErrorIsNil)
   830  	attParams, needsProvisioning := attachment.Params()
   831  	c.Check(needsProvisioning, jc.IsTrue)
   832  	c.Check(attParams.ReadOnly, jc.IsTrue)
   833  }
   834  
   835  func (s *MigrationImportSuite) TestFilesystems(c *gc.C) {
   836  	machine := s.Factory.MakeMachine(c, &factory.MachineParams{
   837  		Filesystems: []state.MachineFilesystemParams{{
   838  			Filesystem: state.FilesystemParams{Size: 1234},
   839  			Attachment: state.FilesystemAttachmentParams{
   840  				Location: "location",
   841  				ReadOnly: true},
   842  		}, {
   843  			Filesystem: state.FilesystemParams{Size: 4000},
   844  			Attachment: state.FilesystemAttachmentParams{
   845  				ReadOnly: true},
   846  		}},
   847  	})
   848  	machineTag := machine.MachineTag()
   849  
   850  	// We know that the first filesystem is called "0/0" as it is the first
   851  	// filesystem (filesystems use sequences), and it is bound to machine 0.
   852  	fsTag := names.NewFilesystemTag("0/0")
   853  	fsInfo := state.FilesystemInfo{
   854  		Size:         1500,
   855  		Pool:         "rootfs",
   856  		FilesystemId: "filesystem id",
   857  	}
   858  	err := s.State.SetFilesystemInfo(fsTag, fsInfo)
   859  	c.Assert(err, jc.ErrorIsNil)
   860  	fsAttachmentInfo := state.FilesystemAttachmentInfo{
   861  		MountPoint: "/mnt/foo",
   862  		ReadOnly:   true,
   863  	}
   864  	err = s.State.SetFilesystemAttachmentInfo(machineTag, fsTag, fsAttachmentInfo)
   865  	c.Assert(err, jc.ErrorIsNil)
   866  
   867  	_, newSt := s.importModel(c)
   868  
   869  	filesystem, err := newSt.Filesystem(fsTag)
   870  	c.Assert(err, jc.ErrorIsNil)
   871  
   872  	// TODO: check status
   873  	// TODO: check storage instance
   874  	info, err := filesystem.Info()
   875  	c.Assert(err, jc.ErrorIsNil)
   876  	c.Check(info, jc.DeepEquals, fsInfo)
   877  
   878  	attachment, err := newSt.FilesystemAttachment(machineTag, fsTag)
   879  	c.Assert(err, jc.ErrorIsNil)
   880  	attInfo, err := attachment.Info()
   881  	c.Assert(err, jc.ErrorIsNil)
   882  	c.Check(attInfo, jc.DeepEquals, fsAttachmentInfo)
   883  
   884  	fsTag = names.NewFilesystemTag("0/1")
   885  	filesystem, err = newSt.Filesystem(fsTag)
   886  	c.Assert(err, jc.ErrorIsNil)
   887  
   888  	params, needsProvisioning := filesystem.Params()
   889  	c.Check(needsProvisioning, jc.IsTrue)
   890  	c.Check(params.Pool, gc.Equals, "rootfs")
   891  	c.Check(params.Size, gc.Equals, uint64(4000))
   892  
   893  	attachment, err = newSt.FilesystemAttachment(machineTag, fsTag)
   894  	c.Assert(err, jc.ErrorIsNil)
   895  	attParams, needsProvisioning := attachment.Params()
   896  	c.Check(needsProvisioning, jc.IsTrue)
   897  	c.Check(attParams.ReadOnly, jc.IsTrue)
   898  }
   899  
   900  func (s *MigrationImportSuite) TestStorage(c *gc.C) {
   901  	app, u, storageTag := s.makeUnitWithStorage(c)
   902  	original, err := s.State.StorageInstance(storageTag)
   903  	c.Assert(err, jc.ErrorIsNil)
   904  	originalCount := state.StorageAttachmentCount(original)
   905  	c.Assert(originalCount, gc.Equals, 1)
   906  	originalAttachments, err := s.State.StorageAttachments(storageTag)
   907  	c.Assert(err, jc.ErrorIsNil)
   908  	c.Assert(originalAttachments, gc.HasLen, 1)
   909  	c.Assert(originalAttachments[0].Unit(), gc.Equals, u.UnitTag())
   910  	appName := app.Name()
   911  
   912  	_, newSt := s.importModel(c)
   913  
   914  	app, err = newSt.Application(appName)
   915  	c.Assert(err, jc.ErrorIsNil)
   916  	cons, err := app.StorageConstraints()
   917  	c.Assert(err, jc.ErrorIsNil)
   918  	c.Check(cons, jc.DeepEquals, map[string]state.StorageConstraints{
   919  		"data":    {Pool: "loop-pool", Size: 0x400, Count: 1},
   920  		"allecto": {Pool: "loop", Size: 0x400},
   921  	})
   922  
   923  	instance, err := newSt.StorageInstance(storageTag)
   924  	c.Assert(err, jc.ErrorIsNil)
   925  
   926  	c.Check(instance.Tag(), gc.Equals, original.Tag())
   927  	c.Check(instance.Kind(), gc.Equals, original.Kind())
   928  	c.Check(instance.Life(), gc.Equals, original.Life())
   929  	c.Check(instance.StorageName(), gc.Equals, original.StorageName())
   930  	c.Check(state.StorageAttachmentCount(instance), gc.Equals, originalCount)
   931  
   932  	attachments, err := newSt.StorageAttachments(storageTag)
   933  
   934  	c.Assert(attachments, gc.HasLen, 1)
   935  	c.Assert(attachments[0].Unit(), gc.Equals, u.UnitTag())
   936  }
   937  
   938  func (s *MigrationImportSuite) TestStoragePools(c *gc.C) {
   939  	pm := poolmanager.New(state.NewStateSettings(s.State), provider.CommonStorageProviders())
   940  	_, err := pm.Create("test-pool", provider.LoopProviderType, map[string]interface{}{
   941  		"value": 42,
   942  	})
   943  	c.Assert(err, jc.ErrorIsNil)
   944  
   945  	_, newSt := s.importModel(c)
   946  
   947  	pm = poolmanager.New(state.NewStateSettings(newSt), provider.CommonStorageProviders())
   948  	pools, err := pm.List()
   949  	c.Assert(err, jc.ErrorIsNil)
   950  	c.Assert(pools, gc.HasLen, 1)
   951  
   952  	pool := pools[0]
   953  	c.Assert(pool.Name(), gc.Equals, "test-pool")
   954  	c.Assert(pool.Provider(), gc.Equals, provider.LoopProviderType)
   955  	c.Assert(pool.Attrs(), jc.DeepEquals, map[string]interface{}{
   956  		"value": 42,
   957  	})
   958  }
   959  
   960  func (s *MigrationImportSuite) TestPayloads(c *gc.C) {
   961  	originalUnit := s.Factory.MakeUnit(c, nil)
   962  	unitID := originalUnit.UnitTag().Id()
   963  	up, err := s.State.UnitPayloads(originalUnit)
   964  	c.Assert(err, jc.ErrorIsNil)
   965  	original := payload.Payload{
   966  		PayloadClass: charm.PayloadClass{
   967  			Name: "something",
   968  			Type: "special",
   969  		},
   970  		ID:     "42",
   971  		Status: "running",
   972  		Labels: []string{"foo", "bar"},
   973  	}
   974  	err = up.Track(original)
   975  	c.Assert(err, jc.ErrorIsNil)
   976  
   977  	_, newSt := s.importModel(c)
   978  
   979  	unit, err := newSt.Unit(unitID)
   980  	c.Assert(err, jc.ErrorIsNil)
   981  
   982  	up, err = newSt.UnitPayloads(unit)
   983  	c.Assert(err, jc.ErrorIsNil)
   984  
   985  	result, err := up.List()
   986  	c.Assert(err, jc.ErrorIsNil)
   987  	c.Assert(result, gc.HasLen, 1)
   988  	c.Assert(result[0].Payload, gc.NotNil)
   989  
   990  	payload := result[0].Payload
   991  
   992  	machineID, err := unit.AssignedMachineId()
   993  	c.Check(err, jc.ErrorIsNil)
   994  	c.Check(payload.Name, gc.Equals, original.Name)
   995  	c.Check(payload.Type, gc.Equals, original.Type)
   996  	c.Check(payload.ID, gc.Equals, original.ID)
   997  	c.Check(payload.Status, gc.Equals, original.Status)
   998  	c.Check(payload.Labels, jc.DeepEquals, original.Labels)
   999  	c.Check(payload.Unit, gc.Equals, unitID)
  1000  	c.Check(payload.Machine, gc.Equals, machineID)
  1001  }
  1002  
  1003  // newModel replaces the uuid and name of the config attributes so we
  1004  // can use all the other data to validate imports. An owner and name of the
  1005  // model are unique together in a controller.
  1006  func newModel(m description.Model, uuid, name string) description.Model {
  1007  	return &mockModel{m, uuid, name}
  1008  }
  1009  
  1010  type mockModel struct {
  1011  	description.Model
  1012  	uuid string
  1013  	name string
  1014  }
  1015  
  1016  func (m *mockModel) Tag() names.ModelTag {
  1017  	return names.NewModelTag(m.uuid)
  1018  }
  1019  
  1020  func (m *mockModel) Config() map[string]interface{} {
  1021  	c := m.Model.Config()
  1022  	c["uuid"] = m.uuid
  1023  	c["name"] = m.name
  1024  	return c
  1025  }