[cli][tests] Changed the routes names and wrote the tests according to current configuration
This commit is contained in:
parent
ad1304f8d4
commit
c4872ec0b3
|
@ -11,11 +11,6 @@ def cli(ctx, version):
|
|||
import halfapi
|
||||
return click.echo(halfapi.version)
|
||||
|
||||
#if not IS_PROJECT:
|
||||
# return init()
|
||||
#if ctx.invoked_subcommand is None:
|
||||
# return run()
|
||||
|
||||
if IS_PROJECT:
|
||||
import halfapi.cli.domain
|
||||
import halfapi.cli.run
|
||||
|
|
|
@ -15,48 +15,15 @@ from halfapi.db import (
|
|||
|
||||
logger = logging.getLogger('halfapi')
|
||||
|
||||
#################
|
||||
# domain create #
|
||||
#################
|
||||
def create_domain(name):
|
||||
pass
|
||||
|
||||
def delete_domain(domain):
|
||||
d = Domain(name=domain)
|
||||
if len(d) != 1:
|
||||
return False
|
||||
|
||||
d.delete(delete_all=True)
|
||||
return True
|
||||
|
||||
|
||||
@click.option('--domain', '-d', default=None, multiple=True)
|
||||
@click.option('--update', default=False, is_flag=True)
|
||||
@cli.command()
|
||||
def domain(domain, update):
|
||||
"""
|
||||
Lists routes for the specified domains, or update them in the database
|
||||
|
||||
Parameters:
|
||||
domain (List[str]|None): The list of the domains to list/update
|
||||
|
||||
The parameter has a misleading name as it is a multiple option
|
||||
but this would be strange to use it several times named as "domains"
|
||||
|
||||
update (boolean): If set, update the database for the selected domains
|
||||
"""
|
||||
|
||||
if not domain:
|
||||
domain = DOMAINS
|
||||
else:
|
||||
for domain_name in domain:
|
||||
if domain_name in DOMAINS:
|
||||
continue
|
||||
click.echo(
|
||||
f'Domain {domain}s is not activated in the configuration')
|
||||
|
||||
if update:
|
||||
update_db(domain)
|
||||
else:
|
||||
for domain_name in domain:
|
||||
list_routes(domain)
|
||||
|
||||
|
||||
###############
|
||||
# domain read #
|
||||
###############
|
||||
def list_routes(domain):
|
||||
click.echo(f'\nDomain : {domain}')
|
||||
routers = APIRouter(domain=domain)
|
||||
|
@ -69,7 +36,9 @@ def list_routes(domain):
|
|||
route['acls'] = acls
|
||||
click.echo('- [{http_verb}] {path} ({acls})'.format(**route))
|
||||
|
||||
|
||||
#################
|
||||
# domain update #
|
||||
#################
|
||||
def update_db(domains):
|
||||
|
||||
def add_domain(domain):
|
||||
|
@ -279,3 +248,63 @@ def update_db(domains):
|
|||
# @TODO : Insertion exception handling
|
||||
print(e)
|
||||
continue
|
||||
|
||||
|
||||
#################
|
||||
# domain delete #
|
||||
#################
|
||||
def delete_domain(domain):
|
||||
d = Domain(name=domain)
|
||||
if len(d) != 1:
|
||||
return False
|
||||
|
||||
d.delete(delete_all=True)
|
||||
return True
|
||||
|
||||
|
||||
@click.option('--read',default=False, is_flag=True)
|
||||
@click.option('--create',default=False, is_flag=True)
|
||||
@click.option('--update',default=False, is_flag=True)
|
||||
@click.option('--delete',default=False, is_flag=True)
|
||||
@click.option('--domains',default=None)
|
||||
@cli.command()
|
||||
def domain(domains, delete, update, create, read): #, domains, read, create, update, delete):
|
||||
"""
|
||||
Lists routes for the specified domains, or update them in the database
|
||||
|
||||
Parameters:
|
||||
domain (List[str]|None): The list of the domains to list/update
|
||||
|
||||
The parameter has a misleading name as it is a multiple option
|
||||
but this would be strange to use it several times named as "domains"
|
||||
|
||||
update (boolean): If set, update the database for the selected domains
|
||||
"""
|
||||
|
||||
if not domains:
|
||||
if create:
|
||||
return create_domain()
|
||||
|
||||
domains = DOMAINS
|
||||
else:
|
||||
domains_ = []
|
||||
for domain_name in domains.split(','):
|
||||
if domain_name in DOMAINS:
|
||||
domains.append(domain_name)
|
||||
continue
|
||||
|
||||
click.echo(
|
||||
f'Domain {domain_name}s is not activated in the configuration')
|
||||
|
||||
domains = domains_
|
||||
|
||||
update = False
|
||||
for domain in domains:
|
||||
if update:
|
||||
update_db(domain)
|
||||
if delete:
|
||||
delete_domain(domain)
|
||||
else:
|
||||
list_routes(domain)
|
||||
|
||||
|
||||
|
|
|
@ -12,9 +12,8 @@ from .cli import cli
|
|||
|
||||
logger = logging.getLogger('halfapi')
|
||||
|
||||
TMPL_HALFAPI_ETC = """Insert this into the HALFAPI_CONF_DIR/{project} file
|
||||
|
||||
[project]
|
||||
TMPL_HALFAPI_ETC = """[project]
|
||||
name = {project}
|
||||
host = 127.0.0.1
|
||||
port = 8000
|
||||
secret = /path/to/secret_file
|
||||
|
@ -22,6 +21,12 @@ production = False
|
|||
base_dir = {base_dir}
|
||||
"""
|
||||
|
||||
def format_halfapi_etc(project, path):
|
||||
return TMPL_HALFAPI_ETC.format(
|
||||
project=project,
|
||||
base_dir=path
|
||||
)
|
||||
|
||||
TMPL_HALFAPI_CONFIG = """[project]
|
||||
name = {name}
|
||||
halfapi_version = {halfapi_version}
|
||||
|
@ -59,8 +64,8 @@ def init(project):
|
|||
halfapi_version=__version__
|
||||
))
|
||||
|
||||
print(TMPL_HALFAPI_ETC.format(
|
||||
project=project,
|
||||
base_dir=os.path.abspath(project)
|
||||
))
|
||||
click.echo(f'Insert this into the HALFAPI_CONF_DIR/{project} file')
|
||||
click.echo(format_halfapi_etc(
|
||||
project,
|
||||
os.path.abspath(project)))
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ from configparser import ConfigParser
|
|||
IS_PROJECT = os.path.isfile('.halfapi/config')
|
||||
|
||||
if IS_PROJECT:
|
||||
|
||||
default_config = {
|
||||
'project': {
|
||||
'host': '127.0.0.1',
|
||||
|
@ -35,17 +36,25 @@ if IS_PROJECT:
|
|||
|
||||
CONF_DIR = environ.get('HALFAPI_CONF_DIR', '/etc/half_api')
|
||||
|
||||
config.read(filenames=[os.path.join(
|
||||
HALFAPI_CONF_FILE=os.path.join(
|
||||
CONF_DIR,
|
||||
PROJECT_NAME
|
||||
)])
|
||||
)
|
||||
if not os.path.isfile(HALFAPI_CONF_FILE):
|
||||
print(f'Missing {HALFAPI_CONF_FILE}, exiting')
|
||||
sys.exit(1)
|
||||
config.read(filenames=[HALFAPI_CONF_FILE])
|
||||
|
||||
HOST = config.get('project', 'host')
|
||||
PORT = config.getint('project', 'port')
|
||||
DB_NAME = f'halfapi_{PROJECT_NAME}'
|
||||
|
||||
try:
|
||||
with open(config.get('project', 'secret')) as secret_file:
|
||||
SECRET = secret_file.read()
|
||||
except FileNotFoundError:
|
||||
print('There is no file like {}'.format(config.get('project', 'secret')))
|
||||
sys.exit(1)
|
||||
|
||||
PRODUCTION = config.getboolean('project', 'production')
|
||||
BASE_DIR = config.get('project', 'base_dir')
|
||||
|
|
|
@ -1,7 +1,57 @@
|
|||
# content of conftest.py
|
||||
|
||||
#!/usr/bin/env python3
|
||||
import re
|
||||
import os
|
||||
import subprocess
|
||||
import importlib
|
||||
import tempfile
|
||||
from unittest.mock import patch
|
||||
from typing import Dict, Tuple
|
||||
import pytest
|
||||
from uuid import uuid1
|
||||
from click.testing import CliRunner
|
||||
from halfapi import __version__
|
||||
from halfapi.cli import cli
|
||||
from halfapi.cli.init import format_halfapi_etc
|
||||
Cli = cli.cli
|
||||
|
||||
PROJNAME = os.environ.get('PROJ','tmp_api')
|
||||
|
||||
@pytest.fixture
|
||||
def runner():
|
||||
return CliRunner()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def dropdb():
|
||||
p = subprocess.Popen(['dropdb', f'halfapi_{PROJNAME}'])
|
||||
p.wait()
|
||||
yield
|
||||
|
||||
p = subprocess.Popen(['dropdb', f'halfapi_{PROJNAME}'])
|
||||
p.wait()
|
||||
|
||||
@pytest.fixture
|
||||
def createdb():
|
||||
p = subprocess.Popen(['createdb', f'halfapi_{PROJNAME}'])
|
||||
p.wait()
|
||||
return
|
||||
|
||||
def confdir(dirname):
|
||||
d = os.environ.get(dirname)
|
||||
if not d:
|
||||
os.environ[dirname] = tempfile.mkdtemp(prefix='halfapi_')
|
||||
return os.environ.get(dirname)
|
||||
if not os.path.isdir(d):
|
||||
os.mkdir(d)
|
||||
return d
|
||||
|
||||
@pytest.fixture
|
||||
def halform_conf_dir():
|
||||
return confdir('HALFORM_CONF_DIR')
|
||||
|
||||
@pytest.fixture
|
||||
def halfapi_conf_dir():
|
||||
return confdir('HALFAPI_CONF_DIR')
|
||||
|
||||
# store history of failures per test class name and per index in parametrize (if
|
||||
# parametrize used)
|
||||
|
@ -51,3 +101,28 @@ def pytest_runtest_setup(item):
|
|||
# test name
|
||||
if test_name is not None:
|
||||
pytest.xfail("previous test failed ({})".format(test_name))
|
||||
|
||||
@pytest.fixture
|
||||
def project_runner(runner, dropdb, createdb, halform_conf_dir, halfapi_conf_dir):
|
||||
env = {
|
||||
'HALFORM_CONF_DIR': halform_conf_dir,
|
||||
'HALFAPI_CONF_DIR': halfapi_conf_dir
|
||||
}
|
||||
with runner.isolated_filesystem():
|
||||
res = runner.invoke(Cli, ['init', PROJNAME],
|
||||
env=env,
|
||||
catch_exceptions=True)
|
||||
assert res.exit_code == 0
|
||||
|
||||
os.chdir(PROJNAME)
|
||||
secret = tempfile.mkstemp()
|
||||
SECRET_PATH = secret[1]
|
||||
with open(SECRET_PATH, 'w') as f:
|
||||
f.write(str(uuid1()))
|
||||
|
||||
with open(os.path.join(halfapi_conf_dir, PROJNAME), 'w') as f:
|
||||
PROJ_CONFIG = re.sub('secret = .*', f'secret = {SECRET_PATH}',
|
||||
format_halfapi_etc(PROJNAME, os.getcwd()))
|
||||
f.write(PROJ_CONFIG)
|
||||
|
||||
yield lambda args: runner.invoke(Cli, args, env=env)
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
import os
|
||||
import subprocess
|
||||
import importlib
|
||||
import tempfile
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
from click.testing import CliRunner
|
||||
|
@ -13,26 +15,6 @@ Cli = cli.cli
|
|||
|
||||
PROJNAME = os.environ.get('PROJ','tmp_api')
|
||||
|
||||
@pytest.fixture
|
||||
def runner():
|
||||
return CliRunner()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def dropdb():
|
||||
p = subprocess.Popen(['dropdb', f'halfapi_{PROJNAME}'])
|
||||
p.wait()
|
||||
yield
|
||||
|
||||
p = subprocess.Popen(['dropdb', f'halfapi_{PROJNAME}'])
|
||||
p.wait()
|
||||
|
||||
@pytest.fixture
|
||||
def createdb():
|
||||
p = subprocess.Popen(['createdb', f'halfapi_{PROJNAME}'])
|
||||
p.wait()
|
||||
return
|
||||
|
||||
|
||||
@pytest.mark.incremental
|
||||
class TestCli():
|
||||
|
@ -79,12 +61,12 @@ class TestCli():
|
|||
r = runner.invoke(Cli, ['init', testproject])
|
||||
assert r.exit_code == 1
|
||||
|
||||
def test_init_project(self, runner, dropdb, createdb):
|
||||
def test_init_project(self, runner, dropdb, createdb, halform_conf_dir, halfapi_conf_dir):
|
||||
cp = ConfigParser()
|
||||
with runner.isolated_filesystem():
|
||||
env = {
|
||||
'HALFORM_CONF_DIR': os.environ.get('HALFORM_CONF_DIR', os.getcwd()),
|
||||
'HALFAPI_CONF_DIR': os.environ.get('HALFAPI_CONF_DIR', os.getcwd()),
|
||||
'HALFORM_CONF_DIR': halform_conf_dir,
|
||||
'HALFAPI_CONF_DIR': halfapi_conf_dir
|
||||
}
|
||||
|
||||
res = runner.invoke(Cli, ['init', PROJNAME], env=env)
|
||||
|
@ -105,96 +87,10 @@ class TestCli():
|
|||
assert os.path.isfile(os.path.join(PROJNAME, '.halfapi', 'domains'))
|
||||
cp.read(os.path.join(PROJNAME, '.halfapi', 'domains'))
|
||||
assert cp.has_section('domains')
|
||||
except AssertionError:
|
||||
except AssertionError as e:
|
||||
subprocess.run(['tree', '-a', os.getcwd()])
|
||||
raise e
|
||||
|
||||
assert res.exit_code == 0
|
||||
assert res.exception is None
|
||||
|
||||
def test_run_commands(self, runner, dropdb, createdb):
|
||||
def reloadcli():
|
||||
importlib.reload(cli)
|
||||
return cli.cli
|
||||
|
||||
with runner.isolated_filesystem():
|
||||
res = runner.invoke(Cli, ['init', PROJNAME])
|
||||
assert res.exit_code == 0
|
||||
os.chdir(PROJNAME)
|
||||
Cli2 = reloadcli()
|
||||
res = runner.invoke(Cli2, ['run', '--help'])
|
||||
assert res.exception is None
|
||||
assert res.exit_code == 0
|
||||
|
||||
with runner.isolated_filesystem():
|
||||
res = runner.invoke(Cli, ['init', PROJNAME])
|
||||
os.chdir(PROJNAME)
|
||||
res = runner.invoke(Cli, ['run', 'foobar'])
|
||||
assert res.exit_code == 2
|
||||
|
||||
|
||||
def test_domain_commands(self, runner, dropdb, createdb):
|
||||
with runner.isolated_filesystem():
|
||||
res = runner.invoke(Cli, ['init', PROJNAME])
|
||||
os.chdir(PROJNAME)
|
||||
res = runner.invoke(Cli, ['domain', 'foobar'])
|
||||
assert res.exit_code == 2
|
||||
|
||||
with runner.isolated_filesystem():
|
||||
res = runner.invoke(Cli, ['init', PROJNAME])
|
||||
os.chdir(PROJNAME)
|
||||
res = runner.invoke(Cli, ['domain', '--help'])
|
||||
assert r.exit_code == 0
|
||||
|
||||
with runner.isolated_filesystem():
|
||||
res = runner.invoke(Cli, ['init', PROJNAME])
|
||||
os.chdir(PROJNAME)
|
||||
res = runner.invoke(Cli, ['domain', 'create', '--help'])
|
||||
assert r.exit_code == 0
|
||||
|
||||
with runner.isolated_filesystem():
|
||||
res = runner.invoke(Cli, ['init', PROJNAME])
|
||||
os.chdir(PROJNAME)
|
||||
res = runner.invoke(Cli, ['domain', 'read', '--help'])
|
||||
assert r.exit_code == 0
|
||||
|
||||
with runner.isolated_filesystem():
|
||||
res = runner.invoke(Cli, ['init', PROJNAME])
|
||||
os.chdir(PROJNAME)
|
||||
res = runner.invoke(Cli, ['domain', 'update', '--help'])
|
||||
assert r.exit_code == 0
|
||||
|
||||
with runner.isolated_filesystem():
|
||||
res = runner.invoke(Cli, ['init', PROJNAME])
|
||||
os.chdir(PROJNAME)
|
||||
res = runner.invoke(Cli, ['domain', 'delete', '--help'])
|
||||
assert r.exit_code == 0
|
||||
|
||||
def test_domain_create(self, runner, dropdb):
|
||||
with runner.isolated_filesystem():
|
||||
res = runner.invoke(Cli, ['init', PROJNAME])
|
||||
assert res.exit_code == 0
|
||||
|
||||
os.chdir(PROJNAME)
|
||||
|
||||
DOMNAME='tmp_domain'
|
||||
res = runner.invoke(Cli, ['domain', 'create', DOMNAME])
|
||||
srcdir = os.path.join('domains', 'src', DOMNAME)
|
||||
assert os.path.isdir(srcdir)
|
||||
moddir = os.path.join(srcdir, DOMNAME)
|
||||
assert os.path.isdir(moddir)
|
||||
setup = os.path.join(srcdir, 'setup.py')
|
||||
assert os.path.isfile(setup)
|
||||
initfile = os.path.join(moddir, '__init__.py')
|
||||
assert os.path.isfile(initfile)
|
||||
aclfile = os.path.join(moddir, 'acl.py')
|
||||
assert os.path.isfile(aclfile)
|
||||
aclsdir = os.path.join(moddir, 'acls')
|
||||
assert os.path.isdir(aclsdir)
|
||||
routersdir = os.path.join(moddir, 'routers')
|
||||
assert os.path.isdir(routersdir)
|
||||
|
||||
try:
|
||||
dom_mod = importlib.import_module(DOMNAME, srcdir)
|
||||
assert hasattr(dom_mod, 'ROUTERS')
|
||||
except ImportError:
|
||||
assert False
|
||||
|
|
Loading…
Reference in New Issue