Example #1
0
func (s *UpgradeSuite) TestAllProvisionedControllersReadyWithPreModelUUIDSchema(c *gc.C) {
	serverIdB, serverIdC := s.addControllers(c)

	machines, closer := state.GetRawCollection(s.State, state.MachinesC)
	defer closer()
	instanceData, closer := state.GetRawCollection(s.State, state.InstanceDataC)
	defer closer()

	// Add minimal machine and instanceData docs for the controllers
	// that look how these documents did before the model UUID
	// migration.
	_, err := instanceData.RemoveAll(nil)
	c.Assert(err, jc.ErrorIsNil)
	_, err = machines.RemoveAll(nil)
	c.Assert(err, jc.ErrorIsNil)

	addLegacyMachine := func(machineId string) {
		err := machines.Insert(bson.M{"_id": machineId})
		c.Assert(err, jc.ErrorIsNil)
	}
	addLegacyMachine(s.serverIdA)
	addLegacyMachine(serverIdB)
	addLegacyMachine(serverIdC)

	legacyProvision := func(machineId string) {
		err := instanceData.Insert(bson.M{"_id": machineId})
		c.Assert(err, jc.ErrorIsNil)
	}
	legacyProvision(s.serverIdA)
	legacyProvision(serverIdB)

	v111 := vers("1.1.1")
	v123 := vers("1.2.3")
	info, err := s.State.EnsureUpgradeInfo(s.serverIdA, v111, v123)
	c.Assert(err, jc.ErrorIsNil)

	assertReady := func(expect bool) {
		ok, err := info.AllProvisionedControllersReady()
		c.Assert(err, jc.ErrorIsNil)
		c.Assert(ok, gc.Equals, expect)
	}
	assertReady(false)

	info, err = s.State.EnsureUpgradeInfo(serverIdB, v111, v123)
	c.Assert(err, jc.ErrorIsNil)
	assertReady(true)

	legacyProvision(serverIdC)
	assertReady(false)

	info, err = s.State.EnsureUpgradeInfo(serverIdC, v111, v123)
	c.Assert(err, jc.ErrorIsNil)
	assertReady(true)
}
Example #2
0
func (s *sequenceSuite) checkDocCount(c *gc.C, expectedCount int) {
	coll, closer := state.GetRawCollection(s.State, "sequence")
	defer closer()
	count, err := coll.Count()
	c.Assert(err, jc.ErrorIsNil)
	c.Check(count, gc.Equals, expectedCount)
}
Example #3
0
// assertMachineStorageRefs ensures that the specified machine's set of volume
// and filesystem references corresponds exactly to the volume and filesystem
// attachments that relate to the machine.
func assertMachineStorageRefs(c *gc.C, st *state.State, m names.MachineTag) {
	machines, closer := state.GetRawCollection(st, state.MachinesC)
	defer closer()

	var doc struct {
		Volumes     []string `bson:"volumes,omitempty"`
		Filesystems []string `bson:"filesystems,omitempty"`
	}
	err := machines.FindId(state.DocID(st, m.Id())).One(&doc)
	c.Assert(err, jc.ErrorIsNil)

	have := make(set.Tags)
	for _, v := range doc.Volumes {
		have.Add(names.NewVolumeTag(v))
	}
	for _, f := range doc.Filesystems {
		have.Add(names.NewFilesystemTag(f))
	}

	expect := make(set.Tags)
	volumeAttachments, err := st.MachineVolumeAttachments(m)
	c.Assert(err, jc.ErrorIsNil)
	for _, a := range volumeAttachments {
		expect.Add(a.Volume())
	}
	filesystemAttachments, err := st.MachineFilesystemAttachments(m)
	c.Assert(err, jc.ErrorIsNil)
	for _, a := range filesystemAttachments {
		expect.Add(a.Filesystem())
	}

	c.Assert(have, jc.DeepEquals, expect)
}
Example #4
0
func (s *sequenceSuite) checkDoc(c *gc.C, envUUID, name string, value int) {
	coll, closer := state.GetRawCollection(s.State, "sequence")
	defer closer()

	docID := envUUID + ":" + name
	var doc bson.M
	err := coll.FindId(docID).One(&doc)
	c.Assert(err, jc.ErrorIsNil)
	c.Check(doc["_id"], gc.Equals, docID)
	c.Check(doc["name"], gc.Equals, name)
	c.Check(doc["env-uuid"], gc.Equals, envUUID)
	c.Check(doc["counter"], gc.Equals, value)
}
Example #5
0
func (s *CollectionsSuite) TestEnvStateCollection(c *gc.C) {
	// The machines collection requires filtering by env UUID. Set up
	// 2 environments with machines in each.
	m0 := s.Factory.MakeMachine(c, nil)
	s.Factory.MakeMachine(c, nil)
	st1 := s.Factory.MakeEnvironment(c, nil)
	defer st1.Close()
	f1 := factory.NewFactory(st1)
	otherM0 := f1.MakeMachine(c, &factory.MachineParams{Series: "trusty"})

	// Ensure that the first machine in each env have overlapping ids
	// (otherwise tests may not fail when they should)
	c.Assert(m0.Id(), gc.Equals, otherM0.Id())

	getIfaceId := func(st *state.State) bson.ObjectId {
		var doc bson.M
		coll, closer := state.GetRawCollection(st, state.NetworkInterfacesC)
		defer closer()
		err := coll.Find(bson.D{{"env-uuid", st.EnvironUUID()}}).One(&doc)
		c.Assert(err, jc.ErrorIsNil)
		return doc["_id"].(bson.ObjectId)
	}

	// Also add a network interface to test collections with ObjectId ids
	_, err := s.State.AddNetwork(state.NetworkInfo{"net1", "net1", "0.1.2.3/24", 0})
	c.Assert(err, jc.ErrorIsNil)
	_, err = m0.AddNetworkInterface(state.NetworkInterfaceInfo{
		MACAddress:    "91:de:f1:02:f6:f0",
		InterfaceName: "foo0",
		NetworkName:   "net1",
	})
	c.Assert(err, jc.ErrorIsNil)

	// Grab the document id of the just added network interface for use in tests.
	ifaceId := getIfaceId(s.State)

	// Add a network interface to the other environment to test collections that rely on the env-uuid field.
	_, err = st1.AddNetwork(state.NetworkInfo{"net2", "net2", "0.1.2.4/24", 0})
	c.Assert(err, jc.ErrorIsNil)
	_, err = otherM0.AddNetworkInterface(state.NetworkInterfaceInfo{
		MACAddress:    "91:de:f1:02:f6:f0",
		InterfaceName: "foo1",
		NetworkName:   "net2",
	})
	c.Assert(err, jc.ErrorIsNil)

	// Grab the document id of the network interface just added to the other environment for use in tests.
	otherIfaceId := getIfaceId(st1)

	machines0, closer := state.GetCollection(s.State, state.MachinesC)
	defer closer()
	machines1, closer := state.GetCollection(st1, state.MachinesC)
	defer closer()
	networkInterfaces, closer := state.GetCollection(s.State, state.NetworkInterfacesC)
	defer closer()

	machinesSnapshot := newCollectionSnapshot(c, machines0.Writeable().Underlying())
	networkInterfacesSnapshot := newCollectionSnapshot(c, networkInterfaces.Writeable().Underlying())

	c.Assert(machines0.Name(), gc.Equals, state.MachinesC)
	c.Assert(networkInterfaces.Name(), gc.Equals, state.NetworkInterfacesC)

	for i, t := range []collectionsTestCase{
		{
			label: "Count filters by env",
			test: func() (int, error) {
				return machines0.Count()
			},
			expectedCount: 2,
		},
		{
			label: "Find filters by env",
			test: func() (int, error) {
				return machines0.Find(bson.D{{"series", m0.Series()}}).Count()
			},
			expectedCount: 2,
		},
		{
			label: "Find adds env UUID when _id is provided",
			test: func() (int, error) {
				return machines0.Find(bson.D{{"_id", m0.Id()}}).Count()
			},
			expectedCount: 1,
		},
		{
			label: "Find tolerates env UUID prefix already being present",
			test: func() (int, error) {
				return machines0.Find(bson.D{
					{"_id", state.DocID(s.State, m0.Id())},
				}).Count()
			},
			expectedCount: 1,
		},
		{
			label: "Find with no selector still filters by env",
			test: func() (int, error) {
				return machines0.Find(nil).Count()
			},
			expectedCount: 2,
		},
		{
			label: "Find leaves _id alone if used with operator",
			test: func() (int, error) {
				return machines0.Find(bson.D{
					{"_id", bson.D{{"$regex", ":" + m0.Id() + "$"}}},
				}).Count()
			},
			expectedCount: 1, // not 2 because env-uuid filter is still added
		},
		{
			label: "Find works with collections with ObjectId ids",
			test: func() (int, error) {
				return networkInterfaces.Find(bson.D{{"interfacename", "foo0"}}).Count()
			},
			expectedCount: 1,
		},
		{
			label: "Find works with ObjectId ids",
			test: func() (int, error) {
				return networkInterfaces.Find(bson.D{{"_id", ifaceId}}).Count()
			},
			expectedCount: 1,
		},
		{
			label: "Find panics if env-uuid is included",
			test: func() (int, error) {
				machines0.Find(bson.D{{"env-uuid", "whatever"}})
				return 0, nil
			},
			expectedPanic: "env-uuid is added automatically and should not be provided",
		},
		{
			label: "Find panics if query type is unsupported",
			test: func() (int, error) {
				machines0.Find(map[string]string{"foo": "bar"})
				return 0, nil
			},
			expectedPanic: "query must be bson.D, bson.M, or nil",
		},
		{
			label: "FindId adds env UUID prefix",
			test: func() (int, error) {
				return machines0.FindId(m0.Id()).Count()
			},
			expectedCount: 1,
		},
		{
			label: "FindId tolerates env UUID prefix already being there",
			test: func() (int, error) {
				return machines0.FindId(state.DocID(s.State, m0.Id())).Count()
			},
			expectedCount: 1,
		},
		{
			label: "FindId works with ObjectId ids",
			test: func() (int, error) {
				return networkInterfaces.FindId(ifaceId).Count()
			},
			expectedCount: 1,
		},
		{
			label: "FindId adds env-uuid field",
			test: func() (int, error) {
				return networkInterfaces.FindId(otherIfaceId).Count()
			},
			// expect to find no networks, as we are searching with the id of
			// the network in the other environment.
			expectedCount: 0,
		},
		{
			label: "Insert works",
			test: func() (int, error) {
				err := machines0.Writeable().Insert(bson.D{
					{"_id", state.DocID(s.State, "99")},
					{"machineid", 99},
					{"env-uuid", s.State.EnvironUUID()},
				})
				c.Assert(err, jc.ErrorIsNil)
				return machines0.Count()
			},
			expectedCount: 3,
		},
		{
			label: "Remove adds env UUID prefix to _id",
			test: func() (int, error) {
				err := machines0.Writeable().Remove(bson.D{{"_id", "0"}})
				c.Assert(err, jc.ErrorIsNil)
				return s.machines.Count()
			},
			expectedCount: 2, // Expect machine-1 in first env and machine-0 in second env
		},
		{
			label: "Remove filters by env",
			test: func() (int, error) {
				// Attempt to remove the trusty machine in the second
				// env with the collection that's filtering for the
				// first env - nothing should get removed.
				err := machines0.Writeable().Remove(bson.D{{"series", "trusty"}})
				c.Assert(err, gc.ErrorMatches, "not found")
				return s.machines.Count()
			},
			expectedCount: 3, // Expect all machines to still be there.
		},
		{
			label: "Remove filters by env 2",
			test: func() (int, error) {
				err := machines0.Writeable().Remove(bson.D{{"machineid", "0"}})
				c.Assert(err, jc.ErrorIsNil)
				return s.machines.Count()
			},
			expectedCount: 2, // Expect machine 1 in first env and machine-0 in second env
		},
		{
			label: "RemoveId adds env UUID prefix",
			test: func() (int, error) {
				err := machines0.Writeable().RemoveId(m0.Id())
				c.Assert(err, jc.ErrorIsNil)
				return s.machines.Count()
			},
			expectedCount: 2, // Expect machine-1 in first env and machine-0 in second env
		},
		{
			label: "RemoveId tolerates env UUID prefix already being there",
			test: func() (int, error) {
				err := machines0.Writeable().RemoveId(state.DocID(s.State, m0.Id()))
				c.Assert(err, jc.ErrorIsNil)
				return s.machines.Count()
			},
			expectedCount: 2, // Expect machine-1 in first env and machine-0 in second env
		},
		{
			label: "RemoveId filters by env-uuid field",
			test: func() (int, error) {
				err := networkInterfaces.Writeable().RemoveId(otherIfaceId)
				c.Assert(err, gc.ErrorMatches, "not found")
				return networkInterfaces.Count()
			},
			expectedCount: 1, // ensure doc was not removed
		},
		{
			label: "RemoveAll filters by env",
			test: func() (int, error) {
				_, err := machines0.Writeable().RemoveAll(bson.D{{"series", m0.Series()}})
				c.Assert(err, jc.ErrorIsNil)
				return s.machines.Count()
			},
			expectedCount: 1, // Expect machine-1 in second env
		},
		{
			label: "RemoveAll adds env UUID when _id is provided",
			test: func() (int, error) {
				_, err := machines0.Writeable().RemoveAll(bson.D{{"_id", m0.Id()}})
				c.Assert(err, jc.ErrorIsNil)
				return s.machines.Count()
			},
			expectedCount: 2, // Expect machine-1 in first env and machine-0 in second env
		},
		{
			label: "RemoveAll tolerates env UUID prefix already being present",
			test: func() (int, error) {
				_, err := machines0.Writeable().RemoveAll(bson.D{
					{"_id", state.DocID(s.State, m0.Id())},
				})
				c.Assert(err, jc.ErrorIsNil)
				return s.machines.Count()
			},
			expectedCount: 2, // Expect machine-1 in first env and machine-0 in second env
		},
		{
			label: "RemoveAll with no selector still filters by env",
			test: func() (int, error) {
				_, err := machines0.Writeable().RemoveAll(nil)
				c.Assert(err, jc.ErrorIsNil)
				return s.machines.Count()
			},
			expectedCount: 1, // Expect machine-0 in second env
		},
		{
			label: "RemoveAll panics if env-uuid is included",
			test: func() (int, error) {
				machines0.Writeable().RemoveAll(bson.D{{"env-uuid", "whatever"}})
				return 0, nil
			},
			expectedPanic: "env-uuid is added automatically and should not be provided",
		},
		{
			label: "RemoveAll panics if query type is unsupported",
			test: func() (int, error) {
				machines0.Writeable().RemoveAll(map[string]string{"foo": "bar"})
				return 0, nil
			},
			expectedPanic: "query must be bson.D, bson.M, or nil",
		},
		{
			label: "Update",
			test: func() (int, error) {
				err := machines0.Writeable().Update(bson.D{{"_id", m0.Id()}},
					bson.D{{"$set", bson.D{{"update-field", "field value"}}}})
				c.Assert(err, jc.ErrorIsNil)
				return machines0.Find(bson.D{{"update-field", "field value"}}).Count()
			},
			expectedCount: 1,
		},
		{
			label: "UpdateId",
			test: func() (int, error) {
				err := machines0.Writeable().UpdateId(m0.Id(),
					bson.D{{"$set", bson.D{{"update-field", "field value"}}}})
				c.Assert(err, jc.ErrorIsNil)
				return machines0.Find(bson.D{{"update-field", "field value"}}).Count()
			},
			expectedCount: 1,
		},
	} {
		c.Logf("test %d: %s", i, t.label)
		machinesSnapshot.restore(c)
		networkInterfacesSnapshot.restore(c)

		if t.expectedPanic == "" {
			count, err := t.test()
			if t.expectedError != "" {
				c.Assert(err, gc.ErrorMatches, t.expectedError)
			} else {
				c.Assert(err, jc.ErrorIsNil)
			}
			c.Check(count, gc.Equals, t.expectedCount)
		} else {
			c.Check(func() { t.test() }, gc.PanicMatches, t.expectedPanic)
		}

		// Check that other environment is untouched after each test
		count, err := machines1.Count()
		c.Assert(err, jc.ErrorIsNil)
		c.Check(count, gc.Equals, 1)
	}
}