def validate_functions(plan): get_property_functions = [] def handler(v, scope, context, path): _func = parse(v, scope=scope, context=context, path=path) if isinstance(_func, Function): _func.validate(plan) if isinstance(_func, GetProperty): get_property_functions.append(_func) return _func return v # Replace all get_property functions with their instance representation scan.scan_service_template(plan, handler, replace=True) if not get_property_functions: return # Validate there are no circular get_property calls for func in get_property_functions: property_path = [str(prop) for prop in func.property_path] visited_functions = [ '{0}.{1}'.format( func.get_node_template(plan)['name'], constants.FUNCTION_NAME_PATH_SEPARATOR.join(property_path)) ] def validate_no_circular_get_property(*args): r = args[0] if isinstance(r, GetProperty): func_id = '{0}.{1}'.format( r.get_node_template(plan)['name'], constants.FUNCTION_NAME_PATH_SEPARATOR.join( r.property_path)) if func_id in visited_functions: visited_functions.append(func_id) error_output = [ x.replace(constants.FUNCTION_NAME_PATH_SEPARATOR, ',') for x in visited_functions ] raise RuntimeError( 'Circular get_property function call detected: ' '{0}'.format(' -> '.join(error_output))) visited_functions.append(func_id) r = r.evaluate(plan) validate_no_circular_get_property(r) else: scan.scan_properties(r, validate_no_circular_get_property) result = func.evaluate(plan) validate_no_circular_get_property(result) def replace_with_raw_function(*args): if isinstance(args[0], GetProperty): return args[0].raw return args[0] # Change previously replaced get_property instances with raw values scan.scan_service_template(plan, replace_with_raw_function, replace=True)
def validate_functions(plan): get_property_functions = [] def handler(v, scope, context, path): _func = parse(v, scope=scope, context=context, path=path) if isinstance(_func, Function): _func.validate(plan) if isinstance(_func, GetProperty): get_property_functions.append(_func) return _func return v # Replace all get_property functions with their instance representation scan.scan_service_template(plan, handler, replace=True) if not get_property_functions: return # Validate there are no circular get_property calls for func in get_property_functions: property_path = [str(prop) for prop in func.property_path] visited_functions = ['{0}.{1}'.format( func.get_node_template(plan)['name'], constants.FUNCTION_NAME_PATH_SEPARATOR.join(property_path))] def validate_no_circular_get_property(*args): r = args[0] if isinstance(r, GetProperty): func_id = '{0}.{1}'.format( r.get_node_template(plan)['name'], constants.FUNCTION_NAME_PATH_SEPARATOR.join( r.property_path)) if func_id in visited_functions: visited_functions.append(func_id) error_output = [ x.replace(constants.FUNCTION_NAME_PATH_SEPARATOR, ',') for x in visited_functions ] raise RuntimeError( 'Circular get_property function call detected: ' '{0}'.format(' -> '.join(error_output))) visited_functions.append(func_id) r = r.evaluate(plan) validate_no_circular_get_property(r) else: scan.scan_properties( r, validate_no_circular_get_property, recursive=False) result = func.evaluate(plan) validate_no_circular_get_property(result) def replace_with_raw_function(*args): if isinstance(args[0], GetProperty): return args[0].raw return args[0] # Change previously replaced get_property instances with raw values scan.scan_service_template(plan, replace_with_raw_function, replace=True)
def validate_functions(plan): def handler(v, scope, context, path): func = parse(v, scope=scope, context=context, path=path) if isinstance(func, Function): func.validate(plan) scan.scan_properties(v, handler, scope=scope, context=context, path=path, replace=False) return v scan.scan_service_template(plan, handler, replace=False)
def _process_functions(plan): def handler(dict_, k, v, scope, context, path): func = functions.parse(v, scope=scope, context=context, path=path) evaluated_value = v while isinstance(func, functions.Function): if isinstance(func, functions.GetAttribute): dict_[k] = func.raw return evaluated_value = func.evaluate(plan) func = functions.parse(evaluated_value, scope=scope, context=context, path=path) dict_[k] = evaluated_value scan.scan_service_template(plan, handler)
def validate_functions(plan): # Represents a level in the tree of function calls. A value in index i # represents that a Runtime Function has been seen in levels # with depth >= i+1. # Level with index 0 is the root of the tree, before entering any function # nodes. levels = [False] def handler(v, scope, context, path): func = parse(v, scope=scope, context=context, path=path) if isinstance(func, Function): func.validate(plan) # Add a value to the stack for this level. levels.append(False) scan.scan_properties( v, handler, scope=scope, context=context, path=path, replace=False) if isinstance(func, Function): # If a Runtime Function has been seen below this level and this is # a Static Function, raise an exception. if levels[-1] and func.func_eval_type == STATIC_FUNC: raise exceptions.FunctionValidationError( func.name, 'Runtime function {0} cannot be nested within ' 'a non-runtime function (found in {1})'.format( func.raw, path)) # Update the parent level value, whether a Runtime Function has # been seen on this level or below. levels[-2] = \ levels[-2] \ or func.func_eval_type == RUNTIME_FUNC \ or levels[-1] # Remove the value of the stack for this level. levels.pop(-1) return v scan.scan_service_template(plan, handler, replace=False)
def _process_functions(plan, runtime_only_evaluation=False): handler = functions.plan_evaluation_handler(plan, runtime_only_evaluation) scan.scan_service_template( plan, handler, replace=True, search_secrets=True)
def _process_functions(plan): handler = functions.plan_evaluation_handler(plan) scan.scan_service_template(plan, handler, replace=True)