From 9404dcb17dbbeb4aec7212575f4759cb03e7d8b2 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 12 Jul 2022 16:10:37 -0700 Subject: [PATCH] support --no-destroy-on-error in up(), closes #122 --- .github/workflows/tox.yml | 2 +- src/vagrant/__init__.py | 11 +++++++-- tests/test_vagrant.py | 24 +++++++++++++++++++ .../shell_provision_fail_Vagrantfile | 5 ++++ 4 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 tests/vagrantfiles/shell_provision_fail_Vagrantfile diff --git a/.github/workflows/tox.yml b/.github/workflows/tox.yml index be3f2da..de0b7c7 100644 --- a/.github/workflows/tox.yml +++ b/.github/workflows/tox.yml @@ -49,7 +49,7 @@ jobs: TOX_PARALLEL_NO_SPINNER: 1 TOXENV: ${{ matrix.tox_env }} FORCE_COLOR: 1 - PYTEST_REQPASS: 24 + PYTEST_REQPASS: 25 steps: - name: Check vagrant presence diff --git a/src/vagrant/__init__.py b/src/vagrant/__init__.py index 6b8282e..54afebb 100644 --- a/src/vagrant/__init__.py +++ b/src/vagrant/__init__.py @@ -307,7 +307,7 @@ def init(self, box_name=None, box_url=None): """ self._call_vagrant_command(["init", box_name, box_url]) - def up( + def up( # pylint: disable-msg=too-many-locals self, vm_name=None, no_provision=False, @@ -315,6 +315,7 @@ def up( provision=None, provision_with=None, stream_output=False, + destroy_on_error=True, ): """ Invoke `vagrant up` to start a box or boxes, possibly streaming the @@ -330,6 +331,8 @@ def up( subprocess might hang. if False, None is returned and the command is run to completion without streaming the output. Defaults to False. + destroy_on_error: if True, the newly created will be destroyed if there + was any error in the provisioning. Note: If provision and no_provision are not None, no_provision will be ignored. returns: None or a generator yielding lines of output. @@ -350,7 +353,10 @@ def up( if provision else "--no-provision" ) - + if destroy_on_error: + destroy_on_error_arg = "--destroy-on-error" + else: + destroy_on_error_arg = "--no-destroy-on-error" args = [ "up", vm_name, @@ -359,6 +365,7 @@ def up( provider_arg, prov_with_arg, providers_arg, + destroy_on_error_arg, ] if stream_output: generator = self._stream_vagrant_command(args) diff --git a/tests/test_vagrant.py b/tests/test_vagrant.py index d35089d..15b9cf5 100644 --- a/tests/test_vagrant.py +++ b/tests/test_vagrant.py @@ -62,6 +62,11 @@ def get_provider() -> str: "vagrantfiles", "shell_provision_Vagrantfile", ) +SHELL_PROVISION_FAIL_VAGRANTFILE = os.path.join( + os.path.dirname(os.path.abspath(__file__)), + "vagrantfiles", + "shell_provision_fail_Vagrantfile", +) # the names of the vms from the multi-vm Vagrantfile. VM_1 = "web" VM_2 = "db" @@ -603,6 +608,25 @@ def test_provisioning(vm_dir): assert test_file_contents == "foo", "The test file should contain 'foo'" +@pytest.mark.parametrize("vm_dir", (SHELL_PROVISION_FAIL_VAGRANTFILE,), indirect=True) +def test_provisioning_no_destory_on_error(vm_dir): + """ + Test support for 'vagrant up --no-destroy-on-error'. + """ + v = vagrant.Vagrant(vm_dir) + try: + v.up(destroy_on_error=True) + except subprocess.CalledProcessError: + pass + assert v.status()[0].state == v.NOT_CREATED + + try: + v.up(destroy_on_error=False) + except subprocess.CalledProcessError: + pass + assert v.status()[0].state == v.RUNNING + + @pytest.mark.parametrize("vm_dir", (MULTIVM_VAGRANTFILE,), indirect=True) def test_multivm_lifecycle(vm_dir): v = vagrant.Vagrant(vm_dir) diff --git a/tests/vagrantfiles/shell_provision_fail_Vagrantfile b/tests/vagrantfiles/shell_provision_fail_Vagrantfile new file mode 100644 index 0000000..baf613a --- /dev/null +++ b/tests/vagrantfiles/shell_provision_fail_Vagrantfile @@ -0,0 +1,5 @@ +Vagrant.configure("2") do |config| + config.vbguest.auto_update = false if Vagrant.has_plugin?("vagrant-vbguest") + config.vm.box = "generic/alpine315" + config.vm.provision :shell, :inline => "exit 1" +end