diff options
Diffstat (limited to 'openstackclient/tests/functional/base.py')
-rw-r--r-- | openstackclient/tests/functional/base.py | 83 |
1 files changed, 56 insertions, 27 deletions
diff --git a/openstackclient/tests/functional/base.py b/openstackclient/tests/functional/base.py index 0ed7dff8..0c430267 100644 --- a/openstackclient/tests/functional/base.py +++ b/openstackclient/tests/functional/base.py @@ -10,6 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. +import json +import logging import os import shlex import subprocess @@ -18,54 +20,81 @@ from tempest.lib.cli import output_parser from tempest.lib import exceptions import testtools - ADMIN_CLOUD = os.environ.get('OS_ADMIN_CLOUD', 'devstack-admin') +LOG = logging.getLogger(__name__) def execute(cmd, fail_ok=False, merge_stderr=False): """Executes specified command for the given action.""" + LOG.debug('Executing: %s', cmd) cmdlist = shlex.split(cmd) stdout = subprocess.PIPE stderr = subprocess.STDOUT if merge_stderr else subprocess.PIPE + proc = subprocess.Popen(cmdlist, stdout=stdout, stderr=stderr) - result, result_err = proc.communicate() - result = result.decode('utf-8') + + result_out, result_err = proc.communicate() + result_out = result_out.decode('utf-8') + LOG.debug('stdout: %s', result_out) + LOG.debug('stderr: %s', result_err) + if not fail_ok and proc.returncode != 0: - raise exceptions.CommandFailed(proc.returncode, cmd, result, - result_err) - return result + raise exceptions.CommandFailed( + proc.returncode, cmd, result_out, result_err, + ) + + return result_out class TestCase(testtools.TestCase): @classmethod - def openstack(cls, cmd, cloud=ADMIN_CLOUD, fail_ok=False): + def openstack( + cls, + cmd, + *, + cloud=ADMIN_CLOUD, + fail_ok=False, + parse_output=False, + ): """Executes openstackclient command for the given action - NOTE(dtroyer): There is a subtle distinction between pasing - cloud=None and cloud='': for compatibility reasons passing - cloud=None continues to include the option '--os-auth-type none' - in the command while passing cloud='' omits the '--os-auth-type' - option completely to let the default handlers be invoked. + :param cmd: A string representation of the command to execute. + :param cloud: The cloud to execute against. This can be a string, empty + string, or None. A string results in '--os-auth-type $cloud', an + empty string results in the '--os-auth-type' option being + omitted, and None resuts in '--os-auth-type none' for legacy + reasons. + :param fail_ok: If failure is permitted. If False (default), a command + failure will result in `~tempest.lib.exceptions.CommandFailed` + being raised. + :param parse_output: If true, pass the '-f json' parameter and decode + the output. + :returns: The output from the command. + :raises: `~tempest.lib.exceptions.CommandFailed` if the command failed + and ``fail_ok`` was ``False``. """ + auth_args = [] if cloud is None: # Execute command with no auth - return execute( - 'openstack --os-auth-type none ' + cmd, - fail_ok=fail_ok - ) - elif cloud == '': - # Execute command with no auth options at all - return execute( - 'openstack ' + cmd, - fail_ok=fail_ok - ) + auth_args.append('--os-auth-type none') + elif cloud != '': + # Execute command with an explicit cloud specified + auth_args.append(f'--os-cloud {cloud}') + + format_args = [] + if parse_output: + format_args.append('-f json') + + output = execute( + ' '.join(['openstack'] + auth_args + [cmd] + format_args), + fail_ok=fail_ok, + ) + + if parse_output: + return json.loads(output) else: - # Execure command with an explicit cloud specified - return execute( - 'openstack --os-cloud=' + cloud + ' ' + cmd, - fail_ok=fail_ok - ) + return output @classmethod def is_service_enabled(cls, service, version=None): |