commands/cook: add prechecks on recipe (#16599)

This commit is contained in:
Christophe Siraut 2019-03-27 17:34:01 +01:00
parent 2e02dd0d35
commit 73848f82f3
7 changed files with 179 additions and 1 deletions

View File

@ -35,7 +35,7 @@ from hobo.agent.common.management.commands.hobo_deploy import (
from hobo.multitenant.middleware import TenantMiddleware
from hobo.environment.models import (AVAILABLE_SERVICES, Authentic, Wcs, Hobo,
Passerelle, Combo, Fargo, Welco, MandayeJS, Chrono, Corbo, BiJoe,
Variable)
Variable, ServiceBase)
from hobo.deploy.signals import notify_agents
from hobo.theme.utils import set_theme
from hobo.profile.models import AttributeDefinition
@ -53,10 +53,12 @@ class Command(BaseCommand):
parser.add_argument(
'--timeout', type=int, action='store', default=120,
help='set the timeout for the wait_operationals method')
parser.add_argument('--permissive', action='store_true', help='ignore integrity checks')
def handle(self, recipe, *args, **kwargs):
self.verbosity = kwargs.get('verbosity')
self.timeout = kwargs.get('timeout')
self.permissive = kwargs.get('permissive')
self.run_cook(recipe)
if self.verbosity:
print 'All steps executed successfully. Your environment should now be ready.'
@ -64,6 +66,7 @@ class Command(BaseCommand):
def run_cook(self, filename):
recipe = json.load(open(filename))
variables = {}
steps = []
if 'load-variables-from' in recipe:
variables.update(json.load(open(
os.path.join(os.path.dirname(filename), recipe['load-variables-from']))))
@ -75,6 +78,11 @@ class Command(BaseCommand):
continue
action_args[arg] = string.Template(
action_args[arg]).substitute(variables)
if not self.permissive:
self.check_action(action, action_args)
steps.append((action, action_args))
for action, action_args in steps:
getattr(self, action.replace('-', '_'))(**action_args)
if self.must_notify:
notify_agents(None)
@ -281,3 +289,14 @@ class Command(BaseCommand):
current_tenant = connection.get_tenant()
self.run_cook(filename)
connection.set_tenant(current_tenant)
def check_action(self, action, action_args):
if not hasattr(self, action.replace('-', '_')):
raise CommandError('Error: Unknown action %s' % action)
if 'url' in action_args.keys():
url = action_args['url']
service = ServiceBase(title='dummy', base_url=url)
if not service.is_resolvable():
raise CommandError('Error: %s is not resolvable' % url)
if not service.has_valid_certificate():
raise CommandError('Error: %s has no valid certificate' % url)

54
tests/test_cook.py Normal file
View File

@ -0,0 +1,54 @@
import pytest
from django.core.management.base import CommandError
from hobo.environment.models import ServiceBase
from hobo.environment.management.commands.cook import Command
def test_check_action(monkeypatch):
"""no exception raised if url are available"""
command = Command()
command.server_action = 'mock a server_action handler (ex: hobo-create)'
action, action_args = 'server-action', {u'url': u'https://test.org/'}
monkeypatch.setattr(ServiceBase, 'is_resolvable', lambda x: True)
monkeypatch.setattr(ServiceBase, 'has_valid_certificate', lambda x: True)
command.check_action(action, action_args)
assert True
def test_check_action_unknown_action(monkeypatch):
"""raise CommandError"""
command = Command()
command.server_action = 'mock a server_action handler (ex: hobo-create)'
action, action_args = 'not-a-server-action', {u'url': u'https://test.org/'}
monkeypatch.setattr(ServiceBase, 'is_resolvable', lambda x: True)
monkeypatch.setattr(ServiceBase, 'has_valid_certificate', lambda x: True)
with pytest.raises(CommandError) as e_info:
command.check_action(action, action_args)
assert 'Unknown action not-a-server-action' in str(e_info.value)
def test_check_action_unresolvable(monkeypatch):
"""raise CommandError"""
command = Command()
command.server_action = 'mock a server_action handler (ex: hobo-create)'
action, action_args = 'server-action', {u'url': u'https://test.org/'}
monkeypatch.setattr(ServiceBase, 'is_resolvable', lambda x: False)
monkeypatch.setattr(ServiceBase, 'has_valid_certificate', lambda x: True)
with pytest.raises(CommandError) as e_info:
command.check_action(action, action_args)
assert 'is not resolvable' in str(e_info.value)
def test_check_action_invalid_certificat(monkeypatch):
"""raise CommandError"""
command = Command()
command.server_action = 'mock a server_action handler (ex: hobo-create)'
action, action_args = 'server-action', {u'url': u'https://test.org/'}
monkeypatch.setattr(ServiceBase, 'is_resolvable', lambda x: True)
monkeypatch.setattr(ServiceBase, 'has_valid_certificate', lambda x: False)
with pytest.raises(CommandError) as e_info:
command.check_action(action, action_args)
assert 'has no valid certificate' in str(e_info.value)

49
tests_schemas/conftest.py Normal file
View File

@ -0,0 +1,49 @@
import pytest
from django.core.management import call_command
from django.db import connection
from tenant_schemas.test.client import TenantClient
from tenant_schemas.utils import tenant_context
from hobo.environment.management.commands.cook import Command
from hobo.multitenant.middleware import TenantMiddleware
@pytest.fixture(scope='session')
def client(request, tenant_schema):
name = 'hobo.foobar'
tenant = TenantMiddleware.get_tenant_by_hostname(name)
with tenant_context(tenant):
return TenantClient(tenant)
@pytest.fixture(scope='session')
def tenant_schema(django_db_setup, django_db_blocker):
name = 'hobo.foobar'
with django_db_blocker.unblock():
call_command('create_hobo_tenant', name)
tenant = TenantMiddleware.get_tenant_by_hostname(name)
connection.set_tenant(tenant)
@pytest.fixture
def fake_notify(monkeypatch):
services = {}
def notify_agents_mock(*args, **kwargs):
from hobo.deploy.utils import get_hobo_json
environment = get_hobo_json()
for service in environment.get('services', []):
if service.keys() and service['slug'] not in services.keys():
services[service['slug']] = service
def fake_wait(*args, **kwargs):
pass
monkeypatch.setattr('hobo.environment.management.commands.cook.notify_agents', notify_agents_mock)
monkeypatch.setattr('hobo.deploy.signals.notify_agents', notify_agents_mock)
monkeypatch.setattr(Command, 'wait_operationals', fake_wait)
return services

19
tests_schemas/recipe.json Normal file
View File

@ -0,0 +1,19 @@
{
"variables": {
"domain": "dev.entrouvert.org"
},
"steps": [
{"create-hobo": {
"url": "https://${domain}/"
}},
{"create-authentic": {
"url": "https://${domain}/",
"title": "Connexion"
}},
{"create-combo": {
"url": "https://${domain}/",
"title": "Portail",
"template_name": "portal-user"
}}
]
}

14
tests_schemas/settings.py Normal file
View File

@ -0,0 +1,14 @@
import tempfile
TENANT_BASE = tempfile.mkdtemp('hobo-tenant-base')
TENANT_MODEL = 'multitenant.Tenant'
MIDDLEWARE_CLASSES = ('hobo.multitenant.middleware.TenantMiddleware',) + MIDDLEWARE_CLASSES
DATABASES = {
'default': {
'ENGINE': 'tenant_schemas.postgresql_backend',
'NAME': 'test_hobo',
}
}
DATABASE_ROUTERS = ('tenant_schemas.routers.TenantSyncRouter',)
INSTALLED_APPS = ('hobo.multitenant', 'hobo') + INSTALLED_APPS
SHARED_APPS = ()
TENANT_APPS = INSTALLED_APPS

View File

@ -0,0 +1,20 @@
import pytest
from django.core.management import call_command
from django.core.management.base import CommandError
from hobo.environment.models import ServiceBase
def test_cook(db, fake_notify, monkeypatch):
monkeypatch.setattr(ServiceBase, 'is_resolvable', lambda x: True)
monkeypatch.setattr(ServiceBase, 'has_valid_certificate', lambda x: True)
call_command('cook', 'tests_schemas/recipe.json')
assert(len(fake_notify) == 3)
def test_cook_unresolvable(db, fake_notify, monkeypatch):
monkeypatch.setattr(ServiceBase, 'is_resolvable', lambda x: False)
with pytest.raises(CommandError) as e_info:
call_command('cook', 'tests_schemas/recipe.json')
assert 'is not resolvable' in str(e_info.value)

View File

@ -15,6 +15,8 @@ setenv =
BRANCH_NAME={env:BRANCH_NAME:}
hobo: DJANGO_SETTINGS_MODULE=hobo.settings
hobo: HOBO_SETTINGS_FILE=tests/settings.py
schemas: DJANGO_SETTINGS_MODULE=hobo.settings
schemas: HOBO_SETTINGS_FILE=tests_schemas/settings.py
multitenant: PYTHONPATH=tests_multitenant
multitenant: DJANGO_SETTINGS_MODULE=settings
multipublik: PYTHONPATH=tests_multipublik
@ -56,6 +58,7 @@ deps:
commands =
./getlasso.sh
hobo: py.test {env:COVERAGE:} {env:NOMIGRATIONS:} {posargs:tests/}
schemas: py.test {env:COVERAGE:} {env:NOMIGRATIONS:} {posargs:tests_schemas/}
multitenant: py.test {env:COVERAGE:} {env:NOMIGRATIONS:} {posargs:tests_multitenant/}
multipublik: py.test {env:COVERAGE:} {env:NOMIGRATIONS:} {posargs:tests_multipublik/}
authentic: py.test {env:FAST:} {env:COVERAGE:} {env:NOMIGRATIONS:} {posargs:tests_authentic/}