Skip functional test cases requiring Keystone credentials

Change-Id: Ib2143b49f8028ec6e4476dece8f8072cd9690967
This commit is contained in:
Federico Ressi 2020-09-22 15:22:17 +02:00
parent efe9febf9a
commit 7d20c11226
24 changed files with 160 additions and 54 deletions

View File

@ -18,7 +18,7 @@ import io
import os import os
import tempfile import tempfile
import time import time
import typing import typing # noqa
from oslo_log import log from oslo_log import log
import requests import requests
@ -27,6 +27,7 @@ import tobiko
from tobiko.config import get_bool_env from tobiko.config import get_bool_env
from tobiko.openstack.glance import _client from tobiko.openstack.glance import _client
from tobiko.openstack.glance import _io from tobiko.openstack.glance import _io
from tobiko.openstack import keystone
LOG = log.getLogger(__name__) LOG = log.getLogger(__name__)
@ -79,15 +80,19 @@ class GlanceImageStatus(object):
IMPORTING = u'importing' IMPORTING = u'importing'
@keystone.skip_unless_has_keystone_credentials()
class GlanceImageFixture(_client.HasGlanceClientMixin, tobiko.SharedFixture): class GlanceImageFixture(_client.HasGlanceClientMixin, tobiko.SharedFixture):
image_name = None # type: str image_name: typing.Optional[str] = None
username = None # type: str username: typing.Optional[str] = None
password = None # type: str password: typing.Optional[str] = None
image = None image = None
wait_interval = 5. wait_interval = 5.
def __init__(self, image_name=None, username=None, password=None): def __init__(self,
image_name: typing.Optional[str] = None,
username: typing.Optional[str] = None, password:
typing.Optional[str] = None):
super(GlanceImageFixture, self).__init__() super(GlanceImageFixture, self).__init__()
if image_name: if image_name:
@ -333,7 +338,7 @@ class FileGlanceImageFixture(UploadGranceImageFixture):
class URLGlanceImageFixture(FileGlanceImageFixture): class URLGlanceImageFixture(FileGlanceImageFixture):
image_url = None # type: str image_url: typing.Optional[str] = None
def __init__(self, image_url=None, **kwargs): def __init__(self, image_url=None, **kwargs):
super(URLGlanceImageFixture, self).__init__(**kwargs) super(URLGlanceImageFixture, self).__init__(**kwargs)

View File

@ -25,6 +25,7 @@ import tobiko
from tobiko import config from tobiko import config
from tobiko.openstack.heat import _client from tobiko.openstack.heat import _client
from tobiko.openstack.heat import _template from tobiko.openstack.heat import _template
from tobiko.openstack import keystone
LOG = log.getLogger(__name__) LOG = log.getLogger(__name__)
@ -58,6 +59,7 @@ def heat_stack_parameters(obj, stack=None):
return parameters return parameters
@keystone.skip_unless_has_keystone_credentials()
class HeatStackFixture(tobiko.SharedFixture): class HeatStackFixture(tobiko.SharedFixture):
"""Manages Heat stacks.""" """Manages Heat stacks."""

View File

@ -16,9 +16,11 @@ from __future__ import absolute_import
import collections import collections
import tobiko import tobiko
from tobiko.openstack import keystone
from tobiko.openstack.neutron import _client from tobiko.openstack.neutron import _client
@keystone.skip_unless_has_keystone_credentials()
class NetworkingExtensionsFixture(tobiko.SharedFixture): class NetworkingExtensionsFixture(tobiko.SharedFixture):
client = None client = None

View File

@ -72,7 +72,9 @@ class PingInterfaceManager(tobiko.SharedFixture):
usage = get_ping_usage(ssh_client) usage = get_ping_usage(ssh_client)
interface = find_ping_interface(usage=usage, interface = find_ping_interface(usage=usage,
interfaces=self.interfaces) interfaces=self.interfaces)
interface = interface or self.default_interface if not interface:
LOG.error('Ping interface not found: using the default one')
interface = self.default_interface
LOG.debug('Assign Ping interface %r to SSH client %r', LOG.debug('Assign Ping interface %r to SSH client %r',
interface, ssh_client) interface, ssh_client)
self.client_interfaces[ssh_client] = interface self.client_interfaces[ssh_client] = interface
@ -349,3 +351,38 @@ class InetToolsPingInterface(PingInterface):
else: else:
return ['-w', parameters.deadline, return ['-w', parameters.deadline,
'-W', parameters.deadline] '-W', parameters.deadline]
IPUTILS_PING_USAGE = """
ping: invalid option -- '-'
Usage: ping [-aAbBdDfhLnOqrRUvV] [-c count] [-i interval] [-I interface]
[-m mark] [-M pmtudisc_option] [-l preload] [-p pattern] [-Q tos]
[-s packetsize] [-S sndbuf] [-t ttl] [-T timestamp_option]
[-w deadline] [-W timeout] [hop1 ...] destination
""".strip()
@ping_interface
class BsdPingInterface(PingInterface):
def match_ping_usage(self, usage):
return usage.startswith(BSD_PING_USAGE)
has_fragment_option = False
def get_deadline_option(self, parameters):
return ['-t', parameters.deadline]
BSD_PING_USAGE = """
ping: unrecognized option `--help'
usage: ping [-AaDdfnoQqRrv] [-c count] [-G sweepmaxsize]
[-g sweepminsize] [-h sweepincrsize] [-i wait]
[-l preload] [-M mask | time] [-m ttl] [-p pattern]
[-S src_addr] [-s packetsize] [-t timeout][-W waittime]
[-z tos] host
ping [-AaDdfLnoQqRrv] [-c count] [-I iface] [-i wait]
[-l preload] [-M mask | time] [-m ttl] [-p pattern] [-S src_addr]
[-s packetsize] [-T ttl] [-t timeout] [-W waittime]
[-z tos] mcast-group
""".strip()

View File

@ -292,35 +292,51 @@ def handle_ping_command_error(error):
prefix = 'ping: ' prefix = 'ping: '
if error.startswith('ping: '): if error.startswith('ping: '):
text = error[len(prefix):] text = error[len(prefix):]
handle_ping_bad_address_error(text)
prefix = 'bad address ' handle_ping_local_error(text)
if text.startswith(prefix): handle_ping_send_to_error(text)
address = text[len(prefix):].replace("'", '').strip() handle_ping_unknow_host_error(text)
raise _exception.BadAddressPingError(address=address)
prefix = 'local error: '
if text.startswith(prefix):
details = text[len(prefix):].strip()
raise _exception.LocalPingError(details=details)
prefix = 'sendto: '
if text.startswith(prefix):
details = text[len(prefix):].strip()
raise _exception.SendToPingError(details=details)
prefix = 'unknown host'
if text.startswith(prefix):
details = text[len(prefix):].strip()
raise _exception.UnknowHostError(details=details)
suffix = ': Name or service not known'
if text.endswith(suffix):
details = text[:-len(suffix)].strip()
raise _exception.UnknowHostError(details=details)
suffix = ': No route to host'
if text.endswith(suffix):
details = text[:-len(suffix)].strip()
raise _exception.UnknowHostError(details=details)
raise _exception.PingError(details=text) raise _exception.PingError(details=text)
def handle_ping_bad_address_error(text):
prefix = 'bad address '
if text.startswith(prefix):
address = text[len(prefix):].replace("'", '').strip()
raise _exception.BadAddressPingError(address=address)
def handle_ping_local_error(text):
prefix = 'local error: '
if text.startswith(prefix):
details = text[len(prefix):].strip()
raise _exception.LocalPingError(details=details)
def handle_ping_send_to_error(text):
prefix = 'sendto: '
if text.startswith(prefix):
details = text[len(prefix):].strip()
raise _exception.SendToPingError(details=details)
def handle_ping_unknow_host_error(text):
prefix = 'unknown host'
if text.startswith(prefix):
details = text[len(prefix):].strip()
raise _exception.UnknowHostError(details=details)
suffix = ': Name or service not known'
if text.endswith(suffix):
details = text[:-len(suffix)].strip()
raise _exception.UnknowHostError(details=details)
suffix = ': No route to host'
if text.endswith(suffix):
details = text[:-len(suffix)].strip()
raise _exception.UnknowHostError(details=details)
suffix = ': Unknown host'
if text.endswith(suffix):
details = text[:-len(suffix)].strip().split()[-1]
raise _exception.UnknowHostError(details=details)

View File

@ -21,6 +21,7 @@ import testtools
import tobiko import tobiko
from tobiko import docker from tobiko import docker
from tobiko.openstack import keystone
from tobiko.openstack import topology from tobiko.openstack import topology
@ -41,6 +42,7 @@ class DockerNodeFixture(tobiko.SharedFixture):
' '.join(node.name for node in nodes)) ' '.join(node.name for node in nodes))
@keystone.skip_unless_has_keystone_credentials()
class DockerClientTest(testtools.TestCase): class DockerClientTest(testtools.TestCase):
node = tobiko.required_setup_fixture(DockerNodeFixture) node = tobiko.required_setup_fixture(DockerNodeFixture)

View File

@ -20,11 +20,13 @@ import yaml
import tobiko import tobiko
from tobiko.shell import sh from tobiko.shell import sh
from tobiko.openstack import keystone
from tobiko.openstack import nova from tobiko.openstack import nova
from tobiko.openstack import stacks from tobiko.openstack import stacks
from tobiko.tests.functional.openstack.stacks import test_cirros from tobiko.tests.functional.openstack.stacks import test_cirros
@keystone.skip_unless_has_keystone_credentials()
class CentosServerStackTest(test_cirros.CirrosServerStackTest): class CentosServerStackTest(test_cirros.CirrosServerStackTest):
"""Tests connectivity to Nova instances via floating IPs""" """Tests connectivity to Nova instances via floating IPs"""

View File

@ -18,11 +18,13 @@ from __future__ import absolute_import
import testtools import testtools
import tobiko import tobiko
from tobiko.openstack import keystone
from tobiko.openstack import stacks from tobiko.openstack import stacks
from tobiko.shell import ping from tobiko.shell import ping
from tobiko.shell import sh from tobiko.shell import sh
@keystone.skip_unless_has_keystone_credentials()
class CirrosServerStackTest(testtools.TestCase): class CirrosServerStackTest(testtools.TestCase):
"""Tests connectivity to Nova instances via floating IPs""" """Tests connectivity to Nova instances via floating IPs"""

View File

@ -18,11 +18,13 @@ from __future__ import absolute_import
import testtools import testtools
import tobiko import tobiko
from tobiko.openstack import keystone
from tobiko.openstack import neutron from tobiko.openstack import neutron
from tobiko.openstack import stacks from tobiko.openstack import stacks
class NetworkTestCase(testtools.TestCase): @keystone.skip_unless_has_keystone_credentials()
class NetworkTest(testtools.TestCase):
"""Tests network creation""" """Tests network creation"""
#: Stack of resources with a network with a gateway router #: Stack of resources with a network with a gateway router
@ -78,8 +80,9 @@ class NetworkTestCase(testtools.TestCase):
self.stack.ipv6_gateway_addresses) self.stack.ipv6_gateway_addresses)
@keystone.skip_unless_has_keystone_credentials()
@neutron.skip_if_missing_networking_extensions('net-mtu-write') @neutron.skip_if_missing_networking_extensions('net-mtu-write')
class NetworkWithNetMtuWriteTestCase(NetworkTestCase): class NetworkWithNetMtuWriteTest(NetworkTest):
#: Stack of resources with a network with a gateway router #: Stack of resources with a network with a gateway router
stack = tobiko.required_setup_fixture( stack = tobiko.required_setup_fixture(
@ -89,15 +92,17 @@ class NetworkWithNetMtuWriteTestCase(NetworkTestCase):
self.assertEqual(self.stack.mtu, self.stack.outputs.mtu) self.assertEqual(self.stack.mtu, self.stack.outputs.mtu)
@keystone.skip_unless_has_keystone_credentials()
@neutron.skip_if_missing_networking_extensions('l3-ha') @neutron.skip_if_missing_networking_extensions('l3-ha')
@neutron.skip_if_missing_networking_agents(binary='neutron-l3-agent', @neutron.skip_if_missing_networking_agents(binary='neutron-l3-agent',
count=2) count=2)
class L3HaNetworkTestCase(NetworkTestCase): class L3HaNetworkTest(NetworkTest):
#: Stack of resources with a network with a gateway router #: Stack of resources with a network with a gateway router
stack = tobiko.required_setup_fixture(stacks.L3haNetworkStackFixture) stack = tobiko.required_setup_fixture(stacks.L3haNetworkStackFixture)
@keystone.skip_unless_has_keystone_credentials()
class FloatingNetworkStackTest(testtools.TestCase): class FloatingNetworkStackTest(testtools.TestCase):
@stacks.skip_if_missing_floating_network @stacks.skip_if_missing_floating_network

View File

@ -31,6 +31,7 @@ LOG = log.getLogger(__name__)
CIENT_CLASSSES = v2_client.Client, v3_client.Client CIENT_CLASSSES = v2_client.Client, v3_client.Client
@keystone.skip_unless_has_keystone_credentials()
class TobikoKeystoneCredentialsCommandTest(testtools.TestCase): class TobikoKeystoneCredentialsCommandTest(testtools.TestCase):
def test_execute(self): def test_execute(self):
@ -41,6 +42,7 @@ class TobikoKeystoneCredentialsCommandTest(testtools.TestCase):
self.assertEqual(expected, actual) self.assertEqual(expected, actual)
@keystone.skip_unless_has_keystone_credentials()
class KeystoneClientAPITest(testtools.TestCase): class KeystoneClientAPITest(testtools.TestCase):
def test_get_keystone_client(self): def test_get_keystone_client(self):

View File

@ -20,6 +20,7 @@ import testtools
import tobiko import tobiko
from tobiko import config from tobiko import config
from tobiko.openstack import keystone
from tobiko.openstack import neutron from tobiko.openstack import neutron
from tobiko.openstack import nova from tobiko.openstack import nova
from tobiko.openstack import stacks from tobiko.openstack import stacks
@ -29,6 +30,7 @@ from tobiko.openstack import tests
CONF = config.CONF CONF = config.CONF
@keystone.skip_unless_has_keystone_credentials()
class NeutronApiTestCase(testtools.TestCase): class NeutronApiTestCase(testtools.TestCase):
"""Tests network creation""" """Tests network creation"""
@ -112,6 +114,7 @@ class NeutronApiTestCase(testtools.TestCase):
self.assertIn(agent['id'], {a['id'] for a in agents}) self.assertIn(agent['id'], {a['id'] for a in agents})
@keystone.skip_unless_has_keystone_credentials()
class PortTest(testtools.TestCase): class PortTest(testtools.TestCase):
#: Stack of resources with a network with a gateway router #: Stack of resources with a network with a gateway router
@ -159,6 +162,7 @@ class PortTest(testtools.TestCase):
self.assertIn(port_address, cidr) self.assertIn(port_address, cidr)
@keystone.skip_unless_has_keystone_credentials()
class AgentTest(testtools.TestCase): class AgentTest(testtools.TestCase):
def test_skip_if_missing_agents(self, count=1, should_skip=False, def test_skip_if_missing_agents(self, count=1, should_skip=False,
@ -192,9 +196,6 @@ class AgentTest(testtools.TestCase):
self.test_skip_if_missing_agents(count=1000000, self.test_skip_if_missing_agents(count=1000000,
should_skip=True) should_skip=True)
class NeutronAgentTest(testtools.TestCase):
def test_neutron_agents_are_alive(self): def test_neutron_agents_are_alive(self):
agents = tests.test_neutron_agents_are_alive() agents = tests.test_neutron_agents_are_alive()
# check has agents and they are all alive # check has agents and they are all alive

View File

@ -21,6 +21,7 @@ import netaddr
import testtools import testtools
import tobiko import tobiko
from tobiko.openstack import keystone
from tobiko.openstack import nova from tobiko.openstack import nova
from tobiko.openstack import stacks from tobiko.openstack import stacks
@ -34,6 +35,7 @@ class KeyPairTest(testtools.TestCase):
self.assertTrue(os.path.isfile(self.stack.key_file + '.pub')) self.assertTrue(os.path.isfile(self.stack.key_file + '.pub'))
@keystone.skip_unless_has_keystone_credentials()
class ClientTest(testtools.TestCase): class ClientTest(testtools.TestCase):
#: Stack of resources with a server attached to a floating IP #: Stack of resources with a server attached to a floating IP
@ -117,6 +119,7 @@ class ClientTest(testtools.TestCase):
self.assertEqual('ACTIVE', server.status) self.assertEqual('ACTIVE', server.status)
@keystone.skip_unless_has_keystone_credentials()
class HypervisorTest(testtools.TestCase): class HypervisorTest(testtools.TestCase):
def test_skip_if_missing_hypervisors(self, count=1, should_skip=False, def test_skip_if_missing_hypervisors(self, count=1, should_skip=False,
@ -152,6 +155,7 @@ class HypervisorTest(testtools.TestCase):
should_skip=True) should_skip=True)
@keystone.skip_unless_has_keystone_credentials()
class ServiceTest(testtools.TestCase): class ServiceTest(testtools.TestCase):
def test_wait_for_services_up(self): def test_wait_for_services_up(self):

View File

@ -21,6 +21,7 @@ from tobiko.openstack import keystone
from tobiko.openstack import octavia from tobiko.openstack import octavia
@keystone.skip_unless_has_keystone_credentials()
@keystone.skip_if_missing_service(name='octavia') @keystone.skip_if_missing_service(name='octavia')
class OctaviaClientAPITest(testtools.TestCase): class OctaviaClientAPITest(testtools.TestCase):

View File

@ -18,12 +18,14 @@ from __future__ import absolute_import
import testtools import testtools
import tobiko import tobiko
from tobiko.openstack import keystone
from tobiko.openstack import nova from tobiko.openstack import nova
from tobiko.openstack import topology from tobiko.openstack import topology
from tobiko.shell import ping from tobiko.shell import ping
from tobiko.shell import sh from tobiko.shell import sh
@keystone.skip_unless_has_keystone_credentials()
class OpenStackTopologyTest(testtools.TestCase): class OpenStackTopologyTest(testtools.TestCase):
topology = tobiko.required_setup_fixture(topology.OpenStackTopology) topology = tobiko.required_setup_fixture(topology.OpenStackTopology)

View File

@ -19,6 +19,7 @@ import testtools
import tobiko import tobiko
from tobiko.openstack import glance from tobiko.openstack import glance
from tobiko.openstack import keystone
from tobiko.openstack import nova from tobiko.openstack import nova
from tobiko.openstack import tests from tobiko.openstack import tests
@ -27,6 +28,7 @@ class MyServerStack(tests.TestServerCreationStack):
pass pass
@keystone.skip_unless_has_keystone_credentials()
class ServerCreationTest(testtools.TestCase): class ServerCreationTest(testtools.TestCase):
def test_server_creation(self): def test_server_creation(self):

View File

@ -21,6 +21,7 @@ import testtools
import tobiko import tobiko
from tobiko import podman from tobiko import podman
from tobiko.openstack import keystone
from tobiko.openstack import topology from tobiko.openstack import topology
@ -41,6 +42,7 @@ class PodmanNodeFixture(tobiko.SharedFixture):
' '.join(node.name for node in nodes)) ' '.join(node.name for node in nodes))
@keystone.skip_unless_has_keystone_credentials()
class PodmanClientTest(testtools.TestCase): class PodmanClientTest(testtools.TestCase):
node = tobiko.required_setup_fixture(PodmanNodeFixture) node = tobiko.required_setup_fixture(PodmanNodeFixture)

View File

@ -1,10 +1,12 @@
from __future__ import absolute_import from __future__ import absolute_import
import tobiko import tobiko
from tobiko.openstack import keystone
from tobiko.openstack import topology from tobiko.openstack import topology
from tobiko.shell import ip from tobiko.shell import ip
@keystone.skip_unless_has_keystone_credentials()
class NetworkNamespaceFixture(tobiko.SharedFixture): class NetworkNamespaceFixture(tobiko.SharedFixture):
network_namespace = None network_namespace = None

View File

@ -23,9 +23,11 @@ import testtools
import tobiko import tobiko
from tobiko.shell import sh from tobiko.shell import sh
from tobiko.shell import ssh from tobiko.shell import ssh
from tobiko.openstack import keystone
from tobiko.openstack import stacks from tobiko.openstack import stacks
@keystone.skip_unless_has_keystone_credentials()
class HostnameTest(testtools.TestCase): class HostnameTest(testtools.TestCase):
server_stack = tobiko.required_setup_fixture( server_stack = tobiko.required_setup_fixture(

View File

@ -22,6 +22,7 @@ import tobiko
from tobiko.shell import ifconfig from tobiko.shell import ifconfig
from tobiko.shell import sh from tobiko.shell import sh
from tobiko.shell import ssh from tobiko.shell import ssh
from tobiko.openstack import keystone
from tobiko.openstack import stacks from tobiko.openstack import stacks
@ -53,9 +54,11 @@ class IfconfigTest(testtools.TestCase):
def test_list_ip_addresses_with_ipv6(self): def test_list_ip_addresses_with_ipv6(self):
self.test_list_ip_addresses(ip_version=6) self.test_list_ip_addresses(ip_version=6)
@keystone.skip_unless_has_keystone_credentials()
def test_list_ip_addresses_with_cirros_server(self): def test_list_ip_addresses_with_cirros_server(self):
self.test_list_ip_addresses(ssh_client=self.cirros_stack.ssh_client) self.test_list_ip_addresses(ssh_client=self.cirros_stack.ssh_client)
@keystone.skip_unless_has_keystone_credentials()
def test_list_ip_addresses_with_ubuntu_server(self): def test_list_ip_addresses_with_ubuntu_server(self):
self.test_list_ip_addresses(ssh_client=self.ubuntu_stack.ssh_client) self.test_list_ip_addresses(ssh_client=self.ubuntu_stack.ssh_client)

View File

@ -15,8 +15,9 @@
# under the License. # under the License.
from __future__ import absolute_import from __future__ import absolute_import
import os
import netaddr import netaddr
import six
import testtools import testtools
import tobiko import tobiko
@ -41,6 +42,8 @@ class IpTest(testtools.TestCase):
def test_list_ip_addresses(self, ip_version=None, scope=None, def test_list_ip_addresses(self, ip_version=None, scope=None,
**execute_params): **execute_params):
if not os.path.isfile('/bin/ip'):
self.skip("'bin/ip' command not found")
ips = ip.list_ip_addresses(ip_version=ip_version, scope=scope, ips = ip.list_ip_addresses(ip_version=ip_version, scope=scope,
**execute_params) **execute_params)
self.assertIsInstance(ips, tobiko.Selection) self.assertIsInstance(ips, tobiko.Selection)
@ -125,10 +128,12 @@ class IpTest(testtools.TestCase):
**execute_params) **execute_params)
def test_list_namespaces(self, **execute_params): def test_list_namespaces(self, **execute_params):
if not os.path.isfile('/bin/ip'):
self.skip("'bin/ip' command not found")
namespaces = ip.list_network_namespaces(**execute_params) namespaces = ip.list_network_namespaces(**execute_params)
self.assertIsInstance(namespaces, list) self.assertIsInstance(namespaces, list)
for namespace in namespaces: for namespace in namespaces:
self.assertIsInstance(namespace, six.string_types) self.assertIsInstance(namespace, str)
self.test_list_ip_addresses(network_namespace=namespace) self.test_list_ip_addresses(network_namespace=namespace)
def test_list_namespaces_with_centos_server(self): def test_list_namespaces_with_centos_server(self):

View File

@ -15,6 +15,8 @@
# under the License. # under the License.
from __future__ import absolute_import from __future__ import absolute_import
import os
import netaddr import netaddr
import testtools import testtools
@ -98,6 +100,8 @@ class PingTest(testtools.TestCase):
def test_ping_hosts(self, ssh_client=None, network_namespace=None, def test_ping_hosts(self, ssh_client=None, network_namespace=None,
**params): **params):
if not os.path.isfile('/sbin/ip'):
self.skip("'/sbin/ip' command not found")
ips = ip.list_ip_addresses(ssh_client=ssh_client, ips = ip.list_ip_addresses(ssh_client=ssh_client,
network_namespace=network_namespace) network_namespace=network_namespace)
reachable_ips, unrecheable_ips = ping.ping_hosts( reachable_ips, unrecheable_ips = ping.ping_hosts(

View File

@ -51,18 +51,20 @@ def normalize_path(path):
def execute(command, *args, **kwargs): def execute(command, *args, **kwargs):
capture_stdout = kwargs.pop('capture_stdout', True) capture_stdout = kwargs.pop('capture_stdout', True)
universal_newlines = kwargs.pop('universal_newlines', True) universal_newlines = kwargs.pop('universal_newlines', True)
check = kwargs.pop('check', True)
if args or kwargs: if args or kwargs:
command = command.format(*args, **kwargs) command = command.format(*args, **kwargs)
command = command.strip() command = command.strip()
if capture_stdout: stdout = capture_stdout and subprocess.PIPE or None
execute_func = subprocess.check_output
else:
execute_func = subprocess.check_call
return execute_func(['/bin/bash', '-x', '-c', command], result = subprocess.run(['/bin/bash', '-x', '-c', command],
shell=False, universal_newlines=universal_newlines) stdout=stdout, shell=False,
universal_newlines=universal_newlines)
if check:
result.check_returncode()
return result.stdout
def get_posargs(args=None): def get_posargs(args=None):

View File

@ -106,7 +106,8 @@ def log_environ():
def log_tests_results(): def log_tests_results():
common.execute('stestr last --all-attachments >> "{log_file}"', common.execute('stestr last --all-attachments >> "{log_file}"',
log_file=TOX_REPORT_LOG, log_file=TOX_REPORT_LOG,
capture_stdout=False) capture_stdout=False,
check=False)
def run_test_cases(): def run_test_cases():

View File

@ -1,6 +1,6 @@
[tox] [tox]
envlist = bindep,linters,py3,lower-constraints envlist = bindep,linters,py3,lower-constraints,functional
minversion = 3.8.0 minversion = 3.8.0