Ansible molecule using docker - how to specify memory limit - docker

I have a molecule test which spins up 2 Docker containers, for testing 2 application versions at once.
dependency:
name: galaxy
driver:
name: docker
lint:
name: yamllint
platforms:
- name: molecule1
hostname: molecule1
image: "geerlingguy/docker-${MOLECULE_DISTRO:-centos7}-ansible:latest"
command: ${MOLECULE_DOCKER_COMMAND:-""}
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
privileged: true
pre_build_image: true
- name: molecule2
hostname: molecule2
image: "geerlingguy/docker-${MOLECULE_DISTRO:-centos7}-ansible:latest"
command: ${MOLECULE_DOCKER_COMMAND:-""}
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
privileged: true
pre_build_image: true
provisioner:
name: ansible
inventory:
host_vars:
molecule1:
app_version: "v1"
molecule2:
app_version: "v2"
lint:
name: ansible-lint
scenario:
name: default
converge_sequence:
- syntax
- lint
- create
- prepare
- converge
- idempotence
- verify
verifier:
name: goss
lint:
name: yamllint
I am looking for a way to specify the memory like -m or --memory= as described here.
I understand that molecule makes use of the docker_container ansible module, which support the memory parameter, but somehow I cannot find a way to make this work in molecule.
Any ideas how to accomplish this?
PS: My guess is that this parameter is not yet implemented in molecule, if my assumption is correct that this is the implementation.
Thanks in advance.

++Update++
--memory is indeed not yet implemented in molecule docker provisioner.
If anybody is interested, here is the relevant change to the source code:
diff --git a/molecule/provisioner/ansible/playbooks/docker/create.yml b/molecule/provisioner/ansible/playbooks/docker/create.yml
index 7a04b851..023a720a 100644
--- a/molecule/provisioner/ansible/playbooks/docker/create.yml
+++ b/molecule/provisioner/ansible/playbooks/docker/create.yml
## -121,6 +121,8 ##
hostname: "{{ item.hostname | default(item.name) }}"
image: "{{ item.pre_build_image | default(false) | ternary('', 'molecule_local/') }}{{ item.image }}"
pull: "{{ item.pull | default(omit) }}"
+ kernel_memory: "{{ item.kernel_memory | default(omit) }}"
+ memory: "{{ item.memory | default(omit) }}"
state: started
recreate: false
log_driver: json-file
My fork has now been merged to Molecule.

Related

Ansible validate docker-compose with env_file and send to host

I created a role that has in template folder two files: docker-compose.yml.j2 and env.j2
env.j2 is used in docker-compose file:
version: "2"
services:
service_name:
image: {{ IMAGE | mandatory }}
container_name: service_name
mem_limit: 256m
user: "2001"
env_file: ".env"
Now my question: is there some ansible module that sends docker-compose file to host and there validate it because than env and docker-compose are in same folder on host machine?
This example of ansible task return error because env file is not in template folder but on host.
- name: "Copy env file"
ansible.builtin.template:
src: "env.j2"
dest: "/opt/db_backup/.env"
mode: '770'
owner: deployment
group: deployment
- name: "Validate and copy docker compose file"
ansible.builtin.template:
src: "docker-compose.yml.j2"
dest: "/opt/db_backup/docker-compose.yml"
mode: '770'
owner: deployment
group: deployment
validate: docker-compose -f %s config
This probably falls into the Complex validation configuration cases linked in the documentation for the template module validate parameter
In any case, unless refactoring completely your current file and passing more variables in your environment (e.g. to allow .env being in a location out of the current directory), you cannot validate docker-compose.yml until both files are in the same location.
An easy scenario would be to copy both files in place, validate prior to doing anything with them and roll back to the previous version in case of error. The below example is far from rocket proof but will give you an idea:
---
- hosts: localhost
gather_facts: false
vars:
IMAGE: alpine:latest
deploy_dir: /tmp/validate_compose
tasks:
- name: "make sure {{ deploy_dir }} directory exits"
file:
path: "{{ deploy_dir }}"
state: directory
- name: copy project file templates
template:
src: "{{ item }}"
dest: "{{ deploy_dir }}/{{ item | regex_replace('^(.*)\\.j2', '\\g<1>') }}"
mode: 0640
backup: true
loop:
- .env.j2
- docker-compose.yml.j2
register: copy_files
- block:
- name: check docker-compose file validity
command:
cmd: docker-compose config
chdir: "{{ deploy_dir }}"
rescue:
- name: rollback configuration to previous version for changed files
copy:
src: "{{ item.backup_file }}"
dest: "{{ item.dest }}"
remote_src: true
loop: "{{ copy_files.results | selectattr('backup_file', 'defined') }}"
- name: Give some info about error.
debug:
msg:
- The compose file did not validate.
- Please see previous error above for details
- Files have been rolled back to the latest known version.
- name: Fail
fail:
- name: Rest of the playbook using the above validated files
debug:
msg: Next tasks...

Retrieve docker container output with ansible using list

I need to retrieve the output of a docker command on ansible, it's easy when running a single instance but I'm running the command using with_dict:
I'm using something like
- name: Running task
docker_container:
command: <<here my command>>
detach: false
recreate: true
restart: false
restart_policy: "no"
with_dict: "{{ mylist.config.validator_client.accounts }}"
register: mycontainers
I've tried the following with no success:
- name: display logs
debug:
msg: "{{ item.ansible_facts.docker_container.Output }}"
with_items: "{{ mycontainers.results }}"
Any idea?

docker_container: How to add multiple Volumes

I am trying to execute with Ansible the following Docker command:
docker run --name soadb_test1 --network=soa_net --ip 172.16.1.10 -d -v $TEST1/SOADB-Volume/u01:/u01/ -v $TEST1/SOADB-Volume/u02:/u02/ -v $TEST1/SOADB-Volume/u03:/u03/ -v $TEST1/SOADB-Volume/u04:/u04/ -v $TEST1/SOADB-Volume/ORCL:/ORCL/ --env-file $ENV_HOME/db.env.list database/enterprise:12.2.0.1
This is my Ansible Script:
---
- name: Create DB container
docker_container:
name: "{{ name }}"
image: "{{ image }}"
env_file: "{{ env_file }}"
detach: yes
volumes:
- "{{ src_vol }}:{{ dest_vol }}"
- "{{ src_vol_2 }}:{{ dest_vol_2 }}"
- "{{ src_vol_3 }}:{{ dest_vol_3 }}"
- "{{ src_vol_4 }}:{{ dest_vol_4 }}"
- "{{ src_vol_5 }}:{{ dest_vol_5 }}"
networks:
- name: soa_net
ipv4_address: "{{ ip }}"
vars_files:
- vars.yml
When I run it I get the following error:
TASK [install_docker_DB : Create DB container] *******************************************************************************************************************************************************************
fatal: [soa_poc]: FAILED! => {"changed": false, "msg": "Unsupported parameters for (docker_container) module: vars_files Supported parameters include: api_version, auto_remove, blkio_weight, cacert_path, cap_drop, capabilities, cert_path, cleanup, command, cpu_period, cpu_quota, cpu_shares, cpuset_cpus, cpuset_mems, debug, detach, devices, dns_opts, dns_search_domains, dns_servers, docker_host, domainname, entrypoint, env, env_file, etc_hosts, exposed_ports, force_kill, groups, hostname, ignore_image, image, init, interactive, ipc_mode, keep_volumes, kernel_memory, key_path, kill_signal, labels, links, log_driver, log_options, mac_address, memory, memory_reservation, memory_swap, memory_swappiness, name, network_mode, networks, oom_killer, oom_score_adj, output_logs, paused, pid_mode, privileged, published_ports, pull, purge_networks, read_only, recreate, restart, restart_policy, restart_retries, security_opts, shm_size, ssl_version, state, stop_signal, stop_timeout, sysctls, timeout, tls, tls_hostname, tls_verify, tmpfs, trust_image_content, tty, ulimits, user, userns_mode, uts, volume_driver, volumes, volumes_from, working_dir"}
Am i declaring the volumes the wrong way?
It looks like your indentation level for the vars_files entry is wrong - please move it to somewhere else:
---
- name: Create DB container
docker_container:
name: "{{ name }}"
image: "{{ image }}"
env_file: "{{ env_file }}"
detach: yes
volumes:
- "{{ src_vol }}:{{ dest_vol }}"
- "{{ src_vol_2 }}:{{ dest_vol_2 }}"
- "{{ src_vol_3 }}:{{ dest_vol_3 }}"
- "{{ src_vol_4 }}:{{ dest_vol_4 }}"
- "{{ src_vol_5 }}:{{ dest_vol_5 }}"
networks:
- name: soa_net
ipv4_address: "{{ ip }}"
The indentation for the first network entry was also wrong.
Depending on whether the above is from a playbook file, or from a role, the location of vars_files might differ. If this is a playbook, then vars_files should be at the same indentation level as tasks:
---
- hosts: all
vars_files:
- vars.yml
tasks:
- name: Create DB container
docker_container: ...
This has nothing to do with the volumes...

Write conditional docker properties in Ansible module

I'm trying to write conditional properties in the Ansible module docker_container. For example adding log_options when a var is set. Any idea? Ansible doesn't seem very elastic in this task.
name: vault
become: yes
docker_container:
name: vault
image: vault
state: started
restart: yes
network_mode: host
command: server
capabilities:
- IPC_LOCK
You may want to read about omitting parameters:
docker_container:
...
log_options: "{{ my_log_opts | default(omit) }}"
...

How to use Docker link in Ansible when link var defined

I want playbook that will start an container (in a task) and only link it to another container if the link is provided in a variable. For example:
- name: Start container
docker_container:
image: somerepo/app-server:{{ var_tag }}
name: odoo-server
state: started
log_opt: "tag=app-server-{{ var_tag }}"
expose:
- 8080
links:
- "{{ var_db_link }}"
when: var_db_link is defined
But of course this does not work. (I know - without a value is invalid ~ this is just pseudo code)
The whole task is actually quite a bit larger because it includes other directives so I really don't to have 2 versions of the task defined, one for starting with a link and another without.
when use '-', it means there is certain value , so I have a way to avoid it.
---
- hosts: localhost
tasks:
- name: Start container
docker_container:
image: centos
name: odoo-server
state: started
expose:
- 8080
links: "{{ var_db_link | default([]) }}"
then test it use
ansible-playbook ha.yml -e var_db_link="redis-master:centos"
ansible-playbook ha.yml
It runs normally!

Resources