def main():
    argument_spec = dict(
        container=dict(type='str', required=True),
        argv=dict(type='list', elements='str'),
        command=dict(type='str'),
        chdir=dict(type='str'),
        detach=dict(type='bool', default=False),
        user=dict(type='str'),
        stdin=dict(type='str'),
        stdin_add_newline=dict(type='bool', default=True),
        strip_empty_ends=dict(type='bool', default=True),
        tty=dict(type='bool', default=False),
        env=dict(type='dict'),
    )

    option_minimal_versions = dict(
        chdir=dict(docker_py_version='3.0.0', docker_api_version='1.35'),
        env=dict(docker_py_version='2.3.0', docker_api_version='1.25'),
    )

    client = AnsibleDockerClient(
        argument_spec=argument_spec,
        option_minimal_versions=option_minimal_versions,
        min_docker_api_version='1.20',
        mutually_exclusive=[('argv', 'command')],
        required_one_of=[('argv', 'command')],
    )

    container = client.module.params['container']
    argv = client.module.params['argv']
    command = client.module.params['command']
    chdir = client.module.params['chdir']
    detach = client.module.params['detach']
    user = client.module.params['user']
    stdin = client.module.params['stdin']
    strip_empty_ends = client.module.params['strip_empty_ends']
    tty = client.module.params['tty']
    env = client.module.params['env']

    if env is not None:
        for name, value in list(env.items()):
            if not isinstance(value, string_types):
                client.module.fail_json(
                    msg=
                    "Non-string value found for env option. Ambiguous env options must be "
                    "wrapped in quotes to avoid them being interpreted. Key: %s"
                    % (name, ))
            env[name] = to_text(value, errors='surrogate_or_strict')

    if command is not None:
        argv = shlex.split(command)

    if detach and stdin is not None:
        client.module.fail_json(
            msg='If detach=true, stdin cannot be provided.')

    if stdin is not None and client.module.params['stdin_add_newline']:
        stdin += '\n'

    selectors = None
    if stdin and not detach:
        selectors = find_selectors(client.module)

    try:
        kwargs = {}
        if chdir is not None:
            kwargs['workdir'] = chdir
        if env is not None:
            kwargs['environment'] = env
        exec_data = client.exec_create(container,
                                       argv,
                                       stdout=True,
                                       stderr=True,
                                       stdin=bool(stdin),
                                       user=user or '',
                                       **kwargs)
        exec_id = exec_data['Id']

        if detach:
            client.exec_start(exec_id, tty=tty, detach=True)
            client.module.exit_json(changed=True, exec_id=exec_id)

        else:
            if selectors:
                exec_socket = client.exec_start(
                    exec_id,
                    tty=tty,
                    detach=False,
                    socket=True,
                )
                try:
                    with DockerSocketHandlerModule(
                            exec_socket, client.module,
                            selectors) as exec_socket_handler:
                        if stdin:
                            exec_socket_handler.write(to_bytes(stdin))

                        stdout, stderr = exec_socket_handler.consume()
                finally:
                    exec_socket.close()
            else:
                stdout, stderr = client.exec_start(
                    exec_id,
                    tty=tty,
                    detach=False,
                    stream=False,
                    socket=False,
                    demux=True,
                )

            result = client.exec_inspect(exec_id)

            stdout = to_text(stdout or b'')
            stderr = to_text(stderr or b'')
            if strip_empty_ends:
                stdout = stdout.rstrip('\r\n')
                stderr = stderr.rstrip('\r\n')

            client.module.exit_json(
                changed=True,
                stdout=stdout,
                stderr=stderr,
                rc=result.get('ExitCode') or 0,
            )
    except NotFound:
        client.fail('Could not find container "{0}"'.format(container))
    except APIError as e:
        if e.response and e.response.status_code == 409:
            client.fail('The container "{0}" has been paused ({1})'.format(
                container, to_native(e)))
        client.fail('An unexpected docker error occurred: {0}'.format(
            to_native(e)),
                    exception=traceback.format_exc())
    except DockerException as e:
        client.fail('An unexpected docker error occurred: {0}'.format(
            to_native(e)),
                    exception=traceback.format_exc())
    except RequestException as e:
        client.fail(
            'An unexpected requests error occurred when docker-py tried to talk to the docker daemon: {0}'
            .format(to_native(e)),
            exception=traceback.format_exc())
Esempio n. 2
0
def main():
    argument_spec = dict(
        container=dict(type='str', required=True),
        argv=dict(type='list', elements='str'),
        command=dict(type='str'),
        chdir=dict(type='str'),
        user=dict(type='str'),
        stdin=dict(type='str'),
        stdin_add_newline=dict(type='bool', default=True),
        strip_empty_ends=dict(type='bool', default=True),
        tty=dict(type='bool', default=False),
    )

    client = AnsibleDockerClient(
        argument_spec=argument_spec,
        min_docker_api_version='1.20',
        mutually_exclusive=[('argv', 'command')],
        required_one_of=[('argv', 'command')],
    )

    container = client.module.params['container']
    argv = client.module.params['argv']
    command = client.module.params['command']
    chdir = client.module.params['chdir']
    user = client.module.params['user']
    stdin = client.module.params['stdin']
    strip_empty_ends = client.module.params['strip_empty_ends']
    tty = client.module.params['tty']

    if command is not None:
        argv = shlex.split(command)

    if stdin is not None and client.module.params['stdin_add_newline']:
        stdin += '\n'

    selectors = None
    if stdin:
        selectors = find_selectors(client.module)

    try:
        exec_data = client.exec_create(
            container,
            argv,
            stdout=True,
            stderr=True,
            stdin=bool(stdin),
            user=user or '',
            workdir=chdir,
        )
        exec_id = exec_data['Id']

        if selectors:
            exec_socket = client.exec_start(
                exec_id,
                tty=tty,
                detach=False,
                socket=True,
            )
            try:
                with DockerSocketHandlerModule(
                        exec_socket, client.module,
                        selectors) as exec_socket_handler:
                    if stdin:
                        exec_socket_handler.write(to_bytes(stdin))

                    stdout, stderr = exec_socket_handler.consume()
            finally:
                exec_socket.close()
        else:
            stdout, stderr = client.exec_start(
                exec_id,
                tty=tty,
                detach=False,
                stream=False,
                socket=False,
                demux=True,
            )

        result = client.exec_inspect(exec_id)

        stdout = to_text(stdout or b'')
        stderr = to_text(stderr or b'')
        if strip_empty_ends:
            stdout = stdout.rstrip('\r\n')
            stderr = stderr.rstrip('\r\n')

        client.module.exit_json(
            changed=True,
            stdout=stdout,
            stderr=stderr,
            rc=result.get('ExitCode') or 0,
        )
    except NotFound:
        client.fail('Could not find container "{0}"'.format(container))
    except APIError as e:
        if e.response and e.response.status_code == 409:
            client.fail('The container "{0}" has been paused ({1})'.format(
                container, to_native(e)))
        client.fail('An unexpected docker error occurred: {0}'.format(
            to_native(e)),
                    exception=traceback.format_exc())
    except DockerException as e:
        client.fail('An unexpected docker error occurred: {0}'.format(
            to_native(e)),
                    exception=traceback.format_exc())
    except RequestException as e:
        client.fail(
            'An unexpected requests error occurred when docker-py tried to talk to the docker daemon: {0}'
            .format(to_native(e)),
            exception=traceback.format_exc())