Deploy templates: fix updating steps in Python 3

If a step in a deploy template is updated, changing only the step's
'args' field, then we see the following error on Python 3:

TypeError: unorderable types: dict() < dict()

In Python 3, dicts are no longer orderable, so cannot be used as part of
the key to a sort function. This change uses a JSON dump of the step
with sorted keys for comparison, as suggested in [1].

[1] https://stackoverflow.com/a/22003440

Change-Id: I70b806d5850f0678f3dd6633228947f6cd39d691
Story: 1722275
Task: 29750
This commit is contained in:
Mark Goddard 2019-02-28 11:58:05 +00:00
parent 1e4a1cb7cb
commit e989a21f06
2 changed files with 15 additions and 1 deletions

View File

@ -16,6 +16,7 @@
import collections
import datetime
import json
import threading
from oslo_db import api as oslo_db_api
@ -1848,7 +1849,11 @@ class Connection(api.Connection):
def _step_key(step):
"""Compare two deploy template steps."""
return step.interface, step.step, step.args, step.priority
# NOTE(mgoddard): In python 3, dicts are not orderable so cannot be
# used as a sort key. Serialise the step arguments to a JSON string
# for comparison. Taken from https://stackoverflow.com/a/22003440.
sortable_args = json.dumps(step.args, sort_keys=True)
return step.interface, step.step, sortable_args, step.priority
# List all existing steps for the template.
current_steps = (model_query(models.DeployTemplateStep)

View File

@ -100,6 +100,15 @@ class DbDeployTemplateTestCase(base.DbTestCase):
self.assertEqual({}, step1.args)
self.assertEqual(50, step1.priority)
def test_update_steps_replace_args(self):
step = self.template.steps[0]
step['args'] = {'foo': 'bar'}
values = {'steps': [step]}
template = self.dbapi.update_deploy_template(self.template.id, values)
self.assertEqual(1, len(template.steps))
step = template.steps[0]
self.assertEqual({'foo': 'bar'}, step.args)
def test_update_steps_remove_all(self):
values = {'steps': []}
template = self.dbapi.update_deploy_template(self.template.id, values)