Esempio n. 1
0
    def _setup_relation_state(self, unit_name=None):
        """For a given unit name make sure we have YAMLState."""
        if unit_name is None:
            unit_name = yield self._resolve_id(
                self._unit_relation.internal_unit_id)

        if unit_name in self._node_cache:
            returnValue(self._node_cache[unit_name])

        unit_id = yield self._resolve_name(unit_name)
        path = self._settings_path(unit_id)

        # verify the unit relation path exists
        relation_data = YAMLState(self._client, path)
        try:
            yield relation_data.read(required=True)
        except StateNotFound:
            raise UnitRelationStateNotFound(
                self._unit_relation.internal_relation_id,
                self._change.relation_name,
                unit_name)

        # cache the value
        self._node_cache[unit_name] = relation_data
        returnValue(relation_data)
Esempio n. 2
0
class TokenDatabase(object):
    """A hash map of principal names to their identity tokens.

    Identity tokens are used to construct node ACLs.
    """
    def __init__(self, client, path="/auth-tokens"):
        self._state = YAMLState(client, path)

    @inlineCallbacks
    def add(self, principal):
        """Add a principal to the token database.
        """
        yield self._state.read()
        self._state[principal.name] = principal.get_token()
        yield self._state.write()

    @inlineCallbacks
    def get(self, name):
        """Return the identity token for a principal name.
        """
        yield self._state.read()
        try:
            returnValue(self._state[name])
        except KeyError:
            raise PrincipalNotFound(name)

    @inlineCallbacks
    def remove(self, name):
        """Remove a principal by name from the token database.
        """
        yield self._state.read()
        if name in self._state:
            del self._state[name]
            yield self._state.write()
Esempio n. 3
0
    def test_multiple_writes(self):
        d1 = YAMLState(self.client, self.path)
        yield d1.read()

        d1.update(dict(foo="bar", this="that"))
        changes = yield d1.write()
        self.assertEqual(
            set(changes),
            set([AddedItem("foo", "bar"),
                 AddedItem("this", "that")]))

        del d1["this"]
        d1["another"] = "value"

        changes = yield d1.write()
        self.assertEqual(
            set(changes),
            set([DeletedItem("this", "that"),
                 AddedItem("another", "value")]))

        expected = {"foo": "bar", "another": "value"}
        self.assertEqual(d1, expected)

        changes = yield d1.write()
        self.assertEqual(changes, [])
        self.assertEqual(d1, expected)

        yield d1.read()
        self.assertEqual(d1, expected)

        # This shouldn't write any changes
        changes = yield d1.write()
        self.assertEqual(changes, [])
        self.assertEqual(d1, expected)
Esempio n. 4
0
    def test_set_w_write(self):
        """Verify that write updates the local and zk state.

        When write is called we expect that zk state reflects this. We
        also expect calls to get to expect the reflected state.
        """
        node = YAMLState(self.client, self.path)
        yield node.read()

        options = dict(alpha="beta", one=1)
        node.update(options)

        changes = yield node.write()
        self.assertEqual(
            set(changes),
            set([AddedItem(key='alpha', new='beta'),
                 AddedItem(key='one', new=1)]))

        # a local get should reflect proper data
        self.assertEqual(node, options)

        # and a direct look at zk should work as well
        zk_data, stat = yield self.client.get(self.path)
        zk_data = yaml.load(zk_data)
        self.assertEqual(zk_data, options)
Esempio n. 5
0
class TokenDatabase(object):
    """A hash map of principal names to their identity tokens.

    Identity tokens are used to construct node ACLs.
    """
    def __init__(self, client, path="/auth-tokens"):
        self._state = YAMLState(client, path)

    @inlineCallbacks
    def add(self, principal):
        """Add a principal to the token database.
        """
        yield self._state.read()
        self._state[principal.name] = principal.get_token()
        yield self._state.write()

    @inlineCallbacks
    def get(self, name):
        """Return the identity token for a principal name.
        """
        yield self._state.read()
        try:
            returnValue(self._state[name])
        except KeyError:
            raise PrincipalNotFound(name)

    @inlineCallbacks
    def remove(self, name):
        """Remove a principal by name from the token database.
        """
        yield self._state.read()
        if name in self._state:
            del self._state[name]
            yield self._state.write()
Esempio n. 6
0
    def test_multiple_writes(self):
        d1 = YAMLState(self.client, self.path)
        yield d1.read()

        d1.update(dict(foo="bar", this="that"))
        changes = yield d1.write()
        self.assertEqual(
            set(changes),
            set([AddedItem("foo", "bar"), AddedItem("this", "that")]))

        del d1["this"]
        d1["another"] = "value"

        changes = yield d1.write()
        self.assertEqual(
            set(changes),
            set([DeletedItem("this", "that"), AddedItem("another", "value")]))

        expected = {"foo": "bar", "another": "value"}
        self.assertEqual(d1, expected)

        changes = yield d1.write()
        self.assertEqual(changes, [])
        self.assertEqual(d1, expected)

        yield d1.read()
        self.assertEqual(d1, expected)

        # This shouldn't write any changes
        changes = yield d1.write()
        self.assertEqual(changes, [])
        self.assertEqual(d1, expected)
Esempio n. 7
0
    def test_del_empties_state(self):
        d = YAMLState(self.client, self.path)
        yield d.read()

        d["a"] = "foo"
        changes = yield d.write()
        self.assertEqual(changes, [AddedItem("a", "foo")])
        del d["a"]
        changes = yield d.write()
        self.assertEqual(changes, [DeletedItem("a", "foo")])
        self.assertEqual(d, {})
Esempio n. 8
0
    def test_del_empties_state(self):
        d = YAMLState(self.client, self.path)
        yield d.read()

        d["a"] = "foo"
        changes = yield d.write()
        self.assertEqual(changes, [AddedItem("a", "foo")])
        del d["a"]
        changes = yield d.write()
        self.assertEqual(changes, [DeletedItem("a", "foo")])
        self.assertEqual(d, {})
Esempio n. 9
0
 def test_missing_constraints(self):
     """ensure compatibility with nodes written for previous versions"""
     yield self.add_machine_state()
     machine = yield self.machine_state_manager.get_machine_state(0)
     path = "/machines/" + machine.internal_id
     node = YAMLState(self.client, path)
     yield node.read()
     del node["constraints"]
     yield node.write()
     constraints = yield machine.get_constraints()
     self.assertEquals(constraints.data, {})
Esempio n. 10
0
    def get(self, unit_name):
        # Only this unit's settings should be accessible.
        if unit_name not in (None, self._unit_name):
            raise RelationBrokenContextError("Cannot access other units in broken relation")

        settings_path = yield self.get_settings_path()

        if self._relation_cache is None:
            relation_data = YAMLState(self._client, settings_path)
            try:
                yield relation_data.read(required=True)
                self._relation_cache = dict(relation_data)
            except StateNotFound:
                self._relation_cache = {}
        returnValue(self._relation_cache)
Esempio n. 11
0
    def test_set_wo_write(self):
        """Check that get resolves from the internal write buffer.

        set/get pairs w/o write should present a view of the state
        reflecting local change. Verify that w/o write local data
        appears on subsequent calls but that zk state hasn't been
        changed.
        """
        path = yield self.client.create(self.path)
        node = YAMLState(self.client, path)
        yield node.read()

        options = dict(alpha="beta", one=1)
        node.update(options)
        self.assertEqual(node, options)

        zk_data, stat = yield self.client.get(self.path)
        # the node isn't created yet in zk
        self.assertEqual(zk_data, "")
Esempio n. 12
0
    def test_set_wo_write(self):
        """Check that get resolves from the internal write buffer.

        set/get pairs w/o write should present a view of the state
        reflecting local change. Verify that w/o write local data
        appears on subsequent calls but that zk state hasn't been
        changed.
        """
        path = yield self.client.create(self.path)
        node = YAMLState(self.client, path)
        yield node.read()

        options = dict(alpha="beta", one=1)
        node.update(options)
        self.assertEqual(node, options)

        zk_data, stat = yield self.client.get(self.path)
        # the node isn't created yet in zk
        self.assertEqual(zk_data, "")
Esempio n. 13
0
    def test_read_resync(self):
        d1 = YAMLState(self.client, self.path)
        yield d1.read()
        d1["a"] = "foo"
        changes = yield d1.write()
        self.assertEqual(changes, [AddedItem("a", "foo")])

        d2 = YAMLState(self.client, self.path)
        yield d2.read()
        del d2["a"]
        changes = yield d2.write()
        self.assertEqual(changes, [DeletedItem("a", "foo")])
        d2["a"] = "bar"
        changes = yield d2.write()
        self.assertEqual(changes, [AddedItem("a", "bar")])
        zk_data, stat = yield self.client.get(self.path)
        yield d1.read()
        # d1 should pick up the new value (from d2) on a read
        zk_data, stat = yield self.client.get(self.path)
        self.assertEqual(d1["a"], "bar")
Esempio n. 14
0
    def test_write_twice(self):
        d1 = YAMLState(self.client, self.path)
        yield d1.read()
        d1["a"] = "foo"
        changes = yield d1.write()
        self.assertEqual(changes, [AddedItem("a", "foo")])

        d2 = YAMLState(self.client, self.path)
        yield d2.read()
        d2["a"] = "bar"
        changes = yield d2.write()
        self.assertEqual(changes, [ModifiedItem("a", "foo", "bar")])

        # Shouldn't write again. Changes were already
        # flushed and acted upon by other parties.
        changes = yield d1.write()
        self.assertEqual(changes, [])

        yield d1.read()
        self.assertEquals(d1, d2)
Esempio n. 15
0
    def test_setitem(self):
        node = YAMLState(self.client, self.path)
        yield node.read()

        options = dict(alpha="beta", one=1)
        node["alpha"] = "beta"
        node["one"] = 1
        changes = yield node.write()
        self.assertEqual(
            set(changes),
            set([AddedItem("alpha", "beta"),
                 AddedItem("one", 1)]))

        # a local get should reflect proper data
        self.assertEqual(node, options)

        # and a direct look at zk should work as well
        zk_data, stat = yield self.client.get(self.path)
        zk_data = yaml.load(zk_data)
        self.assertEqual(zk_data, options)
Esempio n. 16
0
    def test_setitem(self):
        node = YAMLState(self.client, self.path)
        yield node.read()

        options = dict(alpha="beta", one=1)
        node["alpha"] = "beta"
        node["one"] = 1
        changes = yield node.write()
        self.assertEqual(
            set(changes),
            set([AddedItem("alpha", "beta"),
                 AddedItem("one", 1)]))

        # a local get should reflect proper data
        self.assertEqual(node, options)

        # and a direct look at zk should work as well
        zk_data, stat = yield self.client.get(self.path)
        zk_data = yaml.load(zk_data)
        self.assertEqual(zk_data, options)
Esempio n. 17
0
    def test_set_w_write(self):
        """Verify that write updates the local and zk state.

        When write is called we expect that zk state reflects this. We
        also expect calls to get to expect the reflected state.
        """
        node = YAMLState(self.client, self.path)
        yield node.read()

        options = dict(alpha="beta", one=1)
        node.update(options)

        changes = yield node.write()
        self.assertEqual(
            set(changes),
            set([
                AddedItem(key='alpha', new='beta'),
                AddedItem(key='one', new=1)
            ]))

        # a local get should reflect proper data
        self.assertEqual(node, options)

        # and a direct look at zk should work as well
        zk_data, stat = yield self.client.get(self.path)
        zk_data = yaml.load(zk_data)
        self.assertEqual(zk_data, options)
Esempio n. 18
0
    def _setup_relation_state(self, unit_name=None):
        """For a given unit name make sure we have YAMLState."""
        if unit_name is None:
            unit_name = yield self._resolve_id(
                self._unit_relation.internal_unit_id)

        if unit_name in self._node_cache:
            returnValue(self._node_cache[unit_name])

        unit_id = yield self._resolve_name(unit_name)
        path = self._settings_path(unit_id)

        # verify the unit relation path exists
        relation_data = YAMLState(self._client, path)
        try:
            yield relation_data.read(required=True)
        except StateNotFound:
            raise UnitRelationStateNotFound(
                self._unit_relation.internal_relation_id,
                self._change.relation_name, unit_name)

        # cache the value
        self._node_cache[unit_name] = relation_data
        returnValue(relation_data)
Esempio n. 19
0
    def test_dictmixin_usage(self):
        """Verify that the majority of dict operation function."""
        node = YAMLState(self.client, self.path)
        yield node.read()

        node.update({"alpha": "beta", "foo": "bar"})
        self.assertEqual(node, {"alpha": "beta", "foo": "bar"})

        result = node.pop("foo")
        self.assertEqual(result, "bar")
        self.assertEqual(node, {"alpha": "beta"})

        node["delta"] = "gamma"
        self.assertEqual(set(node.keys()), set(("alpha", "delta")))

        result = list(node.iteritems())
        self.assertIn(("alpha", "beta"), result)
        self.assertIn(("delta", "gamma"), result)
Esempio n. 20
0
    def test_read_resync(self):
        d1 = YAMLState(self.client, self.path)
        yield d1.read()
        d1["a"] = "foo"
        changes = yield d1.write()
        self.assertEqual(changes, [AddedItem("a", "foo")])

        d2 = YAMLState(self.client, self.path)
        yield d2.read()
        del d2["a"]
        changes = yield d2.write()
        self.assertEqual(changes, [DeletedItem("a", "foo")])
        d2["a"] = "bar"
        changes = yield d2.write()
        self.assertEqual(changes, [AddedItem("a", "bar")])
        zk_data, stat = yield self.client.get(self.path)
        yield d1.read()
        # d1 should pick up the new value (from d2) on a read
        zk_data, stat = yield self.client.get(self.path)
        self.assertEqual(d1["a"], "bar")
Esempio n. 21
0
    def test_write_twice(self):
        d1 = YAMLState(self.client, self.path)
        yield d1.read()
        d1["a"] = "foo"
        changes = yield d1.write()
        self.assertEqual(changes, [AddedItem("a", "foo")])

        d2 = YAMLState(self.client, self.path)
        yield d2.read()
        d2["a"] = "bar"
        changes = yield d2.write()
        self.assertEqual(changes, [ModifiedItem("a", "foo", "bar")])

        # Shouldn't write again. Changes were already
        # flushed and acted upon by other parties.
        changes = yield d1.write()
        self.assertEqual(changes, [])

        yield d1.read()
        self.assertEquals(d1, d2)
Esempio n. 22
0
    def test_dictmixin_usage(self):
        """Verify that the majority of dict operation function."""
        node = YAMLState(self.client, self.path)
        yield node.read()

        node.update({"alpha": "beta", "foo": "bar"})
        self.assertEqual(node, {"alpha": "beta", "foo": "bar"})

        result = node.pop("foo")
        self.assertEqual(result, "bar")
        self.assertEqual(node, {"alpha": "beta"})

        node["delta"] = "gamma"
        self.assertEqual(set(node.keys()), set(("alpha", "delta")))

        result = list(node.iteritems())
        self.assertIn(("alpha", "beta"), result)
        self.assertIn(("delta", "gamma"), result)
Esempio n. 23
0
 def __init__(self, client, path="/auth-tokens"):
     self._state = YAMLState(client, path)
Esempio n. 24
0
    def test_conflict_on_set(self):
        """Version conflict error tests.

        Test that two YAMLState objects writing to the same path can
        and will throw version errors when elements become out of
        read.
        """
        node = YAMLState(self.client, self.path)
        node2 = YAMLState(self.client, self.path)

        yield node.read()
        yield node2.read()

        options = dict(alpha="beta", one=1)
        node.update(options)
        yield node.write()

        node2.update(options)
        changes = yield node2.write()
        self.assertEqual(
            set(changes),
            set([AddedItem("alpha", "beta"), AddedItem("one", 1)]))

        # first read node2
        self.assertEqual(node, options)

        # write on node 1
        options2 = dict(alpha="gamma", one="two")
        node.update(options2)
        changes = yield node.write()
        self.assertEqual(
            set(changes),
            set([ModifiedItem("alpha", "beta", "gamma"),
                 ModifiedItem("one", 1, "two")]))

        # verify that node 1 reports as expected
        self.assertEqual(node, options2)

        # verify that node2 has the older data still
        self.assertEqual(node2, options)

        # now issue a set/write from node2
        # this will merge the data deleting 'one'
        # and updating other values
        options3 = dict(alpha="cappa", new="next")
        node2.update(options3)
        del node2["one"]

        expected = dict(alpha="cappa", new="next")
        changes = yield node2.write()
        self.assertEqual(
            set(changes),
            set([DeletedItem("one", 1),
                 ModifiedItem("alpha", "beta", "cappa"),
                 AddedItem("new", "next")]))
        self.assertEqual(expected, node2)

        # but node still reflects the old data
        self.assertEqual(node, options2)
Esempio n. 25
0
 def test_read_requires_node(self):
     """Validate that read raises when required=True."""
     d1 = YAMLState(self.client, self.path)
     yield self.assertFailure(d1.read(True), StateNotFound)
Esempio n. 26
0
 def test_read_requires_node(self):
     """Validate that read raises when required=True."""
     d1 = YAMLState(self.client, self.path)
     yield self.assertFailure(d1.read(True), StateNotFound)
Esempio n. 27
0
 def test_get_empty(self):
     """Verify getting an empty node works as expected."""
     path = yield self.client.create(self.path)
     node = YAMLState(self.client, path)
     self.assertEqual(node, {})
Esempio n. 28
0
    def test_multiple_reads(self):
        """Calling read resets state to ZK after multiple round-trips."""
        node = YAMLState(self.client, self.path)
        yield node.read()

        node.update({"alpha": "beta", "foo": "bar"})

        self.assertEqual(node["alpha"], "beta")
        self.assertEqual(node["foo"], "bar")

        yield node.read()

        # A read resets the data to the empty state
        self.assertEqual(node, {})

        node.update({"alpha": "beta", "foo": "bar"})
        changes = yield node.write()
        self.assertEqual(
            set(changes),
            set([AddedItem("alpha", "beta"), AddedItem("foo", "bar")]))

        # A write retains the newly set values
        self.assertEqual(node["alpha"], "beta")
        self.assertEqual(node["foo"], "bar")

        # now get another state instance and change zk state
        node2 = YAMLState(self.client, self.path)
        yield node2.read()
        node2.update({"foo": "different"})
        changes = yield node2.write()
        self.assertEqual(
            changes, [ModifiedItem("foo", "bar", "different")])

        # This should pull in the new state (and still have the merged old.
        yield node.read()

        self.assertEqual(node["alpha"], "beta")
        self.assertEqual(node["foo"], "different")
Esempio n. 29
0
 def test_access_wo_create(self):
     """Verify accessing data for a non-existant node works as expected."""
     node = YAMLState(self.client, self.path)
     yield node.read()
     self.assertEqual(node, {})
Esempio n. 30
0
 def __init__(self, client, path="/auth-tokens"):
     self._state = YAMLState(client, path)
Esempio n. 31
0
    def test_multiple_reads(self):
        """Calling read resets state to ZK after multiple round-trips."""
        node = YAMLState(self.client, self.path)
        yield node.read()

        node.update({"alpha": "beta", "foo": "bar"})

        self.assertEqual(node["alpha"], "beta")
        self.assertEqual(node["foo"], "bar")

        yield node.read()

        # A read resets the data to the empty state
        self.assertEqual(node, {})

        node.update({"alpha": "beta", "foo": "bar"})
        changes = yield node.write()
        self.assertEqual(
            set(changes),
            set([AddedItem("alpha", "beta"),
                 AddedItem("foo", "bar")]))

        # A write retains the newly set values
        self.assertEqual(node["alpha"], "beta")
        self.assertEqual(node["foo"], "bar")

        # now get another state instance and change zk state
        node2 = YAMLState(self.client, self.path)
        yield node2.read()
        node2.update({"foo": "different"})
        changes = yield node2.write()
        self.assertEqual(changes, [ModifiedItem("foo", "bar", "different")])

        # This should pull in the new state (and still have the merged old.
        yield node.read()

        self.assertEqual(node["alpha"], "beta")
        self.assertEqual(node["foo"], "different")
Esempio n. 32
0
    def test_conflict_on_set(self):
        """Version conflict error tests.

        Test that two YAMLState objects writing to the same path can
        and will throw version errors when elements become out of
        read.
        """
        node = YAMLState(self.client, self.path)
        node2 = YAMLState(self.client, self.path)

        yield node.read()
        yield node2.read()

        options = dict(alpha="beta", one=1)
        node.update(options)
        yield node.write()

        node2.update(options)
        changes = yield node2.write()
        self.assertEqual(
            set(changes),
            set([AddedItem("alpha", "beta"),
                 AddedItem("one", 1)]))

        # first read node2
        self.assertEqual(node, options)

        # write on node 1
        options2 = dict(alpha="gamma", one="two")
        node.update(options2)
        changes = yield node.write()
        self.assertEqual(
            set(changes),
            set([
                ModifiedItem("alpha", "beta", "gamma"),
                ModifiedItem("one", 1, "two")
            ]))

        # verify that node 1 reports as expected
        self.assertEqual(node, options2)

        # verify that node2 has the older data still
        self.assertEqual(node2, options)

        # now issue a set/write from node2
        # this will merge the data deleting 'one'
        # and updating other values
        options3 = dict(alpha="cappa", new="next")
        node2.update(options3)
        del node2["one"]

        expected = dict(alpha="cappa", new="next")
        changes = yield node2.write()
        self.assertEqual(
            set(changes),
            set([
                DeletedItem("one", 1),
                ModifiedItem("alpha", "beta", "cappa"),
                AddedItem("new", "next")
            ]))
        self.assertEqual(expected, node2)

        # but node still reflects the old data
        self.assertEqual(node, options2)
Esempio n. 33
0
    def test_set_wo_read(self):
        """Verify that not calling read before mutation raises."""
        node = YAMLState(self.client, self.path)

        self.assertRaises(ValueError, node.__setitem__, "alpha", "beta")
        self.assertRaises(ValueError, node.update, {"alpha": "beta"})
Esempio n. 34
0
 def test_access_wo_create(self):
     """Verify accessing data for a non-existant node works as expected."""
     node = YAMLState(self.client, self.path)
     yield node.read()
     self.assertEqual(node, {})