Skip to content

Commit

Permalink
[1LP][RFR] No more session fixtures (ManageIQ#9639)
Browse files Browse the repository at this point in the history
there is a plan to implement appliance markers and generate appliances based on those markers.
We should get rid of session scoped fixuters using appliance fixture. This PR is one of steps we have to undertake to achieve above.

Adding hook registering and calling for the appliance stack, in order to call methods on appliances, whenever they're used for tests. Replaces previous session scoped fixtures that were modifying the appliance at the start of the session.
  • Loading branch information
izapolsk authored and spusateri committed Jan 27, 2020
1 parent 786e886 commit db413bb
Show file tree
Hide file tree
Showing 11 changed files with 77 additions and 98 deletions.
56 changes: 0 additions & 56 deletions cfme/fixtures/base.py
Original file line number Diff line number Diff line change
@@ -1,56 +0,0 @@
import pytest

from cfme.utils.appliance import DummyAppliance
from cfme.utils.log import logger


@pytest.fixture(scope="session", autouse=True)
def ensure_websocket_role_disabled(appliance):
# TODO: This is a temporary solution until we find something better.
if isinstance(appliance, DummyAppliance) or appliance.is_dev:
return
server_settings = appliance.server.settings
roles = server_settings.server_roles_db
if 'websocket' in roles and roles['websocket']:
logger.info('Disabling the websocket role to ensure we get no intrusive popups')
server_settings.disable_server_roles('websocket')


@pytest.fixture(scope="session", autouse=True)
def fix_missing_hostname(appliance):
"""Fix for hostname missing from the /etc/hosts file
Note: Affects RHOS-based appliances but can't hurt the others so
it's applied on all.
"""
if isinstance(appliance, DummyAppliance) or appliance.is_dev:
return
logger.info("Checking appliance's /etc/hosts for a resolvable hostname")
hosts_grep_cmd = 'grep {} /etc/hosts'.format(appliance.get_resolvable_hostname())
with appliance.ssh_client as ssh_client:
if ssh_client.run_command(hosts_grep_cmd).failed:
logger.info('Setting appliance hostname')
if not appliance.set_resolvable_hostname():
# not resolvable, just use hostname output through appliance_console_cli to modify
cli_hostname = ssh_client.run_command('hostname').output.rstrip('\n')
logger.warning('Unable to resolve hostname, using `hostname`: %s', cli_hostname)
appliance.appliance_console_cli.set_hostname(cli_hostname)

if ssh_client.run_command('grep $(hostname) /etc/hosts').failed:
logger.error('Failed to mangle /etc/hosts')


@pytest.fixture(scope="session", autouse=True)
def fix_missing_appliance_name(appliance):
"""Fix for an empty appliance server name"""
if isinstance(appliance, DummyAppliance) or appliance.is_dev:
return
logger.info('Checking appliance server name is set')
if appliance.server.name == '':
appliance.update_advanced_settings(
{
'server': {
'name': getattr(appliance, '_default_name', 'EVM')
}
}
)
10 changes: 0 additions & 10 deletions cfme/fixtures/browser.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import base64
from urllib.error import URLError

import pytest
from py.error import ENOENT

import cfme.utils.browser
from cfme.fixtures.artifactor_plugin import fire_art_test_hook
from cfme.utils import browser as browser_module
from cfme.utils import safe_string
from cfme.utils.appliance import find_appliance
from cfme.utils.browser import take_screenshot
Expand Down Expand Up @@ -135,11 +133,3 @@ def pytest_sessionfinish(session, exitstatus):
if failed_test_tracking['tests']:
failed_tests_report = failed_tests_template.render(**failed_test_tracking)
outfile.write(failed_tests_report)


@pytest.fixture(scope='session')
def browser(appliance):
from cfme.utils.appliance import DummyAppliance
if isinstance(appliance, DummyAppliance):
pytest.xfail("browser not supported with DummyAppliance")
return browser_module.browser
2 changes: 1 addition & 1 deletion cfme/fixtures/cfme_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@


@pytest.fixture(scope="session")
def cfme_data(request):
def cfme_data():
return conf.cfme_data
4 changes: 2 additions & 2 deletions cfme/fixtures/tag.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from cfme.utils.log import logger


@pytest.fixture(scope="session")
@pytest.fixture(scope="module")
def category(appliance):
"""
Returns random created category object
Expand All @@ -25,7 +25,7 @@ def category(appliance):
cg.delete_if_exists()


@pytest.fixture(scope="session")
@pytest.fixture(scope="module")
def tag(category, appliance):
"""
Returns random created tag object
Expand Down
19 changes: 0 additions & 19 deletions cfme/fixtures/widgets.py

This file was deleted.

2 changes: 1 addition & 1 deletion cfme/tests/configure/test_server_roles.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
{'all': [], 'sets': {}})


@pytest.fixture(scope="session")
@pytest.fixture(scope="module")
def all_possible_roles(appliance):
roles = server_roles_conf['all']
if roles == []:
Expand Down
1 change: 0 additions & 1 deletion cfme/tests/test_modules_importable.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
'cfme/intelligence/chargeback/rates.py',
'cfme/intelligence/chargeback/assignments.py',
'cfme/intelligence/chargeback/__init__.py',
'cfme/fixtures/widgets.py',
'cfme/dashboard.py',
'cfme/configure/tasks.py',
'cfme/scripting/bz.py',
Expand Down
74 changes: 69 additions & 5 deletions cfme/utils/appliance/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import attr
import dateutil.parser
import fauxfactory
import pytest
import pytz
import requests
import sentaku
Expand Down Expand Up @@ -2873,28 +2874,49 @@ def _get_latest_template():


class ApplianceStack(LocalStack):
def __init__(self):
self._registered_hooks = {'on push': [], 'on pop': []}
super(ApplianceStack, self).__init__()

def push(self, obj):
was_before = self.top
super(ApplianceStack, self).push(obj)

logger.info("Pushed appliance {} on stack (was {} before) ".format(
obj.hostname, was_before.hostname if was_before else 'empty'))
logger.info(f"Pushed appliance {obj.hostname} on stack "
f"(was {was_before.hostname if was_before else 'empty'} before)")
if obj.browser_steal:
from cfme.utils import browser
browser.start()

for hook in self._registered_hooks['on push']:
logger.info(f"appliance hook {hook.__name__} triggered on push")
hook(obj)

def pop(self):
was_before = super(ApplianceStack, self).pop()
if was_before:
for hook in self._registered_hooks['on pop']:
logger.info(f"appliance hook {hook.__name__} triggered on pop")
hook(was_before)

current = self.top
logger.info("Popped appliance %s from the stack (now there is %s)",
was_before.hostname if was_before else 'empty',
current.hostname if current else 'empty')
logger.info(f"Popped appliance {was_before.hostname if was_before else 'empty'} from the "
f"stack (now there is {current.hostname if current else 'empty'})")

if was_before and was_before.browser_steal:
from cfme.utils import browser
browser.start()
return was_before

def register_hook(self, hook, func):
if hook in self._registered_hooks:
logger.debug(f"registering appliance method {func.__name__} on hook {hook}")
self._registered_hooks.get(hook).append(func)
else:
msg = f" there is no hook called {hook}"
logger.exception(msg)
raise ValueError(msg)


stack = ApplianceStack()

Expand Down Expand Up @@ -2970,6 +2992,10 @@ class DummyAppliance(object):
url = 'http://dummies.r.us'
is_dummy = attr.ib(default=True)

@property
def browser(self):
pytest.xfail("browser not supported with DummyAppliance")

@property
def is_downstream(self):
return not (self.version.is_in_series('master') or self.version.is_in_series('upstream'))
Expand Down Expand Up @@ -3139,3 +3165,41 @@ def __init__(self, appliance=None):
class MiqImplementationContext(sentaku.ImplementationContext):
""" Our context for Sentaku"""
pass


def ensure_websocket_role_disabled(appliance):
# TODO: This is a temporary solution until we find something better.
if isinstance(appliance, DummyAppliance) or appliance.is_dev:
return
server_settings = appliance.server.settings
roles = server_settings.server_roles_db
if 'websocket' in roles and roles['websocket']:
logger.info('Disabling the websocket role to ensure we get no intrusive popups')
server_settings.disable_server_roles('websocket')


def fix_missing_hostname(appliance):
"""Fix for hostname missing from the /etc/hosts file
Note: Affects RHOS-based appliances but can't hurt the others so
it's applied on all.
"""
if isinstance(appliance, DummyAppliance) or appliance.is_dev:
return
logger.info("Checking appliance's /etc/hosts for a resolvable hostname")
hosts_grep_cmd = 'grep {} /etc/hosts'.format(appliance.get_resolvable_hostname())
with appliance.ssh_client as ssh_client:
if ssh_client.run_command(hosts_grep_cmd).failed:
logger.info('Setting appliance hostname')
if not appliance.set_resolvable_hostname():
# not resolvable, just use hostname output through appliance_console_cli to modify
cli_hostname = ssh_client.run_command('hostname').output.rstrip('\n')
logger.warning('Unable to resolve hostname, using `hostname`: %s', cli_hostname)
appliance.appliance_console_cli.set_hostname(cli_hostname)

if ssh_client.run_command('grep $(hostname) /etc/hosts').failed:
logger.error('Failed to mangle /etc/hosts')


stack.register_hook('on push', ensure_websocket_role_disabled)
stack.register_hook('on push', fix_missing_hostname)
4 changes: 3 additions & 1 deletion cfme/utils/tests/test_ipappliance.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ def test_ipappliance_from_url():

@pytest.mark.skipif(lambda request: request.config.getoption('--dummy-appliance', default=False),
reason="infra_provider cant support dummy instance")
def test_ipappliance_managed_providers(appliance, infra_provider, request):
def test_ipappliance_managed_providers(appliance, infra_provider):
assert infra_provider in appliance.managed_known_providers


@pytest.mark.skipif(lambda request: request.config.getoption('--dummy-appliance', default=False),
reason="infra_provider cant support dummy instance")
def test_context_hack(monkeypatch):

ip_a = IPAppliance.from_url('http://127.0.0.2/')
Expand Down
2 changes: 1 addition & 1 deletion cfme/utils/tests/test_simple_locators.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@


@pytest.fixture(scope='module')
def test_page(browser, datafile, appliance):
def test_page(datafile, appliance):
selenium = appliance.browser.widgetastic.selenium
test_page_html = datafile('/utils/test_simple_locators/elements.html').read()
selenium.get('data:text/html;base64,{}'.format(
Expand Down
1 change: 0 additions & 1 deletion conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,5 @@
"cfme.fixtures.vm",
"cfme.fixtures.vm_console",
"cfme.fixtures.vporizer",
"cfme.fixtures.widgets",
"cfme.fixtures.xunit_tools",
]

0 comments on commit db413bb

Please sign in to comment.