def evaluate_when(
    operator_dict,
    env,
    cc_dict,
    context_key,
):
    """Evaluate the when condition and return bool."""
    if 'when' not in operator_dict:
        return True

    when_raw = operator_dict['when']
    when_condition = False
    if isinstance(when_raw, str):
        when_condition = render_variable(env, when_raw, cc_dict, context_key)
    elif isinstance(when_raw, list):
        # Evaluate lists as successively evalutated 'and' conditions
        for i in when_raw:
            when_condition = render_variable(env, i, cc_dict, context_key)
            # If anything is false, then break immediately
            if not when_condition:
                break

    operator_dict.pop('when')

    return when_condition
def prompt_choice_for_config(cc_dict, env, key, options, no_input, context_key):
    """Prompt user with a set of options to choose from.

    Each of the possible choices is rendered beforehand.
    """
    rendered_options = [
        render_variable(env, raw, cc_dict, context_key) for raw in options
    ]

    if no_input:
        return rendered_options[0]
    return read_user_choice(key, rendered_options)
Example #3
0
def parse_context(context, env, cc_dict, context_key, no_input):
    """Parse the context and iterate over values.

    :param dict context: Source for field names and sample values.
    :param env: Jinja environment to render values with.
    :param context_key: The key to insert all the outputs under in the context dict.
    :param no_input: Prompt the user at command line for manual configuration.
    :param existing_context: A dictionary of values to use during rendering.
    :return: cc_dict
    """
    for key, raw in context[context_key].items():
        if key.startswith(u'_') and not key.startswith('__'):
            cc_dict[key] = raw
            continue
        elif key.startswith('__'):
            cc_dict[key] = render_variable(env, raw, cc_dict, context_key)
            continue

        try:
            if isinstance(raw, list):
                # We are dealing with a choice variable
                val = prompt_choice_for_config(cc_dict, env, key, raw,
                                               no_input, context_key)
                cc_dict[key] = val
            elif not isinstance(raw, dict):
                # We are dealing with a regular variable
                val = render_variable(env, raw, cc_dict, context_key)

                if not no_input:
                    val = read_user_variable(key, val)

                cc_dict[key] = val
        except UndefinedError as err:
            msg = "Unable to render variable '{}'".format(key)
            raise UndefinedVariableInTemplate(msg, err, context)

            # Second pass; handle the dictionaries.
    for key, raw in context[context_key].items():
        if key.startswith('_') and not key.startswith('__'):
            continue
        try:
            if isinstance(raw, dict):
                # dict parsing logic
                if 'type' not in raw:
                    val = render_variable(env, raw, cc_dict, context_key)
                    if not no_input:
                        val = read_user_dict(key, val)
                    cc_dict[key] = val
                else:
                    cc_dict = parse_operator(
                        context,
                        key,
                        dict(cc_dict),
                        no_input=no_input,
                        context_key=context_key,
                    )

        except UndefinedError as err:
            msg = "Unable to render variable '{}'".format(key)
            raise UndefinedVariableInTemplate(msg, err, context)

    return cc_dict
Example #4
0
def parse_operator(
    context,
    key,
    cc_dict,
    append_key: bool = False,
    no_input: bool = False,
    context_key=None,
):
    """Parse input dict for loop and when logic and calls hooks.

    :return: cc_dict
    """
    global post_gen_operator_list
    if not context_key:
        context_key = next(iter(context))

    env = StrictEnvironment(context=context)
    logger.debug("Parsing context_key: %s and key: %s" % (context_key, key))
    operator_dict = context[context_key][key]

    when_condition = evaluate_when(operator_dict, env, cc_dict, context_key)

    if when_condition:
        # Extract loop
        if 'loop' in operator_dict:
            loop_targets = render_variable(
                env, operator_dict['loop'], cc_dict, context_key
            )
            operator_dict.pop('loop')

            loop_output = []
            for i, l in enumerate(loop_targets):
                loop_cookiecutter = cc_dict
                loop_cookiecutter.update({'index': i, 'item': l})
                loop_output += [
                    parse_operator(
                        context,
                        key,
                        loop_cookiecutter,
                        append_key=True,
                        no_input=no_input,
                    )
                ]

            cc_dict.pop('item')
            cc_dict.pop('index')
            cc_dict[key] = loop_output
            return cc_dict

        if 'block' not in operator_dict['type']:
            operator_dict = render_variable(env, operator_dict, cc_dict, context_key)

        # Run the operator
        if operator_dict['merge'] if 'merge' in operator_dict else False:
            to_merge, post_gen_operator = run_operator(
                operator_dict, context, no_input, context_key, cc_dict, env
            )
            cc_dict.update(to_merge)
        else:
            cc_dict[key], post_gen_operator = run_operator(
                operator_dict, context, no_input, context_key, cc_dict, env, key
            )
        if post_gen_operator:
            post_gen_operator_list.append(post_gen_operator)

        if append_key:
            return cc_dict[key]

    return cc_dict