Skip to content

Commit 20677f3

Browse files
committed
bug: Fix parsing of nested objects in lists
This fixes tests, and the lke cluster-create operation. As it happens, the CLI did not parse optional list arguments correctly (namely, if an optional argument to a list was omitted, the list would not be created and no items in the list would populate correctly. Compounding this, objects nested in objects within lists did not properly restructure after being flattened for the command line. This caused nested objects in lists to be sent incorrectly. Both of the above broke the `linode-cli lke cluster-create` endpoint, and thereby tests, when `autoscaler` was added to that endpoint, nested within the `node_pools` object in a list. This change fixes the issues, allowing this endpoint to work again. :warning: I did not write this to handle multiple layers of object nesting in lists. I will revisit this if it ever becomes necessary - I left a comment noting where it would be handled.
1 parent 9b7a170 commit 20677f3

1 file changed

Lines changed: 31 additions & 2 deletions

File tree

linodecli/operation.py

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,13 +188,14 @@ def parse_args(self, args):
188188
type=TYPES[arg.arg_type])
189189

190190
parsed = parser.parse_args(args)
191-
192191
lists = {}
193192
# group list items as expected
194193
for arg_name, list_name in list_items:
195-
item_name = arg_name.split('.')[-1]
194+
item_name = arg_name.split(list_name)[1][1:]
196195
if hasattr(parsed, arg_name):
197196
val = getattr(parsed, arg_name) or []
197+
if not val:
198+
continue
198199
if list_name not in lists:
199200
new_list = [{item_name: c} for c in val]
200201
lists[list_name] = new_list
@@ -203,6 +204,33 @@ def parse_args(self, args):
203204
for obj, item in zip(update_list, val):
204205
obj[item_name] = item
205206

207+
# break out list items with periods in their name into objects. This
208+
# allows supporting nested lists
209+
for _, cur_list in lists.items():
210+
# for each list in lists
211+
for item in cur_list:
212+
# for each item in the list (these are dicts)
213+
new_dicts = {}
214+
remove_keys = []
215+
for k, v in item.items():
216+
# if there's a period in the key, split it into a dict and
217+
# possibly merge it with a dict that came from a prior split
218+
#
219+
# XXX: This only supports one layer of nested dicts in lists
220+
if "." in k:
221+
dict_key, key = k.split('.', 1)
222+
if dict_key in new_dicts:
223+
new_dicts[dict_key][key] = v
224+
else:
225+
new_dicts[dict_key] = {key: v}
226+
remove_keys.append(k)
227+
228+
# remove the original keys
229+
for key in remove_keys:
230+
del item[key]
231+
# and add the combined keys
232+
item.update(new_dicts)
233+
206234
# don't send along empty lists
207235
to_delete = []
208236
for k, v in lists.items():
@@ -219,6 +247,7 @@ def parse_args(self, args):
219247
del parsed[name]
220248
parsed = argparse.Namespace(**parsed)
221249

250+
222251
return parsed
223252

224253
def process_response_json(self, json, handler):

0 commit comments

Comments
 (0)