Commit 4cb908ac authored by Markus Scheidgen's avatar Markus Scheidgen
Browse files

operation

Fixes to bravado client. Separation of admin commands into api resources. Minor backend changes.
parent ff82d7e5
Pipeline #41899 failed with stages
in 15 minutes and 10 seconds
......@@ -24,40 +24,49 @@ from .auth import login_really_required
ns = api.namespace('admin', description='Administrative operations')
@ns.route('/<string:operation>')
@api.doc(params={'operation': 'The operation to perform.'})
class AdminOperationsResource(Resource):
@api.doc('exec_admin_command')
@api.response(200, 'Operation performed')
@api.response(404, 'Operation does not exist')
@api.response(400, 'Operation not available/disabled')
@ns.route('/reset')
class AdminRemoveResource(Resource):
@api.doc('exec_reset_command')
@api.response(200, 'Reset performed')
@api.response(400, 'Reset not available/disabled')
@login_really_required
def post(self, operation):
def post(self):
"""
Allows to perform administrative operations on the nomad services.
The possible operations are ``reset`` and ``remove``.
The ``reset`` operation will attempt to clear the contents of all databased and
indices.
Nomad can be configured to disable reset and the operation might not be available.
"""
if not g.user.is_admin:
abort(401, message='Only the admin user can perform reset.')
if config.services.disable_reset:
abort(400, message='Operation is disabled')
infrastructure.reset()
return dict(messager='Reset performed.'), 200
@ns.route('/remove')
class AdminResetResource(Resource):
@api.doc('exec_remove_command')
@api.response(200, 'Remove performed')
@api.response(400, 'Remove not available/disabled')
@login_really_required
def post(self):
"""
The ``remove``operation will attempt to remove all databases. Expect the
api to stop functioning after this request.
Reset and remove can be disabled.
Nomad can be configured to disable remove and the operation might not be available.
"""
if not g.user.is_admin:
abort(401, message='Only the admin user can perform this operation.')
if operation == 'reset':
if config.services.disable_reset:
abort(400, message='Operation is disabled')
infrastructure.reset()
elif operation == 'remove':
if config.services.disable_reset:
abort(400, message='Operation is disabled')
infrastructure.remove()
else:
abort(404, message='Unknown operation %s' % operation)
return dict(messager='Operation %s performed.' % operation), 200
abort(401, message='Only the admin user can perform remove.')
if config.services.disable_reset:
abort(400, message='Operation is disabled')
infrastructure.remove()
return dict(messager='Remove performed.'), 200
......@@ -61,7 +61,7 @@ api = Api(
@app.errorhandler(Exception)
@api.errorhandler(Exception)
@api.errorhandler
def handle(error: Exception):
status_code = getattr(error, 'code', 500)
name = getattr(error, 'name', 'Internal Server Error')
......
......@@ -49,11 +49,9 @@ def create_client(
user: str = user, password: str = pw):
""" A factory method to create the client. """
http_client = RequestsClient()
if user is not None:
http_client = RequestsClient()
http_client.set_basic_auth(host, user, pw)
else:
http_client = None
client = SwaggerClient.from_url(
'http://%s:%d%s/swagger.json' % (host, port, base_path),
......@@ -299,7 +297,7 @@ def upload(path, name: str, offline: bool, unstage: bool):
@cli.command(help='Attempts to reset the nomad.')
def reset():
_cli_client().admin.exec_admin_command(operation='reset').reponse()
_cli_client().admin.exec_reset_command().response()
@cli.command(help='Run processing locally.')
......
......@@ -458,17 +458,19 @@ class LocalBackend(LegacyParserBackend):
sections = self._delegate.results[meta_name]
return [section.gIndex for section in sections]
@staticmethod
def _write(
json_writer: JSONStreamWriter,
value: Any,
self, json_writer: JSONStreamWriter, value: Any,
filter: Callable[[str, Any], Any] = None):
if isinstance(value, list):
json_writer.open_array()
for item in value:
LocalBackend._write(json_writer, item, filter=filter)
json_writer.close_array()
if len(value) == 1 and isinstance(value[0], Section) and \
not self._delegate.metaInfoEnv().infoKindEl(value[0].name).repeats:
self._write(json_writer, value[0], filter=filter)
else:
json_writer.open_array()
for item in value:
self._write(json_writer, item, filter=filter)
json_writer.close_array()
elif isinstance(value, Section):
section = value
......@@ -482,7 +484,7 @@ class LocalBackend(LegacyParserBackend):
if value is not None:
json_writer.key(name)
LocalBackend._write(json_writer, value, filter=filter)
self._write(json_writer, value, filter=filter)
json_writer.close_object()
......@@ -491,10 +493,11 @@ class LocalBackend(LegacyParserBackend):
def _obj(self, value: Any, filter: Callable[[str, Any], Any] = None) -> Any:
if isinstance(value, list):
if len(value) == 1 and isinstance(value[0], Section) and not self._delegate.metaInfoEnv().infoKindEl(value[0].name).repeats:
return self._obj(value[0])
if len(value) == 1 and isinstance(value[0], Section) and \
not self._delegate.metaInfoEnv().infoKindEl(value[0].name).repeats:
return self._obj(value[0], filter=filter)
else:
return [self._obj(item) for item in value]
return [self._obj(item, filter=filter) for item in value]
elif isinstance(value, Section):
section = value
......@@ -543,10 +546,7 @@ class LocalBackend(LegacyParserBackend):
# TODO the root sections should be determined programatically
for root_section in ['section_run', 'section_calculation_info', 'section_repository_info']:
json_writer.key(root_section)
json_writer.open_array()
for section in self._delegate.results[root_section]:
LocalBackend._write(json_writer, section, filter=filter)
json_writer.close_array()
self._write(json_writer, self._delegate.results[root_section], filter=filter)
json_writer.close_object()
json_writer.close()
......
......@@ -98,7 +98,7 @@ class TestAdmin:
assert rv.status_code == 404
def test_only_admin(self, client, test_user_auth):
rv = client.post('/admin/doesnotexist', headers=test_user_auth)
rv = client.post('/admin/reset', headers=test_user_auth)
assert rv.status_code == 401
@pytest.fixture(scope='function')
......
Supports Markdown
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