def evaluate()

in cfn_policy_validator/parsers/utils/intrinsic_functions/ref_evaluator.py [0:0]


	def evaluate(self, resource_logical_name_or_param, visited_values=None):
		""" Evaluates a Fn::Ref function
			visited_values: tracks visited values to detect circular references in a CloudFormation template
		"""
		if visited_values is None:
			visited_values = []

		validate_schema(resource_logical_name_or_param, ref_schema, 'Ref')

		if resource_logical_name_or_param == "AWS::AccountId":
			return self.account_config.account_id

		if resource_logical_name_or_param == "AWS::Partition":
			return self.account_config.partition

		if resource_logical_name_or_param == "AWS::Region":
			return self.account_config.region

		if resource_logical_name_or_param == "AWS::StackName":
			# just return some default value, we won't know this in advance
			return "StackName"

		if resource_logical_name_or_param == "AWS::NoValue":
			return NoValue()

		if resource_logical_name_or_param == "AWS::URLSuffix":
			return aws_url_suffix_evaluator.evaluate(self.account_config.region)

		# check to see if the reference is for a resource
		resource = self.resources.get(resource_logical_name_or_param)
		if resource is not None:
			resource_type = resource['Type']

			# first, see if this ref should return an ARN.  Not all Ref's return ARNs.
			if resource_type in self.services_where_ref_returns_arn:
				return self.arn_generator.try_generate_arn(resource_logical_name_or_param, resource, 'Ref', visited_values=visited_values)

			# next, see if we have a custom evaluation for this ref
			custom_ref_eval = self.custom_ref_evals.get(resource_type)
			if custom_ref_eval is not None:
				return custom_ref_eval(resource_logical_name_or_param, resource, self.account_config, visited_values)

			# at this point, we make the assumption that the resource just returns a string (probably either the resource
			# name or ID)
			properties = resource.get('Properties', {})

			# next, attempt to return the actual name of the resource if one is defined and it's for a common resource
			name_returned_by_ref = name_hints.get(resource_type)
			property_value = properties.get(name_returned_by_ref)
			if property_value is None:
				# just return the CFN logical name if there's no property to be found
				return resource_logical_name_or_param

			# we found a valid property value for the name of the resources. this property may reference another resource,
			# so check to see if we've already done that and we're stuck in a cycle
			validate_no_cycle(resource_logical_name_or_param, name_returned_by_ref, visited_values)
			return self.node_evaluator.eval(property_value, visited_values=visited_values)

		# if it's not a reference to a resource, check to see if it references a parameter
		parameter = self.parameters.get(resource_logical_name_or_param)
		if parameter is not None:
			# if the parameter exists in the template, make sure a value was passed in for it
			parameter_value = self.parameter_values.get(resource_logical_name_or_param)
			if parameter_value is None:
				raise ApplicationError(f'No value passed for referenced parameter: {resource_logical_name_or_param}.\n'
									   f'Parameters are passed using the --parameters flag.')

			return parameter_value

		raise ApplicationError(f'Unable to find a referenced resource or parameter in template: {resource_logical_name_or_param}')