ansible / proposals

Repository for sharing and tracking progress on enhancement proposals for Ansible.
Creative Commons Zero v1.0 Universal
93 stars 19 forks source link

Copy in files to docker volume #16

Closed ToBeReplaced closed 8 years ago

ToBeReplaced commented 8 years ago

NOTE: This doesn't feel like a proposal, but rather a modification of an existing proposal. How should I have formatted this?

Most of the time that I want to create a new docker volume, it's to add configuration files to the volume before I start a container that uses it. Doing this with ansible is clunky right now. Here is an example that creates a volume "example_volume" and adds "example.j2" to it.

- name: Create a container with a new data volume
  docker:
    name: container
    image: centos:7
    detach: no
    volumes:
      - example_volume:/data
  become: yes

- name: Copy over the template
  template: src=example.j2 dest=/tmp/example
  become: yes

- name: Copy in the template
  command: docker cp /tmp/example container:/data/
  become: yes

- name: Remove the template
  file: path=/tmp/example state=absent
  become: yes

- name: Remove the hanging container
  docker:
    name: container
    image: centos:7
    state: absent
  become: yes

Is this behavior useful to others? Should it happen in docker_volume? Is it more of a "docker_copy" (and docker_template, docker_fetch)? Ex:

# Result is example.j2 has been templated and resides at /example on my_volume
- name: Copy in a template
  docker_template:
    src=example.j2
    dest=/example
    volume=my_volume
    image=centos:7
chouseknecht commented 8 years ago

I think this is covered in proposal for docker_file.

ToBeReplaced commented 8 years ago

Yes, looks like that is where the discussion belongs; the "open issue" referenced there is now closed. Where should I be submit the above feedback? (remote files instead of local files, template handling, fetch vs. copy)?

sivel commented 8 years ago

Also, just as reference, the docker connection plugin, would also allow support for using any of the various existing modules such as copy or template for copying into a container.

ToBeReplaced commented 8 years ago

Okay so I still don't know where to submit feedback. The proposals do not meet my current business need, which is copying templates and files into remote docker containers. Please note that "docker_file" will not do what I am looking for.

Here is what I'm doing in my infrastructure:

1) Copy the "copy" and "template" action plugins to create "docker_copy" and "docker_template". 2) Replace instances of "copy" module with "docker_copy"; sed -e "s/module_name='copy'/module_name='docker_copy'/" <infile> 3) Create a docker_copy module as follows (proof-of-concept):

#!/usr/bin/python
"""Copy a file into a docker container."""
from os import path
import shutil
import subprocess
import tempfile

# pylint: disable=wildcard-import,import-error
from ansible.module_utils.basic import *
# pylint: enable=wildcard-import,import-error

def main():
    """Copy a file into a docker container."""
    # pylint: disable=undefined-variable
    module = AnsibleModule(
        argument_spec=dict(
            src=dict(required=True),
            dest=dict(required=True),
            container=dict(required=True),
            original_basename=dict(required=False)),
        add_file_common_args=True)
    # pylint: enable=undefined-variable

    src = module.params['src']
    dest = module.params['dest']
    container = module.params['container']

    if not path.exists(src):
        module.fail_json(msg="Source %s not found" % (src))

    changed = False
    tmpdir = tempfile.mkdtemp()
    try:
        tmpdest = path.join(tmpdir, path.basename(dest))
        try:
            subprocess.check_call(
                ('docker', 'cp', '{}:{}'.format(container, dest), tmpdest))
        except subprocess.CalledProcessError:
            with open(tmpdest, 'w'):
                pass

        checksum_src = module.sha1(src)
        checksum_dest = module.sha1(tmpdest)
        if checksum_src != checksum_dest:
            changed = True
            module.atomic_move(src, tmpdest)

        module.params['dest'] = tmpdest
        changed = module.set_fs_attributes_if_different(
            module.load_file_common_arguments(module.params), changed)
        if changed:
            subprocess.check_call(
                ('docker', 'cp', tmpdest, '{}:{}'.format(container, dest)))

    finally:
        shutil.rmtree(tmpdir)

    module.exit_json(changed=changed)

if __name__ == '__main__':
    main()

Now I can template and copy into a remote docker container without leaving cruft behind.

- docker_copy:
    src=data
    dest=/data
    container=test-container
    mode=0644
- docker_template:
    src=template.j2
    dest=/template
    container=test-container
    mode=0600
sivel commented 8 years ago

@ToBeReplaced, I believe my comment addresses that, where you would use the docker connection type, and utilize pre-existing modules for templates and files.

See http://docs.ansible.com/ansible/intro_inventory.html#non-ssh-connection-types

ToBeReplaced commented 8 years ago

@sivel Can you explain exactly how that works on a remote host as opposed to the master? As far as I know, you can only use the connection plugin on the master.

I'm looking for an example that copies file X from master to container Y on host Z.

ToBeReplaced commented 8 years ago

Maybe I typed too soon... it looks like you can do it if you expose your docker daemon to the network. I'd rather not do that (I'd rather trust freeipa for policy than docker...), but I get it. I guess we can leave this be then. I'll keep using a module that works without networked docker and expect that ansible will continue developing under the assumption of networked docker.

si-net commented 3 years ago

I think this issue is resolved through: https://docs.ansible.com/ansible/latest/collections/community/docker/docker_container_module.html#parameter-mounts