[Python-modules-commits] [python-vagrant] 02/06: New upstream version 0.5.15
Hans-Christoph Steiner
eighthave at moszumanska.debian.org
Mon Jan 8 21:58:17 UTC 2018
This is an automated email from the git hooks/post-receive script.
eighthave pushed a commit to branch master
in repository python-vagrant.
commit c1538d0c9f0756ba5cbb80dc95c20e6ee2b13c7b
Author: Hans-Christoph Steiner <hans at eds.org>
Date: Mon Jan 8 22:05:42 2018 +0100
New upstream version 0.5.15
---
CHANGELOG.md | 11 ++++
PKG-INFO | 2 +-
python_vagrant.egg-info/PKG-INFO | 2 +-
tests/test_vagrant.py | 54 +++++++++++++++++++-
vagrant/__init__.py | 108 ++++++++++++++++++++++++++++++---------
5 files changed, 150 insertions(+), 27 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 95ceafb..3633673 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,17 @@
This document lists the changes (and individuals who contributed to those
changes) for each release of python-vagrant.
+## 0.5.15
+
+- Pull Request #54: Create ssh() method to run shell commands in a VM
+ Authors: Parker Thompson (https://github.com/mothran) and Todd DeLuca
+ (https://github.com/todddeluca)
+- Pull Request #56: Return generator for `up` and `reload` output lines to
+ avoid having entire output in memory.
+ Authors: mmabey (https://github.com/mmabey) and Todd DeLuca
+ (https://github.com/todddeluca)
+
+
## 0.5.14
- Pull Request #51: Add support for the vagrant package command.
diff --git a/PKG-INFO b/PKG-INFO
index 7fadceb..7a2fbcd 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: python-vagrant
-Version: 0.5.14
+Version: 0.5.15
Summary: Python bindings for interacting with Vagrant virtual machines.
Home-page: https://github.com/todddeluca/python-vagrant
Author: Todd Francis DeLuca
diff --git a/python_vagrant.egg-info/PKG-INFO b/python_vagrant.egg-info/PKG-INFO
index 7fadceb..7a2fbcd 100644
--- a/python_vagrant.egg-info/PKG-INFO
+++ b/python_vagrant.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: python-vagrant
-Version: 0.5.14
+Version: 0.5.15
Summary: Python bindings for interacting with Vagrant virtual machines.
Home-page: https://github.com/todddeluca/python-vagrant
Author: Todd Francis DeLuca
diff --git a/tests/test_vagrant.py b/tests/test_vagrant.py
index 21297ed..7b92c1d 100644
--- a/tests/test_vagrant.py
+++ b/tests/test_vagrant.py
@@ -23,7 +23,7 @@ import subprocess
import sys
import tempfile
import time
-from nose.tools import eq_, ok_, with_setup
+from nose.tools import eq_, ok_, with_setup, assert_raises
import vagrant
from vagrant import compat
@@ -520,6 +520,58 @@ def test_multivm_config():
eq_(keyfile, parsed_config["IdentityFile"].lstrip('"').rstrip('"'))
+ at with_setup(make_setup_vm(), teardown_vm)
+def test_ssh_command():
+ '''
+ Test executing a command via ssh on a vm.
+ '''
+ v = vagrant.Vagrant(TD)
+ v.up()
+ output = v.ssh(command='echo hello')
+ assert output.strip() == 'hello'
+
+
+ at with_setup(make_setup_vm(MULTIVM_VAGRANTFILE), teardown_vm)
+def test_ssh_command_multivm():
+ '''
+ Test executing a command via ssh on a specific vm
+ '''
+ v = vagrant.Vagrant(TD)
+ v.up()
+ output = v.ssh(vm_name=VM_1, command='echo hello')
+ assert output.strip() == 'hello'
+ output = v.ssh(vm_name=VM_2, command='echo I like your hat')
+ assert output.strip() == 'I like your hat'
+
+
+ at with_setup(make_setup_vm(), teardown_vm)
+def test_streaming_output():
+ """
+ Test streaming output of up or reload.
+ """
+ test_string = 'Waiting for machine to boot.'
+ v = vagrant.Vagrant(TD)
+
+ with assert_raises(subprocess.CalledProcessError):
+ v.up(vm_name='incorrect-name')
+
+ streaming_up = False
+ for line in v.up(stream_output=True):
+ print('output line:', line)
+ if test_string in line:
+ streaming_up = True
+
+ assert streaming_up
+
+ streaming_reload = False
+ for line in v.reload(stream_output=True):
+ print('output line:', line)
+ if test_string in line:
+ streaming_reload = True
+
+ assert streaming_reload
+
+
def test_make_file_cm():
filename = os.path.join(TD, 'test.log')
if os.path.exists(filename):
diff --git a/vagrant/__init__.py b/vagrant/__init__.py
index cdd93b8..75d5e7c 100644
--- a/vagrant/__init__.py
+++ b/vagrant/__init__.py
@@ -26,7 +26,7 @@ from . import compat
# python package version
# should match r"^__version__ = '(?P<version>[^']+)'$" for setup.py
-__version__ = '0.5.14'
+__version__ = '0.5.15'
log = logging.getLogger(__name__)
@@ -227,8 +227,8 @@ class Vagrant(object):
env=None, out_cm=None, err_cm=None):
'''
root: a directory containing a file named Vagrantfile. Defaults to
- os.getcwd(). This is the directory and Vagrantfile that the Vagrant
- instance will operate on.
+ os.getcwd(). This is the directory and Vagrantfile that the Vagrant
+ instance will operate on.
env: a dict of environment variables (string keys and values) passed to
the vagrant command subprocess or None. Defaults to None. If env is
None, `subprocess.Popen` uses the current process environment.
@@ -300,17 +300,24 @@ class Vagrant(object):
self._call_vagrant_command(['init', box_name, box_url])
def up(self, no_provision=False, provider=None, vm_name=None,
- provision=None, provision_with=None):
+ provision=None, provision_with=None, stream_output=False):
'''
- Launch the Vagrant box.
+ Invoke `vagrant up` to start a box or boxes, possibly streaming the
+ command output.
vm_name=None: name of VM.
provision_with: optional list of provisioners to enable.
provider: Back the machine with a specific provider
no_provision: if True, disable provisioning. Same as 'provision=False'.
provision: optional boolean. Enable or disable provisioning. Default
behavior is to use the underlying vagrant default.
+ stream_output: if True, return a generator that yields each line of the
+ output of running the command. Consume the generator or the
+ subprocess might hang. if False, None is returned and the command
+ is run to completion without streaming the output. Defaults to
+ False.
Note: If provision and no_provision are not None, no_provision will be
ignored.
+ returns: None or a generator yielding lines of output.
'''
provider_arg = '--provider=%s' % provider if provider else None
prov_with_arg = None if provision_with is None else '--provision-with'
@@ -323,15 +330,14 @@ class Vagrant(object):
no_provision_arg = '--no-provision' if no_provision else None
provision_arg = None if provision is None else '--provision' if provision else '--no-provision'
- self._call_vagrant_command(['up', vm_name, no_provision_arg,
- provision_arg, provider_arg,
- prov_with_arg, providers_arg])
- try:
- self.conf(vm_name=vm_name) # cache configuration
- except subprocess.CalledProcessError:
- # in multi-VM environments, up() can be used to start all VMs,
- # however vm_name is required for conf() or ssh_config().
- pass
+ args = ['up', vm_name, no_provision_arg, provision_arg, provider_arg, prov_with_arg, providers_arg]
+ if stream_output:
+ generator = self._stream_vagrant_command(args)
+ else:
+ self._call_vagrant_command(args)
+
+ self._cached_conf[vm_name] = None # remove cached configuration
+ return generator if stream_output else None
def provision(self, vm_name=None, provision_with=None):
'''
@@ -345,25 +351,40 @@ class Vagrant(object):
self._call_vagrant_command(['provision', vm_name, prov_with_arg,
providers_arg])
- def reload(self, vm_name=None, provision=None, provision_with=None):
+ def reload(self, vm_name=None, provision=None, provision_with=None,
+ stream_output=False):
'''
Quoting from Vagrant docs:
> The equivalent of running a halt followed by an up.
-
- > This command is usually required for changes made in the Vagrantfile to take effect. After making any modifications to the Vagrantfile, a reload should be called.
-
- > The configured provisioners will not run again, by default. You can force the provisioners to re-run by specifying the --provision flag.
+ > This command is usually required for changes made in the Vagrantfile
+ to take effect. After making any modifications to the Vagrantfile, a
+ reload should be called.
+ > The configured provisioners will not run again, by default. You can
+ force the provisioners to re-run by specifying the --provision flag.
provision: optional boolean. Enable or disable provisioning. Default
behavior is to use the underlying vagrant default.
provision_with: optional list of provisioners to enable.
e.g. ['shell', 'chef_solo']
+ stream_output: if True, return a generator that yields each line of the
+ output of running the command. Consume the generator or the
+ subprocess might hang. if False, None is returned and the command
+ is run to completion without streaming the output. Defaults to
+ False.
+ returns: None or a generator yielding lines of output.
'''
prov_with_arg = None if provision_with is None else '--provision-with'
providers_arg = None if provision_with is None else ','.join(provision_with)
provision_arg = None if provision is None else '--provision' if provision else '--no-provision'
- self._call_vagrant_command(['reload', vm_name, provision_arg,
- prov_with_arg, providers_arg])
+
+ args = ['reload', vm_name, provision_arg, prov_with_arg, providers_arg]
+ if stream_output:
+ generator = self._stream_vagrant_command(args)
+ else:
+ self._call_vagrant_command(args)
+
+ self._cached_conf[vm_name] = None # remove cached configuration
+ return generator if stream_output else None
def suspend(self, vm_name=None):
'''
@@ -728,14 +749,24 @@ class Vagrant(object):
'''
self._call_vagrant_command(['snapshot', 'delete', name])
+ def ssh(self, vm_name=None, command=None, extra_ssh_args=None):
+ '''
+ Execute a command via ssh on the vm specified.
+ command: The command to execute via ssh.
+ extra_ssh_args: Corresponds to '--' option in the vagrant ssh command
+ Returns the output of running the command.
+ '''
+ cmd = ['ssh', vm_name, '--command', command]
+ if extra_ssh_args is not None:
+ cmd += ['--', extra_ssh_args]
+
+ return self._run_vagrant_command(cmd)
+
def _parse_box_list(self, output):
'''
Remove Vagrant usage for unit testing
'''
# Parse box list output
- # Cue snarky comment about how nice it would be if vagrant used JSON
- # or even had a description of the machine readable output for each
- # command
boxes = []
# initialize box values
@@ -944,6 +975,35 @@ class Vagrant(object):
return compat.decode(subprocess.check_output(command, cwd=self.root,
env=self.env, stderr=err_fh))
+ def _stream_vagrant_command(self, args):
+ """
+ Execute a vagrant command, returning a generator of the output lines.
+ Caller should consume the entire generator to avoid the hanging the
+ subprocess.
+
+ :param args: Arguments for the Vagrant command.
+ :return: generator that yields each line of the command stdout.
+ :rtype: generator iterator
+ """
+ py3 = sys.version_info > (3, 0)
+
+ # Make subprocess command
+ command = self._make_vagrant_command(args)
+ with self.err_cm() as err_fh:
+ sp_args = dict(args=command, cwd=self.root, env=self.env,
+ stdout=subprocess.PIPE, stderr=err_fh, bufsize=1)
+
+ # Iterate over output lines.
+ # See http://stackoverflow.com/questions/2715847/python-read-streaming-input-from-subprocess-communicate#17698359
+ p = subprocess.Popen(**sp_args)
+ with p.stdout:
+ for line in iter(p.stdout.readline, b''):
+ yield compat.decode(line) # if PY3 decode bytestrings
+ p.wait()
+ # Raise CalledProcessError for consistency with _call_vagrant_command
+ if p.returncode != 0:
+ raise subprocess.CalledProcessError(p.returncode, command)
+
class SandboxVagrant(Vagrant):
'''
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-vagrant.git
More information about the Python-modules-commits
mailing list