def test_get_all_keys(self): client = SysAdminClient("127.0.0.1", 4000) client.set("network.dhcp.startip", "192.168.1.1") client.set("network.dhcp.endip", "192.168.1.100") client.set("network.dhcp.interfaces", ["eth0", "eth1"]) client.set("my.service.restarter", True) client.set("network.breakfast", "waffles") client.set("network.lease", 1440) client.commit() resp = set(map(lambda x: x.key, client.get("network.dhcp.*").get.kvs)) self.assertEqual( set([ "network.dhcp.startip", "network.dhcp.endip", "network.dhcp.interfaces" ]), resp) resp = map(lambda x: UnpackFromProto(x.value), client.get("network.dhcp.*").get.kvs) self.assertEqual(3, len(resp)) self.assertTrue("192.168.1.1" in resp) self.assertTrue("192.168.1.100" in resp) self.assertTrue(["eth0", "eth1"] in resp) resp = set(map(lambda x: x.key, client.get("network.*").get.kvs)) self.assertEqual( set([ "network.dhcp.startip", "network.dhcp.endip", "network.dhcp.interfaces", "network.breakfast", "network.lease" ]), resp) resp = map(lambda x: UnpackFromProto(x.value), client.get("network.*").get.kvs) self.assertEqual(5, len(resp)) self.assertTrue("192.168.1.1" in resp) self.assertTrue("192.168.1.100" in resp) self.assertTrue(["eth0", "eth1"] in resp) self.assertTrue("waffles" in resp) self.assertTrue(1440 in resp)
def test_new_key_migration(self): client = SysAdminClient("127.0.0.1", 4000) client.set("network.dhcp.startip", "192.168.1.1") client.set("network.dhcp.endip", "192.168.1.100") client.set("network.dhcp.interfaces", ["eth0", "eth1"]) client.set("my.service.restarter", True) client.set("network.breakfast", "waffles") client.set("network.lease", 1440) client.commit() m = SysAdminMigrator(client) m.new_keys({"new.key": "value"}) client.commit() self.assertEqual( "value", UnpackFromProto(client.get("new.key").get.kvs[0].value)) m.change_values({"new.key": "4"}) client.commit() self.assertEqual( "4", UnpackFromProto(client.get("new.key").get.kvs[0].value)) m.change_types({"new.key": "int32"}) client.commit() self.assertEqual( 4, UnpackFromProto(client.get("new.key").get.kvs[0].value)) m.rename_keys([{"new.key": "renamed.key"}]) client.commit() self.assertEqual( 4, UnpackFromProto(client.get("renamed.key").get.kvs[0].value)) m.remove_keys(["new.key"]) client.commit() self.assertEqual( 4, UnpackFromProto(client.get("renamed.key").get.kvs[0].value))
def test_change_types(self): client = SysAdminClient("127.0.0.1", 4000) m = SysAdminMigrator(client) m.new_keys({"gonna.be.list": "value"}) client.commit() m.change_types({"gonna.be.list": "stringlist"}) client.commit() self.assertEqual(["value"], UnpackFromProto( client.get("gonna.be.list").get.kvs[0].value)) m.change_types({"gonna.be.list": "str"}) client.commit() self.assertEqual( "value", UnpackFromProto(client.get("gonna.be.list").get.kvs[0].value)) m.new_keys({"gonna.be.intlist": "4"}) client.commit() m.change_types({"gonna.be.intlist": "int32list"}) client.commit() self.assertEqual([4], UnpackFromProto( client.get("gonna.be.intlist").get.kvs[0].value)) m.change_types({"gonna.be.intlist": "str"}) client.commit() self.assertEqual( "4", UnpackFromProto(client.get("gonna.be.intlist").get.kvs[0].value)) m.new_keys({"gonna.be.boollist": "true"}) client.commit() m.change_types({"gonna.be.boollist": "boollist"}) client.commit() self.assertEqual([True], UnpackFromProto( client.get("gonna.be.boollist").get.kvs[0].value)) m.change_types({"gonna.be.boollist": "str"}) client.commit() self.assertEqual( "True", UnpackFromProto(client.get("gonna.be.boollist").get.kvs[0].value)) m.new_keys({"long.list": ["stringlist", "4", "5", "6"]}) client.commit() m.change_types({"long.list": "int32list"}) client.commit() self.assertEqual([4, 5, 6], UnpackFromProto( client.get("long.list").get.kvs[0].value)) m.change_types({"long.list": "int32list"}) client.commit() self.assertEqual([4, 5, 6], UnpackFromProto( client.get("long.list").get.kvs[0].value)) m.change_types({"long.list": "stringlist"}) client.commit() self.assertEqual(["4", "5", "6"], UnpackFromProto( client.get("long.list").get.kvs[0].value))
def rename_key(sysadmin, oldkey, newkey): existing = sysadmin.get(oldkey) if existing.status == sysadminctl_pb2.KEY_NOT_FOUND: print("Key {} must exist to be renamed".format(oldkey)) return sysadmin.erase(oldkey) sysadmin.set(newkey, UnpackFromProto(existing.get.kvs[0].value))
def __iter__(self): """Fetch all the paths that start with this node and terminate at a node that contains a value. Then iterate along each path. If the parent does not contain a corresponding NamespaceFetcher object in its sub_namespaces dict then create a new object and add it. Except for the last node of each branch. In that case add the name and value to the parent's namespace_items dict""" # We always issue a wildcard get on iteration, largely cause there's # no way to know if we've gotten the whole namespace via single gets # TODO, some "hints" to this dict could tell it that we have everything resp = self.sysadmin.get(combine_full_key(self.namespace, "*")) returned = set() for kvs in resp.get.kvs: key = kvs.key if len(self.namespace) > 0: key = kvs.key.replace("%s." % self.namespace, "") split_keys = key.split(".") nested_dict = self for i, skey in enumerate(split_keys): running_key = combine_full_key(nested_dict.namespace, skey) if i >= len(split_keys) - 1: # The end of a path contains a value, but has no children nested_dict.namespace_items[running_key] = UnpackFromProto( kvs.value) elif running_key not in nested_dict.sub_namespaces: fetcher = NamespaceFetcher(self.sysadmin, running_key) nested_dict.sub_namespaces[running_key] = fetcher nested_dict = fetcher else: nested_dict = nested_dict.sub_namespaces[running_key] if split_keys[0] not in returned: returned.add(split_keys[0]) yield split_keys[0]
def test_erase(self): client = SysAdminClient("127.0.0.1", 4000) client.set("wireless.wl0.psk", "password") client.set("wireless.wl0.channel", 40) client.set("wireless.wl0.enabled", True) client.set("wireless.wl0.frequencies", [1, 2, 3]) client.commit() self.assertEqual( "password", UnpackFromProto(client.get("wireless.wl0.psk").get.kvs[0].value)) client.erase("wireless.wl0.psk") self.assertEqual( "password", UnpackFromProto(client.get("wireless.wl0.psk").get.kvs[0].value)) client.erase("not.a.key") client.commit() self.assertEqual(sysadminctl_pb2.KEY_NOT_FOUND, client.get("wireless.wl0.psk").status)
def test_new_key_rollback(self): #make a commit with a new key and value, ensure that a rollback can remove the key client = SysAdminClient("127.0.0.1", 4000) client.set("cheese", 42) self.assertEqual(1, client.commit().commit.commit_id) self.assertEqual( 42, UnpackFromProto(client.get("cheese").get.kvs[0].value)) self.assertEqual(sysadminctl_pb2.SUCCESS, client.rollback(1).status) self.assertEqual(sysadminctl_pb2.KEY_NOT_FOUND, client.get("cheese").status)
def FetchAllValues(keys): client = SysAdminClient("127.0.0.1", 4000) output = {} for arg in keys: resp = client.get(arg) if resp.status == sysadminctl_pb2.SUCCESS: for value in resp.get.kvs: output[value.key] = UnpackFromProto(value.value) elif "last." not in arg: raise Exception("Could not find required key. Key %s, Error: %s" % (arg, resp.status)) return condense(output)
def test_overridden_xid(self): # This client gets the regular sysadmin assigned id client = SysAdminClient("127.0.0.1", 4000) client.set("network.dhcp.startip", "192.168.1.1") client.set("network.dhcp.endip", "192.168.1.100") # This client has a overridden id 0 otherclient = SysAdminClient("127.0.0.1", 4000, 0) # This client can't commit the original clients changes otherclient.commit() self.assertEqual(sysadminctl_pb2.KEY_NOT_FOUND, client.get("network.dhcp.startip").status) self.assertEqual(sysadminctl_pb2.KEY_NOT_FOUND, client.get("network.dhcp.endip").status) client.commit() self.assertEqual( "192.168.1.1", UnpackFromProto( client.get("network.dhcp.startip").get.kvs[0].value)) self.assertEqual( "192.168.1.100", UnpackFromProto(client.get("network.dhcp.endip").get.kvs[0].value))
def test_type_checking(self): client = SysAdminClient("127.0.0.1", 4000) client.set("wireless.wl0.psk", "password") resp = client.set("wireless.wl0.psk", 5) self.assertEqual(sysadminctl_pb2.SUCCESS, resp.status) client.commit() resp = client.set("wireless.wl0.psk", "password") self.assertEqual(sysadminctl_pb2.TYPE_MISMATCH, resp.status) client.commit() self.assertEqual( 5, UnpackFromProto(client.get("wireless.wl0.psk").get.kvs[0].value))
def test_basic_sets(self): # one in-flight client = SysAdminClient("127.0.0.1", 4000) resp = client.set("wireless.wl0.ssid", "cheese") self.assertEqual("wireless.wl0.ssid", resp.get.kvs[0].key) self.assertEqual("cheese", UnpackFromProto(resp.get.kvs[0].value)) resp = client.get("wireless.wl0.ssid") self.assertEqual(sysadminctl_pb2.KEY_NOT_FOUND, resp.status) client.commit() resp = client.get("wireless.wl0.ssid") self.assertEqual("cheese", UnpackFromProto(resp.get.kvs[0].value)) # multiple in-flight, one erasing the other client.set("wireless.wl0.psk", "password") client.set("wireless.wl0.channel", 40) client.set("wireless.wl0.channel", 60) client.set("wireless.wl0.enabled", True) client.set("wireless.wl0.frequencies", [1, 2, 3]) client.commit() self.assertEqual( 60, UnpackFromProto( client.get("wireless.wl0.channel").get.kvs[0].value)) self.assertEqual( "password", UnpackFromProto(client.get("wireless.wl0.psk").get.kvs[0].value)) self.assertEqual( True, UnpackFromProto( client.get("wireless.wl0.enabled").get.kvs[0].value)) self.assertEqual( [1, 2, 3], UnpackFromProto( client.get("wireless.wl0.frequencies").get.kvs[0].value))
def _fetch_update(self, key): if key in self.namespace_items: return self.namespace_items[key] if key in self.sub_namespaces: return self.sub_namespaces[key] resp = self.sysadmin.get(key) if resp.status == sysadminctl_pb2.KEY_NOT_FOUND: if key in self.sub_namespaces: return self.sub_namespaces[key] self.sub_namespaces[key] = NamespaceFetcher(self.sysadmin, key) return self.sub_namespaces[key] self.namespace_items[key] = UnpackFromProto(resp.get.kvs[0].value) return self.namespace_items[key]
def change_type(sysadmin, key, newtype): existing = sysadmin.get(key) if existing.status == sysadminctl_pb2.KEY_NOT_FOUND: print("Key {} must exist to have it's type changed".format(key)) return oldtype = str(existing.get.kvs[0].value.WhichOneof("value")) value = UnpackFromProto(existing.get.kvs[0].value) if "list" in oldtype and "list" not in newtype: if len(getattr(existing.get.kvs[0].value, oldtype).list) > 1: print("Can't type convert a list larger than one element") return value = value[0] # sysadmin's type system requires that we remove the old value # completely before being able to set it with a new type cloneClient = SysAdminClient(sysadmin.ip, sysadmin.port, 10) cloneClient.erase(key) cloneClient.commit(sysadminctl_pb2.NO_HOOKS) sysadmin.set(key, value, newtype)
def test_new_key_migration(self): client = SysAdminClient("127.0.0.1", 4000) client.set("network.dhcp.startip", "192.168.1.1") client.set("network.dhcp.endip", "192.168.1.100") client.set("network.dhcp.interfaces", ["eth0", "eth1"]) client.set("my.service.restarter", True) client.set("network.breakfast", "eggs") client.set("network.lease", 1440) client.set("default.network.breakfast", "waffles") client.set("default.network.lease", 1440) client.commit() client.reset() resp = client.get("network.dhcp.startip") self.assertEqual(sysadminctl_pb2.KEY_NOT_FOUND, resp.status) self.assertEqual( "waffles", UnpackFromProto(client.get("network.breakfast").get.kvs[0].value))
def test_basic_rollback(self): # This client gets the regular sysadmin assigned id client = SysAdminClient("127.0.0.1", 4000) client.set("network.dhcp.startip", "192.168.1.1") client.set("network.dhcp.endip", "192.168.1.100") self.assertEqual(1, client.commit().commit.commit_id) client.set("network.dhcp.startip", "10.0.0.1") client.set("network.dhcp.endip", "10.0.0.100") self.assertEqual(2, client.commit().commit.commit_id) # Can't rollback the first commit self.assertEqual(sysadminctl_pb2.FAILED_ROLLBACK, client.rollback(1).status) self.assertEqual(sysadminctl_pb2.SUCCESS, client.rollback(2).status) self.assertEqual( "192.168.1.1", UnpackFromProto( client.get("network.dhcp.startip").get.kvs[0].value)) self.assertEqual(sysadminctl_pb2.FAILED_ROLLBACK, client.rollback(100).status)
def __iter__(self): # We always issue a wildcard get on iteration, largely cause there's # no way to know if we've gotten the whole namespace via single gets # TODO, some "hints" to this dict could tell it that we have everything resp = self.sysadmin.get(combine_full_key(self.namespace, "*")) returned = set() for kvs in resp.get.kvs: key = kvs.key if len(self.namespace) > 0: key = kvs.key.replace("%s." % self.namespace, "") split_keys = key.split(".") nested_dict = self for i, skey in enumerate(split_keys): running_key = combine_full_key(nested_dict.namespace, skey) if i >= len(split_keys) - 1: nested_dict.namespace_items[running_key] = UnpackFromProto(kvs.value) elif running_key not in nested_dict.sub_namespaces: nested_dict.sub_namespaces[running_key] = NamespaceFetcher(self.sysadmin, running_key) nested_dict = nested_dict[skey] if split_keys[0] not in returned: returned.add(split_keys[0]) yield split_keys[0]