Better handle empty ipaths in schema

When trying to write to sub-item paths that don't yet exist, the
previous method would just blindly write to whatever the root key is,
which is never what we actually want.

Instead, check explicitly for a "base path" situation, and handle that.
Then, if we try to get a subpath that isn't valid, return None. Finally
in the various functions, if the path is None, just continue (or return
false/None) and (try to) chug along.
This commit is contained in:
Joshua Boniface 2021-07-05 23:29:24 -04:00
parent be7b0be8ed
commit a8c28786dd
1 changed files with 35 additions and 10 deletions

View File

@ -201,6 +201,10 @@ class ZKHandler(object):
Check if a key exists Check if a key exists
""" """
path = self.get_schema_path(key) path = self.get_schema_path(key)
if path is None:
# This path is invalid, this is likely due to missing schema entries, so return False
return False
stat = self.zk_conn.exists(path) stat = self.zk_conn.exists(path)
if stat: if stat:
return True return True
@ -213,11 +217,13 @@ class ZKHandler(object):
""" """
try: try:
path = self.get_schema_path(key) path = self.get_schema_path(key)
data = self.zk_conn.get(path)[0].decode(self.encoding) if path is None:
except NoNodeError: # This path is invalid; this is likely due to missing schema entries, so return None
data = None return None
return data return self.zk_conn.get(path)[0].decode(self.encoding)
except NoNodeError:
return None
def write(self, kvpairs): def write(self, kvpairs):
""" """
@ -238,6 +244,9 @@ class ZKHandler(object):
value = kvpair[1] value = kvpair[1]
path = self.get_schema_path(key) path = self.get_schema_path(key)
if path is None:
# This path is invalid; this is likely due to missing schema entries, so continue
continue
if not self.exists(key): if not self.exists(key):
# Creating a new key # Creating a new key
@ -276,9 +285,9 @@ class ZKHandler(object):
keys = [keys] keys = [keys]
for key in keys: for key in keys:
path = self.get_schema_path(key)
if self.exists(key): if self.exists(key):
try: try:
path = self.get_schema_path(key)
self.zk_conn.delete(path, recursive=recursive) self.zk_conn.delete(path, recursive=recursive)
except Exception as e: except Exception as e:
self.log("ZKHandler error: Failed to delete key {}: {}".format(path, e), state='e') self.log("ZKHandler error: Failed to delete key {}: {}".format(path, e), state='e')
@ -292,11 +301,13 @@ class ZKHandler(object):
""" """
try: try:
path = self.get_schema_path(key) path = self.get_schema_path(key)
children = self.zk_conn.get_children(path) if path is None:
except NoNodeError: # This path is invalid; this is likely due to missing schema entries, so return None
children = None return None
return children return self.zk_conn.get_children(path)
except NoNodeError:
return None
def rename(self, kkpairs): def rename(self, kkpairs):
""" """
@ -327,13 +338,20 @@ class ZKHandler(object):
source_key = kkpair[0] source_key = kkpair[0]
source_path = self.get_schema_path(source_key) source_path = self.get_schema_path(source_key)
if source_path is None:
# This path is invalid; this is likely due to missing schema entries, so continue
continue
destination_key = kkpair[1] destination_key = kkpair[1]
destination_path = self.get_schema_path(destination_key) destination_path = self.get_schema_path(destination_key)
if destination_path is None:
# This path is invalid; this is likely due to missing schema entries, so continue
continue
if not self.exists(source_key): if not self.exists(source_key):
self.log("ZKHander error: Source key '{}' does not exist".format(source_path), state='e') self.log("ZKHander error: Source key '{}' does not exist".format(source_path), state='e')
return False return False
if self.exists(destination_key): if self.exists(destination_key):
self.log("ZKHander error: Destination key '{}' already exists".format(destination_path), state='e') self.log("ZKHander error: Destination key '{}' already exists".format(destination_path), state='e')
return False return False
@ -698,9 +716,16 @@ class ZKSchema(object):
if base_path is None: if base_path is None:
# This should only really happen for second-layer key types where the helper functions join them together # This should only really happen for second-layer key types where the helper functions join them together
base_path = '' base_path = ''
if not ipath:
# This is a root path
return f'{base_path}/{item}'
sub_path = self.schema.get(itype).get('.'.join(ipath)) sub_path = self.schema.get(itype).get('.'.join(ipath))
if sub_path is None: if sub_path is None:
sub_path = '' # We didn't find the path we're looking for, so we don't want to do anything
return None
return f'{base_path}/{item}{sub_path}' return f'{base_path}/{item}{sub_path}'
# Get keys of a schema location # Get keys of a schema location