Skip to content

Commit

Permalink
Tests for the conf engine
Browse files Browse the repository at this point in the history
  • Loading branch information
Albin Stjerna committed May 16, 2017
1 parent d0fcc9e commit ce2f7ca
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 33 deletions.
46 changes: 46 additions & 0 deletions conftest.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
# content of conftest.py

from storage_api import extensions

import os
import base64
import logging

import pytest
from hypothesis import settings, Verbosity

import betamax
from betamax_serializers import pretty_json
from unittest import mock

log = logging.getLogger(__name__)

betamax.Betamax.register_serializer(pretty_json.PrettyJSONSerializer)

Expand Down Expand Up @@ -47,3 +54,42 @@ def pytest_runtest_setup(item):
('{0}:{1}'.format(ontap_username,
ontap_password)).encode('utf-8'))
.decode('utf-8'))


@pytest.fixture(scope="function")
def temp_app(request):
"""
Fixture to set up a test app.
"""

with mock.patch.dict(os.environ, {'SAPI_BACKENDS':
("dummy🌈DummyStorage🦄"
"netapp🌈DummyStorage🦄"
"ceph🌈DummyStorage"),
'SAPI_OAUTH_CLIENT_ID': "dummy",
'SAPI_OAUTH_SECRET_KEY': "dummy"}):
from storage_api import app

app.app.testing = True

yield app.app



@pytest.fixture(scope="function")
def client(temp_app):
"""
Fixture to set up a Flask test client
"""

extensions.DummyStorage().init_app(temp_app, endpoint="dummy")
extensions.DummyStorage().init_app(temp_app, endpoint="netapp")
extensions.DummyStorage().init_app(temp_app, endpoint="ceph")

with temp_app.test_client() as client:
yield client

log.debug("App teardown initiated: re-initialising dummy backend")
extensions.DummyStorage().init_app(temp_app, endpoint="dummy")
extensions.DummyStorage().init_app(temp_app, endpoint="netapp")
extensions.DummyStorage().init_app(temp_app, endpoint="ceph")
15 changes: 11 additions & 4 deletions storage_api/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,22 @@ def load_backend_conf(app, backends_module):
backend.init_app(app, endpoint=endpoint)


def set_oauth_property(app, key_name, default_value):
def set_oauth_property(app, key_name, default_value=None):
"""
Helper: fetch an OAuth property named PROPRETY_NAME from an
environment variable named SAPI_OAUTH_PROPERTY_NAME into a
configuration field named OAUTH_PROPERTY_NAME.
Raises KeyError if the variable is not set and no default value was
passed.
"""

internal_key = 'OAUTH_{}'.format(key_name)
env_key = 'SAPI_{}'.format(internal_key)

if not default_value and env_key not in os.environ:
raise KeyError("${} not set!".format(env_key))

app.config[internal_key] = os.getenv(env_key, default_value)
app.logger.debug("Set OAuth configuration key {} from {}"
.format(internal_key, env_key))
Expand All @@ -71,8 +78,8 @@ def load_oauth_conf(app):
"""
app.logger.info("Loading OAuth configuration keys...")

set_oauth_property(app, 'CLIENT_ID', 'dummy_id')
set_oauth_property(app, 'SECRET_KEY', 'dummy_key')
set_oauth_property(app, 'CLIENT_ID')
set_oauth_property(app, 'SECRET_KEY')
set_oauth_property(app, 'ACCESS_TOKEN_URL',
'https://oauth.web.cern.ch/OAuth/Token')
set_oauth_property(app, 'AUTHORIZE_URL',
Expand All @@ -91,7 +98,7 @@ def set_auth_string(app, role_name):

role_name = role_name.upper()
key_name = "{}_GROUPS".format(role_name)
env_var_name = "SAPI_ROLE_{}_GROUPS".format(role_name)
env_var_name = "SAPI_ROLE_{}".format(key_name)

group_string = os.getenv(env_var_name, "")

Expand Down
5 changes: 4 additions & 1 deletion storage_api/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@ def deco(f):
# http://stackoverflow.com/a/26853961
# Waiting for python 3.5 when we can just do z = {**x, **y}
def merge_two_dicts(x, y):
"""Given two dicts, merge them into a new dict as a shallow copy."""
"""
Given two dicts, merge them into a new dict as a shallow copy,
keeping keys from y if they are already in x
"""
z = x.copy()
z.update(y)
return z
Expand Down
28 changes: 0 additions & 28 deletions tests/test_apis.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
from storage_api.apis import common
from storage_api import extensions
from storage_api.utils import compose_decorators

import json
from urllib.parse import urlencode
from contextlib import contextmanager
import uuid
import logging
import os
from functools import partial
from unittest import mock

import pytest
from hypothesis import given
Expand Down Expand Up @@ -122,31 +119,6 @@ def _open(client, path, method, data={}, **params):
_patch = partial(_open, method="PATCH")


@pytest.fixture(scope="function")
def client(request):
"""
Fixture to set up a Flask test client
"""
with mock.patch.dict(os.environ, {'SAPI_BACKENDS':
("dummy🌈DummyStorage🦄"
"netapp🌈DummyStorage🦄"
"ceph🌈DummyStorage")}):
from storage_api import app

app.app.testing = True
extensions.DummyStorage().init_app(app.app, endpoint="dummy")
extensions.DummyStorage().init_app(app.app, endpoint="netapp")
extensions.DummyStorage().init_app(app.app, endpoint="ceph")

with app.app.test_client() as client:
yield client

log.debug("App teardown initiated: re-initialising dummy backend")
extensions.DummyStorage().init_app(app.app, endpoint="dummy")
extensions.DummyStorage().init_app(app.app, endpoint="netapp")
extensions.DummyStorage().init_app(app.app, endpoint="ceph")


def init_vols_from_params(client, namespace, auth, vol_exists, volume_name):
volume_resource = '/{}/volumes/{}'.format(namespace, volume_name)
authorised = auth == "authorised"
Expand Down
64 changes: 64 additions & 0 deletions tests/test_conf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
from storage_api import conf
from storage_api.utils import merge_two_dicts
from storage_api.apis.common.auth import USER_ROLES

from unittest import mock
import os

import pytest

OAUTH_CONF_KEYS = ['OAUTH_CLIENT_ID', 'OAUTH_SECRET_KEY',
'OAUTH_ACCESS_TOKEN_URL', 'OAUTH_AUTHORIZE_URL',
'OAUTH_GROUPS_URL',
'OAUTH_CALLBACK_URL_RELATIVE']

DEFAULT_OAUTH_CONF = {'SAPI_OAUTH_CLIENT_ID': "dummy",
'SAPI_OAUTH_SECRET_KEY': "dummy"}


@mock.patch.dict(os.environ, {})
def test_read_empty_oauth_env_crashes(temp_app):
with pytest.raises(KeyError):
conf.load_oauth_conf(temp_app)


@mock.patch.dict(os.environ, {})
def test_read_empty_backend_env_crashes(temp_app):
with pytest.raises(KeyError):
conf.load_backend_conf(temp_app, backends_module=mock.MagicMock)


@pytest.mark.parametrize('oauth_conf_key', OAUTH_CONF_KEYS)
def test_read_empty_backend_env_values(temp_app, oauth_conf_key):
sentinel_value = "sentinel_value-123"
with mock.patch.dict(os.environ,
merge_two_dicts(DEFAULT_OAUTH_CONF,
{"SAPI_{}".format(oauth_conf_key):
sentinel_value})):
conf.load_oauth_conf(temp_app)
assert temp_app.config[oauth_conf_key] == sentinel_value


@pytest.mark.parametrize('role', USER_ROLES)
def test_set_auth_string(temp_app, role):
groups = set(["a-group", "another-group", "a-third-group",
"a group with spaces"])
with mock.patch.dict(os.environ,
{"SAPI_ROLE_{}_GROUPS".format(role):
",".join(groups)}):
conf.set_auth_string(temp_app, role)
assert temp_app.config["{}_GROUPS".format(role)] == groups


@mock.patch.dict(os.environ, {})
def test_set_auth_string_empty_user_env(temp_app):
conf.set_auth_string(temp_app, 'USER')
assert temp_app.config['USER_GROUPS'] == set()
assert temp_app.config['USER_IS_UNAUTHENTICATED']


@mock.patch.dict(os.environ, {'SAPI_ROLE_USER_GROUPS': 'it-db-ims'})
def test_set_auth_string_user_groups_set(temp_app):
conf.set_auth_string(temp_app, 'USER')
assert temp_app.config['USER_GROUPS'] == set(['it-db-ims'])
assert not temp_app.config['USER_IS_UNAUTHENTICATED']

0 comments on commit ce2f7ca

Please sign in to comment.