Esempio n. 1
0
    def test_get_from_config(self):
        config = Config(SUDO="config-value")
        inventory = Inventory((("somehost", ), {}))

        state = State(config=config, inventory=inventory)

        kwargs, keys = pop_global_arguments(
            {}, state=state, host=inventory.get_host("somehost"))
        assert kwargs["sudo"] == "config-value"
Esempio n. 2
0
def _get_executor_defaults(state, host):
    global_argument_defaults, _ = pop_global_arguments({},
                                                       state=state,
                                                       host=host)
    return {
        key: value
        for key, value in global_argument_defaults.items()
        if key in get_executor_kwarg_keys()
    }
Esempio n. 3
0
    def test_get_from_state_deploy_kwargs(self):
        config = Config(SUDO="config-value")
        inventory = Inventory(([("somehost", {"sudo": "host-value"})], {}))
        somehost = inventory.get_host("somehost")

        state = State(config=config, inventory=inventory)
        somehost.current_deploy_kwargs = {"sudo": "deploy-kwarg-value"}

        kwargs, keys = pop_global_arguments({}, state=state, host=somehost)
        assert kwargs["sudo"] == "deploy-kwarg-value"
Esempio n. 4
0
def _get_fact(
    state,
    host,
    cls,
    args=None,
    kwargs=None,
    ensure_hosts=None,
    apply_failed_hosts=True,
    fact_hash=None,
):
    fact = cls()
    name = fact.name

    args = args or ()
    kwargs = kwargs or {}

    # Get the defaults *and* overrides by popping from kwargs, executor kwargs passed
    # into get_fact override everything else (applied below).
    override_kwargs, override_kwarg_keys = pop_global_arguments(
        kwargs,
        state=state,
        host=host,
        keys_to_check=get_executor_kwarg_keys(),
    )

    executor_kwargs = _get_executor_kwargs(
        state,
        host,
        override_kwargs=override_kwargs,
        override_kwarg_keys=override_kwarg_keys,
    )

    if args or kwargs:
        # Merges args & kwargs into a single kwargs dictionary
        kwargs = getcallargs(fact.command, *args, **kwargs)

    kwargs_str = get_kwargs_str(kwargs)
    logger.debug(
        "Getting fact: %s (%s) (ensure_hosts: %r)",
        name,
        kwargs_str,
        ensure_hosts,
    )

    if not host.connected:
        host.connect(
            reason=f"to load fact: {name} ({kwargs_str})",
            raise_exceptions=True,
        )

    ignore_errors = (host.current_op_global_kwargs or {}).get(
        "ignore_errors",
        state.config.IGNORE_ERRORS,
    )

    # Facts can override the shell (winrm powershell vs cmd support)
    if fact.shell_executable:
        executor_kwargs["shell_executable"] = fact.shell_executable

    command = _make_command(fact.command, kwargs)
    requires_command = _make_command(fact.requires_command, kwargs)
    if requires_command:
        command = StringCommand(
            # Command doesn't exist, return 0 *or* run & return fact command
            "!",
            "command",
            "-v",
            requires_command,
            ">/dev/null",
            "||",
            command,
        )

    status = False
    stdout = []
    combined_output_lines = []

    try:
        status, combined_output_lines = host.run_shell_command(
            command,
            print_output=state.print_fact_output,
            print_input=state.print_fact_input,
            return_combined_output=True,
            **executor_kwargs,
        )
    except (timeout_error, socket_error, SSHException) as e:
        log_host_command_error(
            host,
            e,
            timeout=executor_kwargs["timeout"],
        )

    stdout, stderr = split_combined_output(combined_output_lines)

    data = fact.default()

    if status:
        if stdout:
            data = fact.process(stdout)
    elif stderr:
        # If we have error output and that error is sudo or su stating the user
        # does not exist, do not fail but instead return the default fact value.
        # This allows for users that don't currently but may be created during
        # other operations.
        first_line = stderr[0]
        if executor_kwargs["sudo_user"] and re.match(SUDO_REGEX, first_line):
            status = True
        if executor_kwargs["su_user"] and any(
                re.match(regex, first_line) for regex in SU_REGEXES):
            status = True

    if status:
        log_message = "{0}{1}".format(
            host.print_prefix,
            "Loaded fact {0}{1}".format(
                click.style(name, bold=True),
                f" ({get_kwargs_str(kwargs)})" if kwargs else "",
            ),
        )
        if state.print_fact_info:
            logger.info(log_message)
        else:
            logger.debug(log_message)
    else:
        if not state.print_fact_output:
            print_host_combined_output(host, combined_output_lines)

        log_error_or_warning(
            host,
            ignore_errors,
            description=("could not load fact: {0} {1}").format(
                name, get_kwargs_str(kwargs)),
        )

    # Check we've not failed
    if not status and not ignore_errors and apply_failed_hosts:
        state.fail_hosts({host})

    if fact_hash:
        host.facts[fact_hash] = data
    return data