in src/cfnlint/rules/functions/GetAtt.py [0:0]
def match(self, cfn):
matches = []
getatts = cfn.search_deep_keys('Fn::GetAtt')
valid_getatts = cfn.get_valid_getatts()
valid_attribute_functions = ['Ref']
for getatt in getatts:
if len(getatt[-1]) < 2:
message = 'Invalid GetAtt for {0}'
matches.append(RuleMatch(getatt, message.format('/'.join(map(str, getatt[:-1])))))
continue
if isinstance(getatt[-1], six.string_types):
resname, restype = getatt[-1].split('.', 1)
else:
resname = None
restype = None
if isinstance(getatt[-1][1], six.string_types):
resname = getatt[-1][0]
restype = '.'.join(getatt[-1][1:])
elif isinstance(getatt[-1][1], dict):
# You can ref the secondary part of a getatt
resname = getatt[-1][0]
restype = getatt[-1][1]
if len(restype) == 1:
for k in restype.keys():
if k not in valid_attribute_functions:
message = 'GetAtt only supports functions "{0}" for attributes at {1}'
matches.append(
RuleMatch(
getatt,
message.format(
', '.join(map(str, valid_attribute_functions)),
'/'.join(map(str, getatt[:-1])))))
else:
message = 'Invalid GetAtt structure {0} at {1}'
matches.append(RuleMatch(getatt, message.format(
getatt[-1], '/'.join(map(str, getatt[:-1])))))
# setting restype to None as we can't validate that anymore
restype = None
else:
message = 'Invalid GetAtt structure {0} at {1}'
matches.append(RuleMatch(getatt, message.format(
getatt[-1], '/'.join(map(str, getatt[:-1])))))
# only check resname if its set. if it isn't it is because of bad structure
# and an error is already provided
if resname:
if resname in valid_getatts:
if restype is not None:
# Check for maps
restypeparts = restype.split('.')
if restypeparts[0] in valid_getatts[resname] and len(restypeparts) >= 2:
if valid_getatts[resname][restypeparts[0]].get('Type') != 'Map':
message = 'Invalid GetAtt {0}.{1} for resource {2}'
matches.append(RuleMatch(
getatt[:-1], message.format(resname, restype, getatt[1])))
else:
continue
if restype not in valid_getatts[resname] and '*' not in valid_getatts[resname]:
message = 'Invalid GetAtt {0}.{1} for resource {2}'
matches.append(RuleMatch(
getatt[:-1], message.format(resname, restype, getatt[1])))
else:
modules = cfn.get_modules()
if any(resname.startswith(s) for s in modules.keys()):
LOGGER.debug('Will consider valid getatt %s because it references a resource within a module', resname)
else:
message = 'Invalid GetAtt {0}.{1} for resource {2}'
matches.append(RuleMatch(getatt, message.format(resname, restype, getatt[1])))
return matches