Commit c9ecd7f2 authored by Georges Racinet's avatar Georges Racinet 🦑
Browse files

Testing production servers: first test without root

We introduce a new "Group owner" CLI option to specify the
relevant user, with the idea in mind that all test data will
evntually be created inside this group. For now it is
in the user personal namespace for simplicity.

The basic idea is to avoid changing the test itself,
playing on the fixtures. The first test to actually
work in this mode is the very simple `push_basic` test.

Of course some tests perform more server-side object
creation, assuming admin powers, and would need deeper
adaptation, but a good majority of our tests should work
readily.

To achieve this, we subclass `Heptapod` and replace preparation
(of the `root` and `test_basic` users) with preparation of the
given Group owner.

--HG--
branch : stable
parent 368dfe7d4fd2
......@@ -15,6 +15,7 @@ from tests.utils import git
from tests.utils import hg
from tests.utils.heptapod import (
Heptapod,
ProductionHeptapod,
OmnibusHeptapod,
DockerHeptapod,
SourceHeptapod,
......@@ -49,6 +50,16 @@ def pytest_addoption(parser):
"for a production installation, with precreated "
"users instead of taking with the root account. "
"Implies --heptapod-remote and requires more parameters.")
group = parser.getgroup(
'Heptapod production servers',
description="Required and optional settings to run functional "
"tests against production servers")
group.addoption('--heptapod-prod-group-owner-credentials',
help="prod servers only: numeric id, username and "
"password for owner of the group where most of the "
"testing will happen. "
"Provided as colon separated fields, such as "
"123:ftest_owner:s1cre3t.")
parser.addoption('--heptapod-remote', action='store_true',
help="Test a remote server. This means that no "
"direct command nor file system access is possible "
......@@ -213,7 +224,13 @@ def heptapod(pytestconfig):
try:
if active_threads == 1: # we're the first
if pytestconfig.getoption('heptapod_source_install'):
if pytestconfig.getoption('heptapod_prod_server'):
heptapod = ProductionHeptapod(
group_owner_credentials=pytestconfig.getoption(
'heptapod_prod_group_owner_credentials'),
**common
)
elif pytestconfig.getoption('heptapod_source_install'):
repos_root = pytestconfig.getoption(
'heptapod_repositories_root')
heptapod = SourceHeptapod(repositories_root=repos_root,
......@@ -224,9 +241,6 @@ def heptapod(pytestconfig):
**common)
elif pytestconfig.getoption('heptapod_remote'):
heptapod = Heptapod(**common)
elif pytestconfig.getoption('prod_server'):
# TODO will maybe become a sub class (or not)
heptapod = Heptapod(**common)
elif pytestconfig.getoption('heptapod_omnibus'):
heptapod = OmnibusHeptapod(**common)
else:
......@@ -250,7 +264,9 @@ def heptapod(pytestconfig):
@contextlib.contextmanager
def project_fixture(heptapod, name_prefix, owner, group=None, **opts):
def project_fixture(heptapod, name_prefix, owner=None, group=None, **opts):
if owner is None:
owner = heptapod.default_user_name
name = '%s_%s' % (name_prefix, str(time.time()).replace('.', '_'))
with Project.api_create(heptapod, owner, name,
group=group, **opts) as proj:
......@@ -281,7 +297,7 @@ def additional_user(heptapod, accepts_concurrent):
@pytest.fixture()
def test_project(heptapod, accepts_concurrent):
with project_fixture(heptapod, 'test_project', 'root') as proj:
with project_fixture(heptapod, 'test_project') as proj:
yield proj
......
......@@ -67,6 +67,9 @@ class Heptapod:
chrome_driver_args = ()
default_user_name = 'root'
"""Default user for project, group creation etc."""
def __init__(self, url, ssh_user, ssh_port,
hg_native=False,
reverse_call_host=None,
......@@ -472,6 +475,52 @@ class Heptapod:
assert self.settings['hashed_storage_enabled'] is hashed_storage
class ProductionHeptapod(Heptapod):
"""An Heptapod server for which we don't have the root password.
This allows tests to be naturally sandboxed, typically in the groups
and personal namespaces of a couple of users.
"""
def __init__(self, group_owner_credentials, **kw):
super(ProductionHeptapod, self).__init__(**kw)
user_id, name, pwd = group_owner_credentials.split(':', 2)
user_id = int(user_id)
self.default_user_name = name
self.load_instance_cache()
user = self.users.get(name)
if user is None:
user = self.users[name] = User(heptapod=self,
id=user_id,
name=name,
password=pwd)
else:
# id and password could have changed since last execution
user.id = user_id
user.password = pwd
self.group_owner = user
def prepare(self, root_password):
"""Prepare the group owner.
root password is just ignored in this subclass.
"""
start = time.time()
assert not self.dead, "Heptapod server marked dead by previous test."
if self.dead is None:
self.wait_startup(
wait_after_first_response=self.wait_after_first_response)
logger.info("Preparing Group owner: %r", self.group_owner)
self.group_owner.ensure_private_token()
self.update_instance_cache()
logger.info("All preparations done in %.2f seconds. "
"Proceeding with tests.", time.time() - start)
class OmnibusHeptapod(Heptapod):
fs_access = True
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment