Repository: ansible/molecule

Issue:
Molecule 2.22rc3: Vagrant driver regression
<!--- Verify first that your issue is not already reported on GitHub -->
<!--- Please also check https://molecule.readthedocs.io/en/latest/faq.html --->
<!--- Please use https://groups.google.com/forum/#!forum/molecule-users for usage questions -->

# Issue Type

- Bug report

# Molecule and Ansible details

Ansible: 2.8.1
Molecule 2.22rc3

Python: 2.7.12
Vagrant: 2.0.2
Virtualbox: 5.2.30r130521
Ubuntu 16.04.6 LTS x86_64

Molecule installation method (one of):

- pip

Ansible installation method (one of):

- pip

Detail any linters or test runners used:

# Desired Behavior

Running Molecule test on a sample role with a Vagrant driver and a Virtualbox provider should result in a Virtualbox VM being brought up at some point.

# Actual Behaviour

Debug output snippet:

```
    TASK [Create molecule instance(s)] *********************************************
    task path: /usr/local/lib/python2.7/dist-packages/molecule/provisioner/ansible/playbooks/vagrant/create.yml:8
    <127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: go
    <127.0.0.1> EXEC /bin/sh -c 'echo ~go && sleep 0'
    <127.0.0.1> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /var/go/.ansible/tmp/ansible-tmp-1562189970.7-142759633793038 `" && echo ansible-tmp-1562189970.7-142759633793038="` echo /var/go/.ansible/tmp/ansible-tmp-1562189970.7-142759633793038 `" ) && sleep 0'
    Using module file /usr/local/lib/python2.7/dist-packages/molecule/provisioner/ansible/plugins/libraries/molecule_vagrant.py
    <127.0.0.1> PUT /var/go/.ansible/tmp/ansible-local-10147KOol3i/tmpmVJNT9 TO /var/go/.ansible/tmp/ansible-tmp-1562189970.7-142759633793038/AnsiballZ_molecule_vagrant.py
    <127.0.0.1> EXEC /bin/sh -c 'chmod u+x /var/go/.ansible/tmp/ansible-tmp-1562189970.7-142759633793038/ /var/go/.ansible/tmp/ansible-tmp-1562189970.7-142759633793038/AnsiballZ_molecule_vagrant.py && sleep 0'
    <127.0.0.1> EXEC /bin/sh -c '/usr/bin/python2 /var/go/.ansible/tmp/ansible-tmp-1562189970.7-142759633793038/AnsiballZ_molecule_vagrant.py && sleep 0'
    <127.0.0.1> EXEC /bin/sh -c 'rm -f -r /var/go/.ansible/tmp/ansible-tmp-1562189970.7-142759633793038/ > /dev/null 2>&1 && sleep 0'
    The full traceback is:
    WARNING: The below traceback may *not* be related to the actual failure.
      File "/tmp/ansible_molecule_vagrant_payload_VrLKoY/__main__.py", line 395, in up
        self._vagrant.up(provision=provision)
      File "/usr/local/lib/python2.7/dist-packages/vagrant/__init__.py", line 337, in up
        self._call_vagrant_command(args)
      File "/usr/local/lib/python2.7/dist-packages/vagrant/__init__.py", line 963, in _call_vagrant_command
        stderr=err_fh, env=self.env)
      File "/usr/lib/python2.7/subprocess.py", line 541, in check_call
        raise CalledProcessError(retcode, cmd)

    failed: [localhost] (item={'box': u'ubuntu/xenial64', 'name': u'Ubuntu'}) => {
        "ansible_loop_var": "item",
        "changed": false,
        "invocation": {
            "module_args": {
                "config_options": {},
                "force_stop": false,
                "instance_interfaces": [],
                "instance_name": "Ubuntu",
                "instance_raw_config_args": null,
                "platform_box": "ubuntu/xenial64",
                "platform_box_url": null,
                "platform_box_version": null,
                "provider_cpus": 2,
                "provider_memory": 512,
                "provider_name": "virtualbox",
                "provider_options": {},
                "provider_override_args": null,
                "provider_raw_config_args": null,
                "provision": false,
                "state": "up"
            }
        },
        "item": {
            "box": "ubuntu/xenial64",
            "name": "Ubuntu"
        },
        "msg": "ERROR: See log file '/tmp/molecule/test-role-vagrant/default/vagrant-Ubuntu.err'"
    }
```

Content of sample error file identified in Molecule output:
```
### 2019-07-03 10:08:56 ###
### 2019-07-03 10:08:56 ###
A Vagrant environment or target machine is required to run this
command. Run `vagrant init` to create a new Vagrant environment. Or,
get an ID of a target machine from `vagrant global-status` to run
this command on. A final option is to change to a directory with a
Vagrantfile and to try again.
```

Note that with the same sample role and environment, rolling back to Molecule 2.20.1 via `pip install molecule==2.20.1` fixed the problem and Vagrant boxes were again created successfully.
Molecule 2.22rc3: Vagrant driver regression
<!--- Verify first that your issue is not already reported on GitHub -->
<!--- Please also check https://molecule.readthedocs.io/en/latest/faq.html --->
<!--- Please use https://groups.google.com/forum/#!forum/molecule-users for usage questions -->

# Issue Type

- Bug report

# Molecule and Ansible details

Ansible: 2.8.1
Molecule 2.22rc3

Python: 2.7.12
Vagrant: 2.0.2
Virtualbox: 5.2.30r130521
Ubuntu 16.04.6 LTS x86_64

Molecule installation method (one of):

- pip

Ansible installation method (one of):

- pip

Detail any linters or test runners used:

# Desired Behavior

Running Molecule test on a sample role with a Vagrant driver and a Virtualbox provider should result in a Virtualbox VM being brought up at some point.

# Actual Behaviour

Debug output snippet:

```
    TASK [Create molecule instance(s)] *********************************************
    task path: /usr/local/lib/python2.7/dist-packages/molecule/provisioner/ansible/playbooks/vagrant/create.yml:8
    <127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: go
    <127.0.0.1> EXEC /bin/sh -c 'echo ~go && sleep 0'
    <127.0.0.1> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /var/go/.ansible/tmp/ansible-tmp-1562189970.7-142759633793038 `" && echo ansible-tmp-1562189970.7-142759633793038="` echo /var/go/.ansible/tmp/ansible-tmp-1562189970.7-142759633793038 `" ) && sleep 0'
    Using module file /usr/local/lib/python2.7/dist-packages/molecule/provisioner/ansible/plugins/libraries/molecule_vagrant.py
    <127.0.0.1> PUT /var/go/.ansible/tmp/ansible-local-10147KOol3i/tmpmVJNT9 TO /var/go/.ansible/tmp/ansible-tmp-1562189970.7-142759633793038/AnsiballZ_molecule_vagrant.py
    <127.0.0.1> EXEC /bin/sh -c 'chmod u+x /var/go/.ansible/tmp/ansible-tmp-1562189970.7-142759633793038/ /var/go/.ansible/tmp/ansible-tmp-1562189970.7-142759633793038/AnsiballZ_molecule_vagrant.py && sleep 0'
    <127.0.0.1> EXEC /bin/sh -c '/usr/bin/python2 /var/go/.ansible/tmp/ansible-tmp-1562189970.7-142759633793038/AnsiballZ_molecule_vagrant.py && sleep 0'
    <127.0.0.1> EXEC /bin/sh -c 'rm -f -r /var/go/.ansible/tmp/ansible-tmp-1562189970.7-142759633793038/ > /dev/null 2>&1 && sleep 0'
    The full traceback is:
    WARNING: The below traceback may *not* be related to the actual failure.
      File "/tmp/ansible_molecule_vagrant_payload_VrLKoY/__main__.py", line 395, in up
        self._vagrant.up(provision=provision)
      File "/usr/local/lib/python2.7/dist-packages/vagrant/__init__.py", line 337, in up
        self._call_vagrant_command(args)
      File "/usr/local/lib/python2.7/dist-packages/vagrant/__init__.py", line 963, in _call_vagrant_command
        stderr=err_fh, env=self.env)
      File "/usr/lib/python2.7/subprocess.py", line 541, in check_call
        raise CalledProcessError(retcode, cmd)

    failed: [localhost] (item={'box': u'ubuntu/xenial64', 'name': u'Ubuntu'}) => {
        "ansible_loop_var": "item",
        "changed": false,
        "invocation": {
            "module_args": {
                "config_options": {},
                "force_stop": false,
                "instance_interfaces": [],
                "instance_name": "Ubuntu",
                "instance_raw_config_args": null,
                "platform_box": "ubuntu/xenial64",
                "platform_box_url": null,
                "platform_box_version": null,
                "provider_cpus": 2,
                "provider_memory": 512,
                "provider_name": "virtualbox",
                "provider_options": {},
                "provider_override_args": null,
                "provider_raw_config_args": null,
                "provision": false,
                "state": "up"
            }
        },
        "item": {
            "box": "ubuntu/xenial64",
            "name": "Ubuntu"
        },
        "msg": "ERROR: See log file '/tmp/molecule/test-role-vagrant/default/vagrant-Ubuntu.err'"
    }
```

Content of sample error file identified in Molecule output:
```
### 2019-07-03 10:08:56 ###
### 2019-07-03 10:08:56 ###
A Vagrant environment or target machine is required to run this
command. Run `vagrant init` to create a new Vagrant environment. Or,
get an ID of a target machine from `vagrant global-status` to run
this command on. A final option is to change to a directory with a
Vagrantfile and to try again.
```

Note that with the same sample role and environment, rolling back to Molecule 2.20.1 via `pip install molecule==2.20.1` fixed the problem and Vagrant boxes were again created successfully.


Discussion:
Can anyone using the Vagrant driver comment on this? Can anyone reproduce such an error with the latest release candidate? I don't use this driver, so I can't comment on this.
I have got the same Issue with vagrant driver. But instead I use the libvirt provider. (Provider doesn't matter I think...)

It is very likely that the invokation of the vagrant command via "vagrant-molecule" has not been adapted to the new directory structure.

The vagrant command needs to be invoked where the Vagrantfile is located. With the introduction of the new directory structure this location changed from `/tmp/molecule/[role name]/[scenario name]` (1.20.1) to
`/tmp/mol.[user]/molecule/[role name]/[scenario name]/molecule/vagrant/[scenario name]` (1.22rc3).

As far as I understand, the working directory for the vagrant call needs to be adapted to the correct path.
That's awesome @jonasjoest, you're probably right. Can anyone pick this up?

I'll try to get to it sometime soon ...

This should block any further release @ssbarnea.
After further investigation it turned out that the env variable `MOLECULE_EPHEMERAL_DIRECTORY` is still set to `/tmp/mol.[user]/molecule/[role name]/[scenario name]`.

The `molecule-vagrant` - **Ansible module** assembles the vagrant CWD with that `MOLECULE_EPHEMERAL_DIRECTORY`  env variable:
https://github.com/ansible/molecule/blob/55f3b11c21379bacd82db5601d648a6c3e1156c6/molecule/provisioner/ansible/plugins/libraries/molecule_vagrant.py#L474



But instead the `vagrant` **driver** uses the config attribute `self._config.scenario.ephemeral_directory` to create the Vagrantfile.
https://github.com/ansible/molecule/blob/55f3b11c21379bacd82db5601d648a6c3e1156c6/molecule/driver/vagrant.py#L198

Since the Vagrantfile is in the end located at
`/tmp/mol.[user]/molecule/[role name]/[scenario name]/molecule/vagrant/[scenario name]`
and the env variable points to
`/tmp/mol.[user]/molecule/[role name]/[scenario name]`
there has to be a mismatch between environment variables and config attributes as far as I understand.


So this issue is perhaps not only vagrant-driver-specific. Maybe you can try to confirm that the config attribute in python does not equal the environment variable in terms of the `ephemeral directory`. I am currently not able to test this though.
Any patch would be welcomed, I will review it with priority.
Can anyone using the Vagrant driver comment on this? Can anyone reproduce such an error with the latest release candidate? I don't use this driver, so I can't comment on this.
I have got the same Issue with vagrant driver. But instead I use the libvirt provider. (Provider doesn't matter I think...)

It is very likely that the invokation of the vagrant command via "vagrant-molecule" has not been adapted to the new directory structure.

The vagrant command needs to be invoked where the Vagrantfile is located. With the introduction of the new directory structure this location changed from `/tmp/molecule/[role name]/[scenario name]` (1.20.1) to
`/tmp/mol.[user]/molecule/[role name]/[scenario name]/molecule/vagrant/[scenario name]` (1.22rc3).

As far as I understand, the working directory for the vagrant call needs to be adapted to the correct path.
That's awesome @jonasjoest, you're probably right. Can anyone pick this up?

I'll try to get to it sometime soon ...

This should block any further release @ssbarnea.
After further investigation it turned out that the env variable `MOLECULE_EPHEMERAL_DIRECTORY` is still set to `/tmp/mol.[user]/molecule/[role name]/[scenario name]`.

The `molecule-vagrant` - **Ansible module** assembles the vagrant CWD with that `MOLECULE_EPHEMERAL_DIRECTORY`  env variable:
https://github.com/ansible/molecule/blob/55f3b11c21379bacd82db5601d648a6c3e1156c6/molecule/provisioner/ansible/plugins/libraries/molecule_vagrant.py#L474



But instead the `vagrant` **driver** uses the config attribute `self._config.scenario.ephemeral_directory` to create the Vagrantfile.
https://github.com/ansible/molecule/blob/55f3b11c21379bacd82db5601d648a6c3e1156c6/molecule/driver/vagrant.py#L198

Since the Vagrantfile is in the end located at
`/tmp/mol.[user]/molecule/[role name]/[scenario name]/molecule/vagrant/[scenario name]`
and the env variable points to
`/tmp/mol.[user]/molecule/[role name]/[scenario name]`
there has to be a mismatch between environment variables and config attributes as far as I understand.


So this issue is perhaps not only vagrant-driver-specific. Maybe you can try to confirm that the config attribute in python does not equal the environment variable in terms of the `ephemeral directory`. I am currently not able to test this though.
Any patch would be welcomed, I will review it with priority.

Resolving patch:
diff --git a/molecule/config.py b/molecule/config.py
--- a/molecule/config.py
+++ b/molecule/config.py
@@ -138,7 +138,7 @@ def action(self, value):
 
     @property
     def project_directory(self):
-        return os.getcwd()
+        return os.getenv('MOLECULE_PROJECT_DIRECTORY', os.getcwd())
 
     @property
     def cache_directory(self):
diff --git a/molecule/scenario.py b/molecule/scenario.py
--- a/molecule/scenario.py
+++ b/molecule/scenario.py
@@ -145,6 +145,10 @@ def directory(self):
 
     @property
     def ephemeral_directory(self):
+        _ephemeral_directory = os.getenv('MOLECULE_EPHEMERAL_DIRECTORY')
+        if _ephemeral_directory:
+            return _ephemeral_directory
+
         project_directory = os.path.basename(self.config.project_directory)
 
         if self.config.is_parallel:


Test patch: