diff --git a/inventory_provider/routes/common.py b/inventory_provider/routes/common.py index a025f3a39c23abe26ad28c7d20cd7cc54663889a..046c1831f43ed7269fc270ccfcaad634a9af3447 100644 --- a/inventory_provider/routes/common.py +++ b/inventory_provider/routes/common.py @@ -18,13 +18,18 @@ _DECODE_TYPE_XML = 'xml' _DECODE_TYPE_JSON = 'json' -def _ignore_cache_or_retrieve(request_, cache_key, r): - - ignore_cache = request_.args.get('ignore-cache', default='false', type=str) +def get_bool_request_arg(name, default=False): + assert isinstance(default, bool) # sanity, otherwise caller error + value = request.args.get(name, default=str(default), type=str) try: - ignore_cache = strtobool(ignore_cache) + value = strtobool(value) except ValueError: - ignore_cache = False + value = default + return value + + +def _ignore_cache_or_retrieve(request_, cache_key, r): + ignore_cache = get_bool_request_arg('ignore-cache', default=False) if ignore_cache: result = False logger.debug('ignoring cache') diff --git a/inventory_provider/routes/jobs.py b/inventory_provider/routes/jobs.py index 078e8a56392bd5bb4bb4076d83b6ced585f89e97..95b404a03af8782a902d84059a6dcd5dcdf09d04 100644 --- a/inventory_provider/routes/jobs.py +++ b/inventory_provider/routes/jobs.py @@ -125,15 +125,10 @@ def update(): :return: """ - force = request.args.get('force', default='false', type=str) - try: - force = strtobool(force) - except ValueError: - force = False - config = current_app.config['INVENTORY_PROVIDER_CONFIG'] r = get_current_redis(config) + force = common.get_bool_request_arg('force', default=False) if not force: latch = get_latch(r) if latch and latch['pending']: diff --git a/inventory_provider/routes/poller.py b/inventory_provider/routes/poller.py index 1939e5d4b83e561169b046f2dd10c0d6be0bb2b2..8530f2f704b5c1a9c8f6af3cf52c8d35afa00713 100644 --- a/inventory_provider/routes/poller.py +++ b/inventory_provider/routes/poller.py @@ -237,12 +237,13 @@ SERVICES_LIST_SCHEMA = { 'pop': {'type': 'string'}, 'hostname': {'type': 'string'}, 'interface': {'type': 'string'}, - 'type': {'type': 'string'} + 'type': {'type': 'string'}, + 'status': {'type': 'string'} }, 'required': [ 'id', 'name', 'customer', 'speed', 'pop', 'hostname', - 'interface', 'type'], + 'interface', 'type', 'status'], 'additionalProperties': False } }, @@ -737,6 +738,9 @@ def _get_services_internal(service_type=None): :param service_type: a service type, or None to return all :return: service list, json-serialized to a string """ + + return_all = common.get_bool_request_arg('all', False) + def _services(): key_pattern = f'ims:services:{service_type}:*' \ if service_type else 'ims:services:*' @@ -747,8 +751,8 @@ def _get_services_internal(service_type=None): num_threads=20): yield doc['value'] - def _operational(s): - return s['status'].lower() == 'operational' + def _wanted_in_output(s): + return return_all or (s['status'].lower() == 'operational') def _format_services(s): return { @@ -760,18 +764,22 @@ def _get_services_internal(service_type=None): 'hostname': common.ims_equipment_to_hostname( s['here']['equipment']), 'interface': s['here']['port'], - 'type': s['type'] + 'type': s['type'], + 'status': s['status'] } cache_key = f'classifier-cache:poller:services:{service_type}' \ - if service_type else 'classifier-cache:poller:services:all' + if service_type else 'classifier-cache:poller:services:all-types' + + if return_all: + cache_key = f'{cache_key}:all' redis = common.get_current_redis() result = _ignore_cache_or_retrieve(request, cache_key, redis) if not result: result = _services() - result = filter(_operational, result) + result = filter(_wanted_in_output, result) result = map(_format_services, result) result = list(result) @@ -855,6 +863,10 @@ def get_service_types(): """ cache_key = f'classifier-cache:poller:service-types' + return_all = common.get_bool_request_arg('all', False) + if return_all: + cache_key = f'{cache_key}-all' + redis = common.get_current_redis() service_types = _ignore_cache_or_retrieve(request, cache_key, redis) diff --git a/test/test_general_poller_routes.py b/test/test_general_poller_routes.py index f9359a367183ab093ab47a5e8fdef7280399663b..e867baf3e875a66f43e0e99f195cab246c919625 100644 --- a/test/test_general_poller_routes.py +++ b/test/test_general_poller_routes.py @@ -78,7 +78,7 @@ def test_gws_indirect(client): assert all(s['type'] == 'GWS - INDIRECT' for s in response_data) -def test_all_services(client): +def test_all_services_default(client): rv = client.get( '/poller/services', headers=DEFAULT_REQUEST_HEADERS) @@ -88,6 +88,20 @@ def test_all_services(client): jsonschema.validate(response_data, poller.SERVICES_LIST_SCHEMA) assert response_data # test data is non-empty + assert all(s['status'] == 'operational' for s in response_data) + + +def test_all_services_all(client): + rv = client.get( + '/poller/services?all=1', + headers=DEFAULT_REQUEST_HEADERS) + assert rv.status_code == 200 + assert rv.is_json + response_data = json.loads(rv.data.decode('utf-8')) + jsonschema.validate(response_data, poller.SERVICES_LIST_SCHEMA) + + assert response_data # test data is non-empty + assert any(s['status'] != 'operational' for s in response_data) @pytest.mark.parametrize('uri_type,expected_type', [ @@ -124,4 +138,7 @@ def test_get_service_types(client): jsonschema.validate(response_data, poller.STRING_LIST_SCHEMA) assert response_data # test data is non-empty + # some hard-coded values we expect to see from the test data ... + assert 'gws_indirect' in response_data + assert 'geant_ip' in response_data