예제 #1
0
    def test_get_fact(self):
        inventory = make_inventory(hosts=('anotherhost', ))
        state = State(inventory, Config())

        anotherhost = inventory.get_host('anotherhost')

        connect_all(state)

        with patch('pyinfra.api.connectors.ssh.run_shell_command'
                   ) as fake_run_command:
            fake_run_command.return_value = MagicMock(), MagicMock(
            ), MagicMock()
            fact_data = get_facts(state, 'command', ('yes', ))

        assert fact_data == {anotherhost: ''}

        fake_run_command.assert_called_with(
            state,
            anotherhost,
            'yes',
            print_input=False,
            print_output=False,
            shell_executable=None,
            su_user=None,
            sudo=False,
            sudo_user=None,
            timeout=None,
            use_sudo_password=False,
        )
예제 #2
0
    def test_run_shell_command_masked(self, fake_ssh_client, fake_click):
        fake_ssh = MagicMock()
        fake_stdout = MagicMock()
        fake_ssh.exec_command.return_value = MagicMock(), fake_stdout, MagicMock()

        fake_ssh_client.return_value = fake_ssh

        inventory = make_inventory(hosts=('somehost',))
        State(inventory, Config())
        host = inventory.get_host('somehost')
        host.connect()

        command = StringCommand('echo', MaskString('top-secret-stuff'))
        fake_stdout.channel.recv_exit_status.return_value = 0

        out = host.run_shell_command(command, print_output=True, print_input=True)
        assert len(out) == 3

        status, stdout, stderr = out
        assert status is True

        fake_ssh.exec_command.assert_called_with(
            "sh -c 'echo top-secret-stuff'",
            get_pty=False,
        )

        fake_click.echo.assert_called_with(
            "{0}>>> sh -c 'echo ***'".format(host.print_prefix),
            err=True,
        )
예제 #3
0
    def test_get_file_sudo_copy_fail(self, fake_ssh_client):
        inventory = make_inventory(hosts=('somehost',))
        State(inventory, Config())
        host = inventory.get_host('somehost')
        host.connect()

        stdout_mock = MagicMock()
        stdout_mock.channel.recv_exit_status.return_value = 1
        fake_ssh_client().exec_command.return_value = MagicMock(), stdout_mock, MagicMock()

        status = host.get_file(
            'not-a-file', 'not-another-file',
            print_output=True,
            sudo=True,
            sudo_user='******',
        )

        assert status is False

        fake_ssh_client().exec_command.assert_has_calls([
            call((
                "sudo -H -n -u ubuntu sh -c 'cp not-a-file "
                "/tmp/pyinfra-e9c0d3c8ffca943daa0e75511b0a09c84b59c508 && chmod +r not-a-file'"
            ), get_pty=False),
        ])
예제 #4
0
    def test_connect_with_rsa_ssh_key_password_from_prompt(self):
        state = State(make_inventory(hosts=(
            ('somehost', {'ssh_key': 'testkey'}),
        )), Config())

        with patch(
            'pyinfra.api.connectors.ssh.path.isfile',
            lambda *args, **kwargs: True,
        ), patch(
            'pyinfra.api.connectors.ssh.getpass',
            lambda *args, **kwargs: 'testpass',
        ), patch(
            'pyinfra.api.connectors.ssh.RSAKey.from_private_key_file',
        ) as fake_key_open:
            fake_key = MagicMock()

            def fake_key_open_fail(*args, **kwargs):
                if 'password' not in kwargs:
                    raise PasswordRequiredException()
                return fake_key

            fake_key_open.side_effect = fake_key_open_fail

            state.deploy_dir = '/'

            pyinfra.is_cli = True
            connect_all(state)
            pyinfra.is_cli = False

            # Check the key was created properly
            fake_key_open.assert_called_with(filename='testkey', password='******')
            # Check the certificate file was then loaded
            fake_key.load_certificate.assert_called_with('testkey.pub')
예제 #5
0
    def test_connect_with_rsa_ssh_key_wrong_password(self):
        state = State(make_inventory(hosts=(
            ('somehost', {'ssh_key': 'testkey', 'ssh_key_password': '******'}),
        )), Config())

        with patch(
            'pyinfra.api.connectors.ssh.path.isfile',
            lambda *args, **kwargs: True,
        ), patch(
            'pyinfra.api.connectors.ssh.RSAKey.from_private_key_file',
        ) as fake_key_open:

            def fake_key_open_fail(*args, **kwargs):
                if 'password' not in kwargs:
                    raise PasswordRequiredException
                raise SSHException

            fake_key_open.side_effect = fake_key_open_fail

            fake_key = MagicMock()
            fake_key_open.return_value = fake_key

            state.deploy_dir = '/'

            with self.assertRaises(PyinfraError) as e:
                connect_all(state)

            assert e.exception.args[0] == 'Incorrect password for private key: testkey'
예제 #6
0
    def test_ignore_errors_op_fail(self):
        inventory = make_inventory()
        state = State(inventory, Config())
        connect_all(state)

        add_op(state, server.shell, 'echo "hi"', ignore_errors=True)

        with patch('pyinfra.api.connectors.ssh.run_shell_command'
                   ) as fake_run_command:
            fake_channel = FakeChannel(1)
            fake_run_command.return_value = (
                False,
                FakeBuffer('', fake_channel),
            )

            # This should run OK
            run_ops(state)

        somehost = inventory.get_host('somehost')

        # Ensure the op was added to results
        assert state.results[somehost]['ops'] == 1
        assert state.results[somehost]['error_ops'] == 1
        # But not as a success
        assert state.results[somehost]['success_ops'] == 0
예제 #7
0
    def test_get_file_error(self, fake_get_file):
        fake_ssh_docker_shell.custom_command = [
            "docker cp containerid:not-a-file remote_tempfile",
            False,
            [],
            ["docker error"],
        ]

        inventory = make_inventory(hosts=("@dockerssh/somehost:not-an-image",))
        state = State(inventory, Config())
        state.get_temp_filename = lambda _: "remote_tempfile"

        host = inventory.get_host("@dockerssh/somehost:not-an-image")
        host.connect()

        fake_get_file.return_value = True
        with self.assertRaises(IOError) as ex:
            host.get_file("not-a-file", "not-another-file", print_output=True)

        assert str(ex.exception) == "docker error"

        # SSH error
        fake_ssh_docker_shell.custom_command = [
            "docker cp containerid:not-a-file remote_tempfile",
            True,
            [],
            [],
        ]
        fake_get_file.return_value = False
        with self.assertRaises(IOError) as ex:
            host.get_file("not-a-file", "not-another-file", print_output=True)

        assert str(ex.exception) == "failed to copy file over ssh"
예제 #8
0
def build_global_kwargs_doc():
    pyinfra_config = Config()

    this_dir = path.dirname(path.realpath(__file__))
    docs_dir = path.abspath(path.join(this_dir, '..', 'docs'))

    lines = []

    for category, kwarg_configs in OPERATION_KWARGS.items():
        if category is None:
            continue

        lines.append('{0}:'.format(category))

        for key, config in kwarg_configs.items():
            description = config
            if isinstance(config, dict):
                description = config.get('description')
                default = config.get('default')
                if callable(default):
                    default = default(pyinfra_config)
                if default:
                    key = '{0}={1}'.format(key, default)

            lines.append('    + ``{0}``: {1}'.format(key, description))

    module_filename = path.join(docs_dir, '_deploy_globals.rst')
    print('--> Writing {0}'.format(module_filename))

    out = '\n'.join(lines)

    with open(module_filename, 'w') as outfile:
        outfile.write(out)
예제 #9
0
    def test_run_shell_command(self):
        inventory = make_inventory(hosts=('@local', ))
        State(inventory, Config())
        host = inventory.get_host('@local')

        command = 'echo Šablony'
        self.fake_popen_mock().returncode = 0

        out = host.run_shell_command(command, stdin='hello', print_output=True)
        assert len(out) == 3

        status, stdout, stderr = out
        assert status is True
        self.fake_popen_mock().stdin.write.assert_called_with(b'hello\n')

        combined_out = host.run_shell_command(
            command,
            stdin='hello',
            print_output=True,
            return_combined_output=True,
        )
        assert len(combined_out) == 2

        shell_command = make_unix_command(command).get_raw_value()
        self.fake_popen_mock.assert_called_with(
            shell_command,
            shell=True,
            stdout=PIPE,
            stderr=PIPE,
            stdin=PIPE,
        )
예제 #10
0
    def test_require_pyinfra_requirement_too_low(self):
        with self.assertRaises(PyinfraError) as context:
            with patch("pyinfra.api.config.__version__", "99"):
                Config(REQUIRE_PYINFRA_VERSION=">=100")

        assert context.exception.args[0] == (
            "pyinfra version requirement not met (requires >=100, running 99)")
예제 #11
0
    def __init__(self,
                 make_names_data=make_names_data_local,
                 general_facts={},
                 fail_percent=100,
                 connect_timeout=5,
                 ):
        hosts = []
        groups = defaultdict(lambda: ([], {}))

        names_data = make_names_data() if callable(
            make_names_data) else make_names_data

        for name, data, group_names in names_data:
            hosts.append((name, data))
            for group_name in group_names:
                if name not in groups[group_name][0]:
                    groups[group_name][0].append(name)

        for host in hosts:
            for fact_name, fact in general_facts.items():
                host[1][fact_name] = fact

        # First we setup some inventory we want to target
        # the first argument is a tuple of (list all all hosts, global/ALL data)
        self.inventory = Inventory((hosts, {}), **groups)

        # Now we create a new config (w/optional args)
        self.config = Config(
            FAIL_PERCENT=fail_percent,
            CONNECT_TIMEOUT=connect_timeout,
        )

        # Setup the pyinfra state for this deploy
        self.state = State(self.inventory, self.config)
예제 #12
0
    def test_run_shell_command(self):
        fake_winrm_session = MagicMock()

        fake_winrm = MagicMock()
        fake_stdin = MagicMock()
        fake_stdout = MagicMock()
        fake_winrm.run_cmd.return_value = fake_stdin, fake_stdout, MagicMock()

        fake_winrm_session.return_value = fake_winrm

        inventory = make_inventory(hosts=('@winrm/somehost', ))
        State(inventory, Config())
        host = inventory.get_host('@winrm/somehost')
        host.connect()

        command = 'echo hi'

        out = host.run_shell_command(command, stdin='hello', print_output=True)
        assert len(out) == 3

        status, stdout, stderr = out
        # TODO: assert status is True

        combined_out = host.run_shell_command(
            command,
            print_output=True,
            return_combined_output=True,
        )
        assert len(combined_out) == 2
예제 #13
0
    def test_connect_all_error(self):
        inventory = make_inventory(
            hosts=('@dockerssh/somehost:a-broken-image', ))
        state = State(inventory, Config())

        with self.assertRaises(PyinfraError):
            connect_all(state)
예제 #14
0
    def test_get_fact_error(self):
        inventory = make_inventory(hosts=('anotherhost', ))
        state = State(inventory, Config())

        anotherhost = inventory.get_host('anotherhost')

        connect_all(state)

        with patch('pyinfra.api.connectors.ssh.run_shell_command'
                   ) as fake_run_command:
            fake_run_command.return_value = False, MagicMock(), MagicMock()

            with self.assertRaises(PyinfraError) as context:
                get_facts(state, 'command', ('fail command', ))

        assert context.exception.args[0] == 'No hosts remaining!'

        fake_run_command.assert_called_with(
            state,
            anotherhost,
            'fail command',
            print_input=False,
            print_output=False,
            shell_executable=None,
            su_user=None,
            sudo=False,
            sudo_user=None,
            timeout=None,
            use_sudo_password=False,
        )
예제 #15
0
    def test_rsync_op(self):
        inventory = make_inventory(hosts=('somehost', ))
        state = State(inventory, Config())
        connect_all(state)

        with patch('pyinfra.api.connectors.ssh.check_can_rsync'):
            add_op(state,
                   files.rsync,
                   'src',
                   'dest',
                   sudo=True,
                   sudo_user='******')

        assert len(state.get_op_order()) == 1

        with patch('pyinfra.api.connectors.ssh.run_local_process'
                   ) as fake_run_local_process:
            fake_run_local_process.return_value = 0, []
            run_ops(state)

        fake_run_local_process.assert_called_with(
            ('rsync -ax --delete --rsh '
             "'ssh -o BatchMode=yes -o StrictHostKeyChecking=no '"
             " --rsync-path 'sudo -u root rsync' src vagrant@somehost:dest"),
            print_output=False,
            print_prefix=inventory.get_host('somehost').print_prefix,
        )
예제 #16
0
    def test_run_shell_command_masked(self, fake_click):
        inventory = make_inventory(hosts=('@local', ))
        State(inventory, Config())
        host = inventory.get_host('@local')

        command = StringCommand('echo', MaskString('top-secret-stuff'))
        self.fake_popen_mock().returncode = 0

        out = host.run_shell_command(command,
                                     print_output=True,
                                     print_input=True)
        assert len(out) == 3

        status, stdout, stderr = out
        assert status is True

        self.fake_popen_mock.assert_called_with(
            "sh -c 'echo top-secret-stuff'",
            shell=True,
            stdout=PIPE,
            stderr=PIPE,
            stdin=PIPE,
        )

        fake_click.echo.assert_called_with(
            "{0}>>> sh -c 'echo ***'".format(host.print_prefix),
            err=True,
        )
예제 #17
0
    def test_full_op_fail(self):
        inventory = make_inventory()
        state = State(inventory, Config())
        connect_all(state)

        add_op(state, server.shell, 'echo "hi"')

        with patch('pyinfra.api.connectors.ssh.run_shell_command'
                   ) as fake_run_command:
            fake_channel = FakeChannel(1)
            fake_run_command.return_value = (
                False,
                FakeBuffer('', fake_channel),
            )

            with self.assertRaises(PyinfraError) as e:
                run_ops(state)

            assert e.exception.args[0] == 'No hosts remaining!'

            somehost = inventory.get_host('somehost')

            # Ensure the op was not flagged as success
            assert state.results[somehost]['success_ops'] == 0
            # And was flagged asn an error
            assert state.results[somehost]['error_ops'] == 1
예제 #18
0
파일: test_api.py 프로젝트: xcitic/pyinfra
    def test_connect_with_ssh_key(self):
        state = State(make_inventory(hosts=(
            ('somehost', {'ssh_key': 'testkey'}),
        )), Config())

        with patch('pyinfra.api.ssh.path.isfile', lambda *args, **kwargs: True), \
                patch('pyinfra.api.ssh.RSAKey.from_private_key_file') as fake_key_open:

            fake_key = FakeRSAKey()
            fake_key_open.return_value = fake_key

            state.deploy_dir = '/'

            connect_all(state)

            # Check the key was created properly
            fake_key_open.assert_called_with(filename='testkey')

            # And check the Paramiko SSH call was correct
            self.fake_connect_mock.assert_called_with(
                'somehost',
                allow_agent=False,
                look_for_keys=False,
                pkey=fake_key,
                port=22,
                timeout=10,
                username='******'
            )
예제 #19
0
 def test_connect_disconnect_host(self):
     inventory = make_inventory(hosts=("@dockerssh/somehost:not-an-image",))
     state = State(inventory, Config())
     host = inventory.get_host("@dockerssh/somehost:not-an-image")
     host.connect(reason=True)
     assert len(state.active_hosts) == 0
     host.disconnect()
예제 #20
0
파일: test_api.py 프로젝트: xcitic/pyinfra
    def test_pseudo_op(self):
        inventory = make_inventory()
        state = State(inventory, Config())
        connect_all(state)

        pseudo_state.set(state)
        pseudo_host.set(inventory['somehost'])

        # Exceute the op "bare"
        server.shell('echo "hi"')

        # Ensure this is ignored
        state.active = False
        server.shell('echo "hi 2"')

        # We should now have one op
        self.assertEqual(len(state.op_order), 1)

        # Ensure only somehost has actual op
        self.assertEqual(len(state.ops['somehost']), 1)
        self.assertEqual(len(state.ops['anotherhost']), 0)

        # Check we can't call it inside another op
        state.active = True
        state.in_op = True
        with self.assertRaises(PyinfraError):
            server.shell('echo "hi 3"')

        pseudo_state.reset()
        pseudo_host.reset()
예제 #21
0
    def test_connect_with_ssh_key_password(self):
        state = State(
            make_inventory(hosts=(('somehost', {
                'ssh_key': 'testkey',
                'ssh_key_password': '******'
            }), )), Config())

        with patch(
                'pyinfra.api.connectors.ssh.path.isfile',
                lambda *args, **kwargs: True,
        ), patch('pyinfra.api.connectors.ssh.RSAKey.from_private_key_file',
                 ) as fake_key_open:

            def fake_key_open_fail(*args, **kwargs):
                if 'password' not in kwargs:
                    raise PasswordRequiredException()

            fake_key_open.side_effect = fake_key_open_fail

            fake_key = FakeRSAKey()
            fake_key_open.return_value = fake_key

            state.deploy_dir = '/'

            connect_all(state)

            # Check the key was created properly
            fake_key_open.assert_called_with(filename='testkey',
                                             password='******')
예제 #22
0
    def test_run_shell_command(self):
        inventory = make_inventory(hosts=('@chroot/not-a-chroot', ))
        state = State(inventory, Config())
        host = inventory.get_host('@chroot/not-a-chroot')
        host.connect(state)

        command = 'echo hoi'
        self.fake_popen_mock().returncode = 0
        out = host.run_shell_command(
            state,
            command,
            stdin='hello',
            get_pty=True,
            print_output=True,
        )
        assert len(out) == 3
        assert out[0] is True

        command, _ = make_unix_command(command)
        command = shlex_quote(command)
        docker_command = 'chroot /not-a-chroot sh -c {0}'.format(command)
        shell_command, _ = make_unix_command(docker_command)

        self.fake_popen_mock.assert_called_with(
            shell_command,
            shell=True,
            stdout=PIPE,
            stderr=PIPE,
            stdin=PIPE,
        )
예제 #23
0
    def test_connect_with_rsa_ssh_key_missing_password(self):
        state = State(make_inventory(hosts=(
            ('somehost', {'ssh_key': 'testkey'}),
        )), Config())

        with patch(
            'pyinfra.api.connectors.ssh.path.isfile',
            lambda *args, **kwargs: True,
        ), patch(
            'pyinfra.api.connectors.ssh.RSAKey.from_private_key_file',
        ) as fake_key_open:

            def fake_key_open_fail(*args, **kwargs):
                raise PasswordRequiredException

            fake_key_open.side_effect = fake_key_open_fail

            fake_key = MagicMock()
            fake_key_open.return_value = fake_key

            state.deploy_dir = '/'

            with self.assertRaises(PyinfraError) as e:
                connect_all(state)

            assert e.exception.args[0] == (
                'Private key file (testkey) is encrypted, set ssh_key_password '
                'to use this key'
            )
예제 #24
0
 def test_connect_disconnect_host(self):
     inventory = make_inventory(hosts=('@docker/not-an-image', ))
     state = State(inventory, Config())
     host = inventory.get_host('@docker/not-an-image')
     host.connect(for_fact=True)
     assert len(state.active_hosts) == 0
     host.disconnect()
예제 #25
0
    def test_run_shell_command(self, fake_ssh_client):
        fake_ssh = MagicMock()
        fake_stdin = MagicMock()
        fake_stdout = MagicMock()
        fake_ssh.exec_command.return_value = fake_stdin, fake_stdout, MagicMock()

        fake_ssh_client.return_value = fake_ssh

        inventory = make_inventory(hosts=('somehost',))
        State(inventory, Config())
        host = inventory.get_host('somehost')
        host.connect()

        command = 'echo Šablony'
        fake_stdout.channel.recv_exit_status.return_value = 0

        out = host.run_shell_command(command, stdin='hello', print_output=True)
        assert len(out) == 3

        status, stdout, stderr = out
        assert status is True
        fake_stdin.write.assert_called_with(b'hello\n')

        combined_out = host.run_shell_command(
            command, stdin='hello', print_output=True,
            return_combined_output=True,
        )
        assert len(combined_out) == 2

        fake_ssh.exec_command.assert_called_with("sh -c 'echo Šablony'", get_pty=False)
예제 #26
0
    def test_run_shell_command(self):
        inventory = make_inventory(hosts=('@docker/not-an-image', ))
        State(inventory, Config())

        command = 'echo hi'
        self.fake_popen_mock().returncode = 0

        host = inventory.get_host('@docker/not-an-image')
        host.connect()
        out = host.run_shell_command(
            command,
            stdin='hello',
            get_pty=True,
            print_output=True,
        )
        assert len(out) == 3
        assert out[0] is True

        command = make_unix_command(command).get_raw_value()
        command = shlex_quote(command)
        docker_command = 'docker exec -it containerid sh -c {0}'.format(
            command)
        shell_command = make_unix_command(docker_command).get_raw_value()

        self.fake_popen_mock.assert_called_with(
            shell_command,
            shell=True,
            stdout=PIPE,
            stderr=PIPE,
            stdin=PIPE,
        )
예제 #27
0
    def test_put_file_su_user_fail(self, fake_sftp_client, fake_ssh_client):
        inventory = make_inventory(hosts=('anotherhost',))
        State(inventory, Config())
        host = inventory.get_host('anotherhost')
        host.connect()

        stdout_mock = MagicMock()
        stdout_mock.channel.recv_exit_status.return_value = 1
        fake_ssh_client().exec_command.return_value = MagicMock(), stdout_mock, MagicMock()

        fake_open = mock_open(read_data='test!')
        with patch('pyinfra.api.util.open', fake_open, create=True):
            status = host.put_file(
                'not-a-file', 'not-another-file',
                print_output=True,
                su_user='******',
            )

        assert status is False

        fake_ssh_client().exec_command.assert_called_with((
            "su centos -s `which sh` -c 'mv "
            '/tmp/pyinfra-43db9984686317089fefcf2e38de527e4cb44487 '
            "not-another-file && chown centos not-another-file'"
        ), get_pty=False)

        fake_sftp_client.from_transport().putfo.assert_called_with(
            fake_open(), '/tmp/pyinfra-43db9984686317089fefcf2e38de527e4cb44487',
        )
예제 #28
0
    def test_op_state_hosts_limit(self):
        inventory = make_inventory()
        state = State(inventory, Config())
        connect_all(state)

        # Add op to both hosts
        add_op(state, server.shell, 'echo "hi"')

        # Add op to just the first host
        with state.hosts('test_group'):
            add_op(
                state,
                server.user,
                'somehost_user',
            )

            # Now, also limited but set hosts to the non-limited hosts, which
            # should mean this operation applies to no hosts.
            add_op(
                state,
                server.user,
                'somehost_user',
                hosts=inventory.get_host('anotherhost'),
            )

        # Ensure there are three ops
        assert len(state.get_op_order()) == 3

        # Ensure somehost has two ops and anotherhost only has the one
        assert len(state.ops[inventory.get_host('somehost')]) == 2
        assert len(state.ops[inventory.get_host('anotherhost')]) == 1
예제 #29
0
    def test_get_file_su_user(self, fake_sftp_client, fake_ssh_client):
        inventory = make_inventory(hosts=('somehost',))
        State(inventory, Config())
        host = inventory.get_host('somehost')
        host.connect()

        stdout_mock = MagicMock()
        stdout_mock.channel.recv_exit_status.return_value = 0
        fake_ssh_client().exec_command.return_value = MagicMock(), stdout_mock, MagicMock()

        fake_open = mock_open(read_data='test!')
        with patch('pyinfra.api.util.open', fake_open, create=True):
            status = host.get_file(
                'not-a-file', 'not-another-file',
                print_output=True,
                su_user='******',
            )

        assert status is True

        fake_ssh_client().exec_command.assert_has_calls([
            call((
                "su centos -s `which sh` -c 'cp not-a-file "
                "/tmp/pyinfra-e9c0d3c8ffca943daa0e75511b0a09c84b59c508 && chmod +r not-a-file'"
            ), get_pty=False),
            call((
                "su centos -s `which sh` -c 'rm -f "
                "/tmp/pyinfra-e9c0d3c8ffca943daa0e75511b0a09c84b59c508'"
            ), get_pty=False),
        ])

        fake_sftp_client.from_transport().getfo.assert_called_with(
            '/tmp/pyinfra-e9c0d3c8ffca943daa0e75511b0a09c84b59c508', fake_open(),
        )
예제 #30
0
    def test_get_fact_error(self):
        inventory = make_inventory(hosts=("anotherhost", ))
        state = State(inventory, Config())

        anotherhost = inventory.get_host("anotherhost")

        connect_all(state)

        with patch("pyinfra.connectors.ssh.run_shell_command"
                   ) as fake_run_command:
            fake_run_command.return_value = False, MagicMock()

            with self.assertRaises(PyinfraError) as context:
                get_facts(state, Command, ("fail command", ))

        assert context.exception.args[0] == "No hosts remaining!"

        fake_run_command.assert_called_with(
            state,
            anotherhost,
            "fail command",
            print_input=False,
            print_output=False,
            return_combined_output=True,
            **_get_executor_defaults(state, anotherhost),
        )