From 69cd4e6421ac02c1c4a279a40520be2cec83f0e7 Mon Sep 17 00:00:00 2001 From: Nicolas Calderon Asselin Date: Tue, 7 May 2019 20:58:27 -0400 Subject: [PATCH 1/3] Factor out ami-* imageId lookup from get_imageId Separation of concerns, and reduces the amount of mocking that needs to be done in order to isolate bug. --- salt/cloud/clouds/ec2.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/salt/cloud/clouds/ec2.py b/salt/cloud/clouds/ec2.py index 03deb4eedb45..6c647e1815fe 100644 --- a/salt/cloud/clouds/ec2.py +++ b/salt/cloud/clouds/ec2.py @@ -1214,21 +1214,29 @@ def get_imageid(vm_): ) if image.startswith('ami-'): return image + else: + return _get_imageid_from_image_name(image) + + +def _get_imageid_from_image_name(image_name): + ''' + Returns most recent 'ami-*' imageId matching image name + ''' # a poor man's cache - if not hasattr(get_imageid, 'images'): - get_imageid.images = {} - elif image in get_imageid.images: - return get_imageid.images[image] + if not hasattr(_get_imageid_from_image_name, 'images'): + _get_imageid_from_image_name.images = {} + elif image_name in _get_imageid_from_image_name.images: + return _get_imageid_from_image_name.images[image_name] params = {'Action': 'DescribeImages', 'Filter.0.Name': 'name', - 'Filter.0.Value.0': image} + 'Filter.0.Value.0': image_name} # Query AWS, sort by 'creationDate' and get the last imageId _t = lambda x: datetime.datetime.strptime(x['creationDate'], '%Y-%m-%dT%H:%M:%S.%fZ') image_id = sorted(aws.query(params, location=get_location(), provider=get_provider(), opts=__opts__, sigver='4'), lambda i, j: salt.utils.compat.cmp(_t(i), _t(j)) )[-1]['imageId'] - get_imageid.images[image] = image_id + _get_imageid_from_image_name.images[image_name] = image_id return image_id From 332dcd365c29fb28d8e47429fe3a9b569ae88bc3 Mon Sep 17 00:00:00 2001 From: Nicolas Calderon Asselin Date: Tue, 7 May 2019 21:00:18 -0400 Subject: [PATCH 2/3] Add test case for salt-cloud ec2's get_imageid The mock values were obtained by running an acutal query, truncating the list of returned entries and stripping unnecessary keys from the results. The test case runs well with python 2 but causes a traceback with python 3. --- tests/unit/cloud/clouds/test_ec2.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/unit/cloud/clouds/test_ec2.py b/tests/unit/cloud/clouds/test_ec2.py index 312b3953c3b4..9046a3e83906 100644 --- a/tests/unit/cloud/clouds/test_ec2.py +++ b/tests/unit/cloud/clouds/test_ec2.py @@ -86,3 +86,20 @@ def test_get_password_data(self, query, get_provider, get_location, _get_node): ) assert ret['passwordData'] == PASS_DATA assert ret['password'] == 'testp4ss!' + + @patch('salt.cloud.clouds.ec2.get_location') + @patch('salt.cloud.clouds.ec2.get_provider') + @patch('salt.utils.aws.query') + def test__get_imageid_by_name(self, query, get_provider, get_location): + # Trimmed list and stripped dictionary keys for brevity + query.return_value = [ + {u'creationDate': '2019-01-30T23:40:58.000Z', u'imageId': 'ami-02eac2c0129f6376b'}, + {u'creationDate': '2019-03-15T00:08:05.000Z', u'imageId': 'ami-089ccd342f0be98ab'}, + {u'creationDate': '2018-05-14T17:19:51.000Z', u'imageId': 'ami-4b6bff34'}, + {u'creationDate': '2018-01-12T20:33:32.000Z', u'imageId': 'ami-4bf3d731'}] + get_location.return_value = 'us-west2' + get_provider.return_value = 'ec2' + + # Mock makes argument irrelevant; illustrates value used to obtain mock + imageid = ec2._get_imageid_from_image_name('CentOS Linux 7*') + assert imageid == 'ami-089ccd342f0be98ab' From 99831c748bf180d269616b7aff408343c8339a56 Mon Sep 17 00:00:00 2001 From: Nicolas Calderon Asselin Date: Fri, 22 Mar 2019 18:32:32 -0400 Subject: [PATCH 3/3] Fix salt-cloud traceback with python 3 With python 3, salt-cloud tracebacks in salt/cloud/clouds/ec2.py's get_imageid when searching for an image name not starting with "ami-". Python 3 removed the cmp parameter in favor of key. --- salt/cloud/clouds/ec2.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/salt/cloud/clouds/ec2.py b/salt/cloud/clouds/ec2.py index 6c647e1815fe..9ce30d48ec92 100644 --- a/salt/cloud/clouds/ec2.py +++ b/salt/cloud/clouds/ec2.py @@ -1231,10 +1231,9 @@ def _get_imageid_from_image_name(image_name): 'Filter.0.Name': 'name', 'Filter.0.Value.0': image_name} # Query AWS, sort by 'creationDate' and get the last imageId - _t = lambda x: datetime.datetime.strptime(x['creationDate'], '%Y-%m-%dT%H:%M:%S.%fZ') image_id = sorted(aws.query(params, location=get_location(), provider=get_provider(), opts=__opts__, sigver='4'), - lambda i, j: salt.utils.compat.cmp(_t(i), _t(j)) + key=lambda x: datetime.datetime.strptime(x['creationDate'], '%Y-%m-%dT%H:%M:%S.%fZ') )[-1]['imageId'] _get_imageid_from_image_name.images[image_name] = image_id return image_id