summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik Panter <e.panter@mittwald.de>2021-10-29 11:03:27 +0200
committerTakashi Kajinami <tkajinam@redhat.com>2022-04-13 07:55:38 +0000
commit5ea5276a3e76829fd72345e3aae7482cbd260b51 (patch)
treee809087044333fd974948cde765a4602e35d41ed
parentef36cb30495f3b9bb0fc265f13aa4fad00733705 (diff)
downloadheat-5ea5276a3e76829fd72345e3aae7482cbd260b51.tar.gz
Fix None comparision when sorting by `updated_at`
When sorting resource candidates in `_get_best_existing_rsrc_db`, resources with the same score are sorted by `updated_at`, which can be `None`. If that is the case, use `created_at` instead. Task: 43815 Story: 2009653 Change-Id: Ic0265fcf7ceb811803cdebaa8932fe80dc59a627 (cherry picked from commit 403fa55fe94ae1063d2cb4b8db3b63b76b1ee5cf)
-rw-r--r--heat/engine/stack.py5
-rw-r--r--heat/tests/test_convg_stack.py27
2 files changed, 26 insertions, 6 deletions
diff --git a/heat/engine/stack.py b/heat/engine/stack.py
index 3503c2f34..ec46e8ff4 100644
--- a/heat/engine/stack.py
+++ b/heat/engine/stack.py
@@ -1549,7 +1549,10 @@ class Stack(collections.abc.Mapping):
# Rolling back to previous resource
score += 10
- return score, ext_rsrc.updated_at
+ last_changed_at = ext_rsrc.updated_at
+ if last_changed_at is None:
+ last_changed_at = ext_rsrc.created_at
+ return score, last_changed_at
candidates = sorted((r for r in self.ext_rsrcs_db.values()
if r.name == rsrc_name),
diff --git a/heat/tests/test_convg_stack.py b/heat/tests/test_convg_stack.py
index 0db119781..c001af1e0 100644
--- a/heat/tests/test_convg_stack.py
+++ b/heat/tests/test_convg_stack.py
@@ -11,6 +11,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from datetime import datetime
+from datetime import timedelta
from unittest import mock
from oslo_config import cfg
@@ -429,22 +431,32 @@ class StackConvergenceCreateUpdateDeleteTest(common.HeatTestCase):
stack.prev_raw_template_id = 2
stack.t.id = 3
- def db_resource(current_template_id):
+ def db_resource(current_template_id,
+ created_at=None,
+ updated_at=None):
db_res = resource_objects.Resource(stack.context)
db_res['id'] = current_template_id
db_res['name'] = 'A'
db_res['current_template_id'] = current_template_id
- db_res['action'] = 'CREATE'
+ db_res['action'] = 'UPDATE' if updated_at else 'CREATE'
db_res['status'] = 'COMPLETE'
- db_res['updated_at'] = None
+ db_res['updated_at'] = updated_at
+ db_res['created_at'] = created_at
db_res['replaced_by'] = None
return db_res
+ start_time = datetime.utcfromtimestamp(0)
+
+ def t(minutes):
+ return start_time + timedelta(minutes=minutes)
+
a_res_2 = db_resource(2)
a_res_3 = db_resource(3)
- a_res_1 = db_resource(1)
+ a_res_0 = db_resource(0, created_at=t(0), updated_at=t(1))
+ a_res_1 = db_resource(1, created_at=t(2))
existing_res = {a_res_2.id: a_res_2,
a_res_3.id: a_res_3,
+ a_res_0.id: a_res_0,
a_res_1.id: a_res_1}
stack.ext_rsrcs_db = existing_res
best_res = stack._get_best_existing_rsrc_db('A')
@@ -460,9 +472,14 @@ class StackConvergenceCreateUpdateDeleteTest(common.HeatTestCase):
# no resource with current template id as 3 or 2
del existing_res[2]
best_res = stack._get_best_existing_rsrc_db('A')
- # should return resource with template id 1 existing in DB
+ # should return resource with template id 1 which is the newest
self.assertEqual(a_res_1.id, best_res.id)
+ del existing_res[1]
+ best_res = stack._get_best_existing_rsrc_db('A')
+ # should return resource with template id 0 existing in the db
+ self.assertEqual(a_res_0.id, best_res.id)
+
@mock.patch.object(parser.Stack, '_converge_create_or_update')
def test_updated_time_stack_create(self, mock_ccu, mock_cr):
stack = parser.Stack(utils.dummy_context(), 'convg_updated_time_test',