ansible / ansible-container

DEPRECATED -- Ansible Container was a tool to build Docker images and orchestrate containers using only Ansible playbooks.
GNU Lesser General Public License v3.0
2.19k stars 392 forks source link

incomplete --vars-files processing / inconsistent documentation on --vars-files processing #886

Open dchsueh opened 6 years ago

dchsueh commented 6 years ago
ISSUE TYPE

(it may be all three!)

container.yml
version: '2'

settings:
  project_name: "centos{{os_major_version}}-test-box"
  conductor:
    base: 'centos:{{os_major_version}}'

services:
  base:
    from: 'centos:{{os_major_version}}'
    roles:
    - 'centos{{os_major_version}}test'
centos7.yml
---
os_major_version: 7
OS / ENVIRONMENT
# ansible-container --debug version
Ansible Container, version 0.9.2
Linux, ubuntu, 4.4.0-112-generic, #135-Ubuntu SMP Fri Jan 19 11:48:36 UTC 2018, x86_64
2.7.12 (default, Nov 20 2017, 18:23:56) 
[GCC 5.4.0 20160609] /home/ubuntu/ansible-container/bin/python2
SUMMARY

The intended behavior of jinja2 templating of container.yml is confusing. I'm not sure if it's a documentation or code issue, and is definitely a good feature, hence my indicating all three issue types above.

At time of writing, the docs at https://docs.ansible.com/ansible-container/container_yml/template.html say

STEPS TO REPRODUCE
ansible-container --vars-files centos7.yml build
EXPECTED RESULTS

The best outcome is if the container.yml works with all four above variable references, e.g., Jinja is called to perform rendering before the build command is even attempted, which corresponds with the --vars-files arg required before "build".

If substitution happens in the conductor, then the build should work with the last two variable references.

ACTUAL RESULTS

The --vars-files processing does not happen before the build is executed, as evidenced by the below output, where the project_name did not undergo substitution (when used as a name for "-conductor"):

# ansible-container --vars-files centos7.yml build 
Building Docker Engine context...   
Starting Docker build of Ansible Container Conductor image (please be patient)...   
ERROR   Unknown exception   
Traceback (most recent call last):
<traceback-removed>
APIError: 500 Server Error: Internal Server Error ("Error parsing reference: "centos{{os_major_version}}-test-box-conductor" is not a valid repository/tag: invalid reference format")

The conductor:base is not substituted either; if the (first variable) project_name is changed to "centos7-test-box" the error is now:

BuildError: Error parsing reference: "container-conductor-centos-{{os_major_version}}:0.9.2" is not a valid repository/tag: invalid reference format

The third (services:base:from) variable is the only one that is substituted.

The fourth variable (roles) is not:

# ansible-container --vars-files centos7.yml build 
Building Docker Engine context...   
Starting Docker build of Ansible Container Conductor image (please be patient)...   
Parsing conductor CLI args.
Traceback (most recent call last):
  File "/usr/bin/conductor", line 11, in <module>
    load_entry_point('ansible-container', 'console_scripts', 'conductor')()
  File "/_ansible/container/__init__.py", line 19, in __wrapped__
    return fn(*args, **kwargs)
  File "/_ansible/container/cli.py", line 389, in conductor_commandline
    conductor_config = AnsibleContainerConductorConfig(list_to_ordereddict(containers_config))
  File "/_ansible/container/__init__.py", line 19, in __wrapped__
    return fn(*args, **kwargs)
  File "/_ansible/container/config.py", line 297, in __init__
    self._process_services()
  File "/_ansible/container/config.py", line 357, in _process_services
    role_metadata = get_metadata_from_role(role_name)
  File "/_ansible/container/__init__.py", line 19, in __wrapped__
    return fn(*args, **kwargs)
  File "/_ansible/container/utils/__init__.py", line 275, in get_metadata_from_role
    return get_content_from_role(role_name, os.path.join('meta', 'container.yml'))
  File "/_ansible/container/__init__.py", line 19, in __wrapped__
    return fn(*args, **kwargs)
  File "/_ansible/container/utils/__init__.py", line 264, in get_content_from_role
    role_path = resolve_role_to_path(role_name)
  File "/_ansible/container/__init__.py", line 19, in __wrapped__
    return fn(*args, **kwargs)
  File "/_ansible/container/utils/__init__.py", line 210, in resolve_role_to_path
    loader=loader)
  File "/usr/lib/python2.7/site-packages/ansible/playbook/role/include.py", line 59, in load
    return ri.load_data(data, variable_manager=variable_manager, loader=loader)
  File "/usr/lib/python2.7/site-packages/ansible/playbook/base.py", line 244, in load_data
    ds = self.preprocess_data(ds)
  File "/usr/lib/python2.7/site-packages/ansible/playbook/role/definition.py", line 94, in preprocess_data
    (role_name, role_path) = self._load_role_path(role_name)
  File "/usr/lib/python2.7/site-packages/ansible/playbook/role/definition.py", line 172, in _load_role_path
    role_name = templar.template(role_name)
  File "/usr/lib/python2.7/site-packages/ansible/template/__init__.py", line 453, in template
    disable_lookups=disable_lookups,
  File "/usr/lib/python2.7/site-packages/ansible/template/__init__.py", line 706, in do_template
    raise AnsibleUndefinedVariable(e)
ansible.errors.AnsibleUndefinedVariable: 'os_major_version' is undefined
Conductor terminated. Cleaning up.  command_rc=1 conductor_id=5c836d1fba0ffd022f5921214ce8c02ec6b753622b91906375699bb2c8fd4a66 save_container=False
ERROR   Conductor exited with status 1  
FEATURE REQUEST

As indicated in "expected results", it would be nice if template processing is done before build is attempted. It should be possible given python is available on the ansible-container invoking machine.

Another feature (a new one) is to specify vars on the command line, also before the "build" command, similar to "ansible-playbook --extra-vars"

# ansible-playbook --help
Usage: ansible-playbook [options] playbook.yml [playbook2 ...]

Runs Ansible playbooks, executing the defined tasks on the targeted hosts.

Options:
<snip>
  -e EXTRA_VARS, --extra-vars=EXTRA_VARS
                        set additional variables as key=value or YAML/JSON, if
                        filename prepend with @
<snip>

which supports direct or file-referenced vars.