diff --git a/machine/machine.py b/machine/machine.py index 27bc937..76e0418 100644 --- a/machine/machine.py +++ b/machine/machine.py @@ -38,6 +38,24 @@ def _run(self, cmd, raise_error=True): raise RuntimeError("cmd returned error %s: %s" % (error_code, stderr.decode('utf-8').strip())) return stdout.decode('utf-8'), stderr.decode('utf-8'), error_code + def _run_blocking(self, cmd, raise_error=True): + """ + Run a docker-machine command, optionally raise error if error code != 0 + Args: + cmd (List[str]): a list of the docker-machine command with the arguments to run + raise_error (bool): raise an exception on non 0 return code + Returns: + tuple: stdout, stderr, error_code + """ + cmd = [self.path] + cmd + p = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE) + stdout, stderr = p.communicate() + error_code = p.wait() + + if raise_error and error_code: + raise RuntimeError("cmd returned error %s: %s" % (error_code, stderr.decode('utf-8').strip())) + return stdout.decode('utf-8'), stderr.decode('utf-8'), error_code + def _match(self, cmd, regexp): """ Run cmd and match regular expression regexp on it, return results. @@ -68,6 +86,26 @@ def version(self): match = self._match(cmd, regexp) return match.group(1) + def create(self, name, driver='virtualbox', blocking=True): + """ + Create a docker machine using the provided name and driver + NOTE: This takes a loooooong time + + Args: + name (str): the name to give to the machine (must be unique) + driver: the driver to use to create the machine + blocking (bool): should wait for completion before exiting + + Returns: + int: error code from the run + """ + cmd = ['create', '--driver', driver, name] + if blocking: + stdout, stderr, errorcode = self._run_blocking(cmd) + else: + stdout, stderr, errorcode = self._run(cmd) + return errorcode + def config(self, machine="default"): """ Returns the docker configuration for the given machine. diff --git a/tests/test_commands.py b/tests/test_commands.py index b11df69..80ea1e0 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -1,6 +1,7 @@ import unittest import os import docker +from time import sleep import machine @@ -50,11 +51,6 @@ def test_config_invalid_machine(self): with self.assertRaises(RuntimeError): self.machine.config(machine=INVALID_MACHINE) - @unittest.skip("disabled since it takes ages") - def test_create_and_rm(self): - self.machine.create(machine=TEMPORARY_MACHINE) - self.machine.rm(machine=TEMPORARY_MACHINE) - def test_env(self): self.machine.env(machine=TEST_MACHINE) @@ -118,3 +114,40 @@ def test_url(self): def test_version(self): version = self.machine.version() + + def test_create_already_exists(self): + self.assertTrue(self.machine.exists(machine=TEST_MACHINE)) + try: + self.machine.create(TEST_MACHINE, blocking=True) + except RuntimeError: + pass # The test should raise this error + try: + self.machine.create(TEST_MACHINE, blocking=False) + except RuntimeError: + pass # The test should raise this error + + @unittest.skip("disabled since it takes ages") + def test_create_non_blocking(self): + self.assertFalse(self.machine.exists(machine=TEMPORARY_MACHINE)) + + # Create a new machine with blocking=False, and wait... + self.machine.create(TEMPORARY_MACHINE, blocking=False) + + max_time = 300 #Max waiting time opf 300 seconds + for sec in range(max_time) : + sleep(1) + if self.machine.exists(machine=TEMPORARY_MACHINE): + break + self.assertTrue(self.machine.exists(machine=TEMPORARY_MACHINE)) + self.machine.stop(machine=TEMPORARY_MACHINE) + self.machine.rm(machine=TEMPORARY_MACHINE) + + @unittest.skip("disabled since it takes ages") + def test_create_blocking(self): + self.assertFalse(self.machine.exists(machine=TEMPORARY_MACHINE)) + + # Create a new machine with blocking=True, and wait... + self.machine.create(TEMPORARY_MACHINE, blocking=True) + self.assertTrue(self.machine.exists(machine=TEMPORARY_MACHINE)) + self.machine.stop(machine=TEMPORARY_MACHINE) + self.machine.rm(machine=TEMPORARY_MACHINE)