Skip to content
Snippets Groups Projects
Commit 9338717b authored by Erik Reid's avatar Erik Reid
Browse files

Finished feature classifier-support.

parents 1dd46a24 314224c5
No related branches found
No related tags found
No related merge requests found
......@@ -256,3 +256,17 @@ Any non-empty responses are JSON formatted messages.
This resource updates data that should only be refreshed
in case of system restart.
* /classifier/infinera-dna-addresses, /classifier/juniper-server-addresses
Both of these resources return lists of source addresses
of known senders of snmp traps. Responses will be
formatted as follows:
```json
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "array",
"items": {"type": "string"}
}
```
\ No newline at end of file
......@@ -29,6 +29,9 @@ def create_app():
from inventory_provider.routes import alarmsdb
app.register_blueprint(alarmsdb.routes, url_prefix='/alarmsdb')
from inventory_provider.routes import classifier
app.register_blueprint(classifier.routes, url_prefix='/classifier')
if "SETTINGS_FILENAME" not in os.environ:
assert False, \
"environment variable SETTINGS_FILENAME' must be defined"
......
......@@ -46,6 +46,18 @@ CONFIG_SCHEMA = {
},
"required": ["hostname", "port"],
"additionalProperties": False
},
"infinera-dna": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {"type": "string"},
"address": {"type": "string"}
},
"required": ["name", "address"],
"additionalProperties": False
}
}
},
"required": [
......@@ -54,7 +66,8 @@ CONFIG_SCHEMA = {
"oid_list.conf",
"routers_community.conf",
"ssh",
"redis"],
"redis",
"infinera-dna"],
"additionalProperties": False
}
......
import functools
from flask import Blueprint, request, Response, current_app, jsonify
import json
import jsonschema
from inventory_provider import db
routes = Blueprint("inventory-data-classifier-support-routes", __name__)
def require_accepts_json(f):
"""
used as a route handler decorator to return an error
unless the request allows responses with type "application/json"
:param f: the function to be decorated
:return: the decorated function
"""
@functools.wraps(f)
def decorated_function(*args, **kwargs):
# TODO: use best_match to disallow */* ...?
if not request.accept_mimetypes.accept_json:
return Response(
response="response will be json",
status=406,
mimetype="text/html")
return f(*args, **kwargs)
return decorated_function
@routes.route("/infinera-dna-addresses", methods=['GET', 'POST'])
@require_accepts_json
def infinera_addresses():
infinera_config = current_app.config[
"INVENTORY_PROVIDER_CONFIG"]["infinera-dna"]
return jsonify([dna['address'] for dna in infinera_config])
@routes.route("/juniper-server-addresses", methods=['GET', 'POST'])
@require_accepts_json
def juniper_addresses():
backend_data_schema = {
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "array",
"items": {
"type": "object",
"properties": {
"ip_address": {"type": "string"}
},
"required": ["ip_address"]
}
}
servers = db.get_redis().get('alarmsdb:juniper_servers')
if not servers:
return Response(
response="no juniper server data found",
status=404,
mimetype="text/html")
servers = json.loads(servers.decode('utf-8'))
jsonschema.validate(servers, backend_data_schema)
return jsonify([s['ip_address'] for s in servers])
......@@ -42,7 +42,12 @@ def data_config_filename(tmp_dir_name):
"redis": {
"hostname": "xxxxxx",
"port": 6379
}
},
"infinera-dna": [
{"name": "name1", "address": "123.456.789.0"},
{"name": "name2", "address": "012.345.678.9"},
{"name": "name3", "address": "111.222.333.000"}
]
}
shutil.copyfile(
......
import json
import jsonschema
DEFAULT_REQUEST_HEADERS = {
"Content-type": "application/json",
"Accept": ["application/json"]
}
def test_infinera_addresses(client):
response_schema = {
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "array",
"items": {"type": "string"}
}
rv = client.post(
"/classifier/infinera-dna-addresses",
headers=DEFAULT_REQUEST_HEADERS)
assert rv.status_code == 200
jsonschema.validate(
json.loads(rv.data.decode("utf-8")),
response_schema)
def test_juniper_addresses(mocker, client):
test_data = [
{"ip_address": "a.b.c.d", "project_name": "AAABBB"},
{"ip_address": "b.c.d.e", "project_name": "CCCCDDDDD"},
{"ip_address": "c.d.e.f", "project_name": "EFEFEFEF"},
{"ip_address": "::1", "project_name": "GGHHGGHH"}
]
class MockedRedis():
def __init__(self):
pass
def get(self, ignored):
return json.dumps(test_data).encode('utf-8')
mocker.patch(
'inventory_provider.routes.classifier.db.get_redis',
return_value=MockedRedis())
response_schema = {
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "array",
"items": {"type": "string"}
}
rv = client.post(
"/classifier/juniper-server-addresses",
headers=DEFAULT_REQUEST_HEADERS)
assert rv.status_code == 200
response_data = json.loads(rv.data.decode('utf-8'))
jsonschema.validate(response_data, response_schema)
assert len(response_data) == len(test_data)
assert set([x['ip_address'] for x in test_data]) == set(response_data)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment