Repository: localstack/localstack

Issue:
CloudFormation - CreationTime is now supported in moto
Originally reported in https://github.com/localstack/localstack/issues/2099, the CreationTime for CF stacks was hardcoded. This was fixed in in LocalStack itself (https://github.com/localstack/localstack/pull/2103), but is now also fixed in moto (https://github.com/spulec/moto/pull/2818).

I don't know what version of moto you're using, and whether it's acceptable to use dev-releases, but if you do: 

moto 1.3.15.dev550 should fix this issue, so the LS fix can be removed if you upgrade :) 


Discussion:

Resolving patch:
diff --git a/localstack/services/cloudformation/cloudformation_listener.py b/localstack/services/cloudformation/cloudformation_listener.py
--- a/localstack/services/cloudformation/cloudformation_listener.py
+++ b/localstack/services/cloudformation/cloudformation_listener.py
@@ -112,6 +112,7 @@ def get_template_body(req_data):
                 parsed_path = urlparse.urlparse(url).path.lstrip('/')
                 parts = parsed_path.partition('/')
                 client = aws_stack.connect_to_service('s3')
+                LOG.debug('Download CloudFormation template content from local S3: %s - %s' % (parts[0], parts[2]))
                 result = client.get_object(Bucket=parts[0], Key=parts[2])
                 body = to_str(result['Body'].read())
                 return body
@@ -121,7 +122,8 @@ def get_template_body(req_data):
 
 
 def is_local_service_url(url):
-    return '://%s:' % config.LOCALSTACK_HOSTNAME in url
+    candidates = ('localhost', config.LOCALSTACK_HOSTNAME, config.HOSTNAME_EXTERNAL, config.HOSTNAME)
+    return any('://%s:' % host in url for host in candidates)
 
 
 def is_real_s3_url(url):
@@ -141,9 +143,10 @@ def convert_s3_to_local_url(url):
 
 
 def fix_hardcoded_creation_date(response):
-    search = '<CreationTime>2011-05-23T15:47:44Z</CreationTime>'
-    replace = '<CreationTime>%s</CreationTime>' % timestamp()
-    response._content = to_str(response._content or '').replace(search, replace)
+    # TODO: remove once this is fixed upstream
+    search = r'<CreationTime>\s*(2011-05-23T15:47:44Z)?\s*</CreationTime>'
+    replace = r'<CreationTime>%s</CreationTime>' % timestamp()
+    response._content = re.sub(search, replace, to_str(response._content or ''))
     response.headers['Content-Length'] = str(len(response._content))
 
 
diff --git a/localstack/utils/cloudformation/template_deployer.py b/localstack/utils/cloudformation/template_deployer.py
--- a/localstack/utils/cloudformation/template_deployer.py
+++ b/localstack/utils/cloudformation/template_deployer.py
@@ -636,7 +636,7 @@ def retrieve_resource_details(resource_id, resource_status, resources, stack_nam
             if not api_id or not res_id:
                 return None
             res_obj = aws_stack.connect_to_service('apigateway').get_resource(restApiId=api_id, resourceId=res_id)
-            match = [v for (k, v) in res_obj['resourceMethods'].items()
+            match = [v for (k, v) in res_obj.get('resourceMethods', {}).items()
                      if resource_props['HttpMethod'] in (v.get('httpMethod'), k)]
             int_props = resource_props.get('Integration')
             if int_props:


Test patch: