Packer: Ansible inventory_directory parameter causes the entire directory to be used as the inventory

Created on 21 Jun 2018  ยท  12Comments  ยท  Source: hashicorp/packer

  • Packer version from packer version: Packer v1.2.4
  • Host platform: Ubuntu 16.04.4 LTS
  • Debug log output from PACKER_LOG=1 packer build template.json.
    Relevant portion:
    Executing Ansible: ansible-playbook --extra-vars packer_build_name=amazon-ebs packer_builder_type=amazon-ebs -i ../ansible/inventories/ec2/ /home/wmd/git/myrepo/ansible/coreos.yaml -e ansible_ssh_private_key_file=/tmp/ansible-key962358977 --limit default
  • The _simplest example template and scripts_ needed to reproduce the bug:
    "provisioners": [ { "type": "ansible", "inventory_directory": "/path/to/ansible/inventory/directory", "playbook_file": "/path/to/ansible/playbook.yaml" } ]

When the remote Ansible provisioner is run with inventory_directory, the -i option is provided to Ansible as inventory_directory, rather than the path to the temporary inventory file in inventory_directory. This runs counter to what is stated in the documentation:

The directory in which to place the temporary generated Ansible inventory file. ... The fully-qualified name of this temporary file will be passed to the -i argument of the ansible command when this provisioner runs ansible.

This results in the Ansible playbook running against all matching hosts in the inventory, rather than just the host being provisioned by Packer, which is extremely undesirable.

The issue can be worked around by using extra_arguments to pass --limit to ansible-playbook.

The error is here. The inventory variable is replaced with the inventory directory, rather than the path to the inventory file in the inventory directory.

This might be a mistake in the documentation, but it feels much more likely that this is a bug in the code. It is NOT desirable to have Packer running Ansible against more hosts than just the one it's operating on. In my opinion, if the user actually desires that Packer should be aware of more hosts than just the one it's provisioning, they should explicitly configure that with inventory_file. And, if they desire that this inventory should be a directory, then inventory_file should support directories, as described in #4510. The stated purpose of inventory_directory in the docs is to allow users to take advantage of existing host_vars and group_vars, not to be the directory version of inventory_file.

bug docs provisioneansible-remote regression thinking

All 12 comments

I'm getting this same bug. It's causing ansible to recursively parse every file in inventory_directory as an inventory file, and it will execute any bash scripts it finds.

My inventory_directory looks like this:

inventory
playbook.yml
roles/
    my-role/
        files/
            install.sh
        tasks/
            main.yml

Which means ansible tries to parse inventory, playbook.yml, main.yml and install.sh as inventory files. Which gives me a bunch of errors that look like this for every yaml file:

packer:  [WARNING]:  * Failed to parse
packer: roles/my-role/tasks/main.yml with
packer: ini plugin:
packer: b'roles/my-role/tasks/main.yml':2:
packer: Expected key=value host variable assignment, got: name:

When it comes across a bash script, it gets executed with the script plugin:

packer:  [WARNING]:  * Failed to parse
packer: roles/my-role/files/install.sh with script plugin: Inventory script
packer: (roles/my-role/files/install.sh) had an execution error:
packer: roles/my-role/files/install.sh: line 2: apt-get: command not found
packer: roles/my-role/files/install.sh: line 3: apt-get: command not found
...

and it continues to execute the script, even though it failed. Using the --limit workaround suggested doesn't prevent ansible from parsing and executing all the files in the directory.

I agree with @geekofalltrades, this is definitely not desired behaviour.

This also causes issues with vars being defined and overridden in different inventory files, assuming you have per environment inventory files.

+1, it doesn't seem that inventory_directory behaves as it says on the documentation

I think all we need to do is revert https://github.com/hashicorp/packer/pull/6065 to get the behavior to work as documented. I think that the person who made that PR probably should have introduced a new template option. Can you confirm this for me? Here's a build of Packer 1.3.2 with that PR reverted:

Linux:
packer.zip

OSX:
packer.zip

Windows:
packer.zip

@SwampDragons I tried your build on Arch Linux (which was version 1.4.0 according to packer --version) and the issue seems to be fixed. It loaded the inventory in the expected way.

I came across this issue when trying to use inventory_directory as described in https://www.packer.io/docs/provisioners/ansible.html#inventory_directory .

According to ansible docs, if ansible gets a directory as inventory, it will treat it differently and it will allow you to use host_vars and group_vars (my desired use case).

As for packer/ansible trying to run shell scripts and YAML files, the correct solution would be to set ANSIBLE_INVENTORY_IGNORE env var.

Should I open a new ticket or could this ticket be reopened?

I think you want #4510.

It sounds to me like you already have what you want, though:

it will allow you to use host_vars and group_vars (my desired use case)

This is what inventory_directory does currently. Just make sure that you have the host in the right groups though, by using the groups arg to the provisioner.

No, it doesn't.

This is the current (packer 1.3.4) ansible command that is being generated:

==> vagrant: Executing Ansible: ansible-playbook --extra-vars packer_build_name=vagrant packer_builder_type=vagrant -o IdentitiesOnly=yes -i inventory/packer-provisioner-ansible650316513 /Users/DaviVidal/Projects/ansible-ng/testing.yml -e ansible_ssh_private_key_file=/var/folders/h1/k1xskb210yx895nw0mzzk6p80000gp/T/ansible-key127423242 --skip-tags foo,bar

And here is the relevant portion of my packer.json

        {
            "type": "ansible",
            "groups": [
                "s_all_nginx",
                "s_all_php",
                "s_all_consul"
            ],
            "empty_groups": [
                "a_all",
                "b_all",
                "c_all"
            ],
            "extra_arguments": [
                "--skip-tags",
                "foo,bar"
            ],
            "inventory_directory": "inventory/",
            "playbook_file": "../ansible-ng/testing.yml"
        }

EDIT: what I expected was to have something like ansible-playbook -i inventory (...)

Packer was doing that temporarily. I opened this bug to specifically revert that behavior, since it results in Ansible doing a lot more than I or probably most other users would want or expect.

-i inventory/packer-provisioner-ansible650316513 is the expected behavior after this fix. If you have host_vars/ and group_vars/ defined in inventory/, they should be getting used.

If I set inventory_directory the expected behavior is to ignore that and use a file instead?

Yes.

https://www.packer.io/docs/provisioners/ansible.html#inventory_directory

inventory_directory (string) - The directory in which to place the temporary generated Ansible inventory file. By default, this is the system-specific temporary file location. The fully-qualified name of this temporary file will be passed to the -i argument of the ansible command when this provisioner runs ansible. Specify this if you have an existing inventory directory with host_vars group_vars that you would like to use in the playbook that this provisioner will run.

I'm going to lock this issue because it has been closed for _30 days_ โณ. This helps our maintainers find and focus on the active issues.

If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

tleyden picture tleyden  ยท  3Comments

Tensho picture Tensho  ยท  3Comments

sourav82 picture sourav82  ยท  3Comments

jesse-c picture jesse-c  ยท  3Comments

znerd picture znerd  ยท  3Comments