Files
monasca-api/api_func_check.py
Ryan Brandt d6b48698ab Add basic functional test
Change-Id: I7b150a31f59ed32765e9a6d0634aceeb9ce1d8b7
2015-06-04 13:27:39 -06:00

698 lines
20 KiB
Python

# Copyright 2015 Hewlett-Packard
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import datetime
import json
import random
import requests
import time
import urllib
from jsonschema import validate
from monascaclient import ksclient
url = "http://192.168.10.4:8080/"
version = "v2.0"
version_url = url + version
keystone = {
'username': 'mini-mon',
'password': 'password',
'project': 'test',
'auth_url': 'http://192.168.10.5:35357/v3'
}
ksclient = ksclient.KSClient(**keystone)
default_headers = {
'X-Auth-User': 'mini-mon',
'X-Auth-Token': ksclient.token,
'X-Auth-Key': 'password',
'Accept': 'application/json',
'User-Agent': 'python-monascaclient',
'Content-Type': 'application/json'}
timestamp_pattern = ("[0-9]{2}-[0-9]{2}-[0-9]{2}T" +
"[0-9]{2}:[0-9]{2}:[0-9]{2}(.[0-9]{0,3})?Z")
list_schema = {
"type": "object",
"properties": {
"links": {
"type": "array",
"items": {
"type": "object",
"properties": {
"rel": {"type": "string"},
"href": {"type": "string"}
},
"required": ["rel", "href"]
},
},
"elements": {
"type": "array",
# "items": None
}
},
"required": ["links", "elements"]
}
version_schema = {
"type": "object",
"properties": {
"id": {"type": "string"},
"links": {
"type": "array",
"items": {
"type": "object",
"properties": {
"rel": {"type": "string"},
"href": {"type": "string"}
},
"required": ["rel", "href"]}
},
"status": {"type": "string"},
"updated": {"updated": "string",
"pattern": timestamp_pattern}
}
}
metric_schema = {
"type": "object",
"properties": {
"id": {"type": "string"},
"name": {"type": "string"},
"dimensions": {"type": "object"}
},
"required": ["id", "name"]
}
metric_name_schema = {
"type": "object",
"properties": {
"id": {"type": "string"},
"name": {"type": "string"}
},
"required": ["name"]
}
measurement_schema = {
"type": "object",
"properties": {
"id": {"type": "string"},
"name": {"type": "string"},
"dimensions": {"type": "object"},
"columns": {
"type": "array",
"items": {"type": "string"}
},
"measurements": {
"type": "array",
"items": {"type": "array"}
}
},
"required": ["id", "name", "measurements"]
}
statistics_schema = {
"type": "object",
"properties": {
"id": {"type": "string"},
"name": {"type": "string"},
"dimensions": {"type": "object"},
"columns": {
"type": "array",
"items": {"type": "string"}
},
"statistics": {
"type": "array",
"items": {"type": "array"}
}
},
"required": ["name", "columns", "statistics"]
}
notification_schema = {
"type": "object",
"properties": {
"id": {"type": "string"},
"links": {
"type": "array",
"items": {
"type": "object",
"properties": {
"rel": {"type": "string"},
"href": {"type": "string"}},
"required": ["rel", "href"]}},
"name": {"type": "string"},
"type": {
"type": "string",
"enum": ["WEBHOOK", "EMAIL", "PAGERDUTY"]},
"address": {"type": "string"}}
}
alarm_definition_schema = {
"type": "object",
"properties": {
"id": {"type": "string"},
"links": {
"type": "array",
"items": {
"type": "object",
"properties": {
"rel": {"type": "string"},
"href": {"type": "string"}},
"required": ["rel", "href"]}},
"name": {"type": "string"},
"description": {"type": ["string", "null"]},
"expression": {"type": "string"},
"match_by": {
"type": "array",
"items": {"type": "string"}},
"severity": {"type": "string"},
"ok_actions": {
"type": ["array", "null"],
"items": {"type": "string"}},
"alarm_actions": {
"type": ["array", "null"],
"items": {"type": "string"}},
"undetermined_actions": {
"type": ["array", "null"],
"items": {"type": "string"}}},
"required": ["id", "links", "name", "description", "expression",
"match_by","severity", "ok_actions", "alarm_actions",
"undetermined_actions"]
}
alarm_history_schema = {
"type": "object",
"properties": {
"id": {"type": ["number", "string"]},
"alarm_id": {"type": "string"},
"metrics": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {"type": ["string", "null"]},
"name": {"type": "string"},
"dimensions": {"type": "object"}}}},
"old_state": {"type": "string",
"enum": ["OK", "ALARM", "UNDETERMINED"]},
"new_state": {"type": "string",
"enum": ["OK", "ALARM", "UNDETERMINED"]},
"reason": {"type": "string"},
"reason_data": {"type": "string"},
"timestamp": {"type": "string",
"pattern": timestamp_pattern},
"sub_alarms": {
"type": ["array", "null"],
"items": {
"type": "object",
"properties": {
"sub_alarm_expression": {
"type": "object",
"properties": {
"function": {"type": "string"},
"metric_name": {"type": "string"},
"dimensions": {"type": "object"},
"operator": {"type": "string"},
"threshold": {"type": "number"},
"period": {"type": "number"},
"periods": {"type": "number"}},
"required": ["function", "metric_name", "dimensions",
"operator", "threshold", "period",
"periods"]},
"sub_alarm_state": {"type": "string",
"enum": ["OK", "ALARM",
"UNDETERMINED"]},
"current_values": {
"type": ["array", "null"],
"items": {"type": "number"}}}}}}
}
alarm_schema = {
"type": "object",
"properties": {
"id": {"type": "string"},
"links": {
"type": "array",
"items": {
"type": "object",
"properties": {
"rel": {"type": "string"},
"href": {"type": "string"}
},
"required": ["rel", "href"]}
},
"alarm_definition": {
"type": "object",
"properties": {
"severity": {"type": "string"},
"id": {"type": "string"},
"links": {
"type": "array",
"items": {
"type": "object",
"properties": {
"rel": {"type": "string"},
"href": {"type": "string"}
},
"required": ["rel", "href"]}
},
"name": {"type": "string"}},
"required": ["severity", "id", "links", "name"]
},
"metrics": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {"type": "string"},
"dimensions": {"type": "object"}
},
"required": ["name"]
}
},
"state": {"type": "string",
"enum": ["OK", "ALARM", "UNDETERMINED"]},
"lifecycle_state": {"type": ["string", "null"]},
"link": {"type": ["string", "null"]},
"state_updated_timestamp": {"type": "string",
"pattern": timestamp_pattern},
"updated_timestamp": {"type": "string",
"pattern": timestamp_pattern},
"created_timestamp": {"type": "string",
"pattern": timestamp_pattern}
},
"required": ["id", "links", "alarm_definition", "metrics", "state",
"lifecycle_state", "link", "state_updated_timestamp",
"updated_timestamp", "created_timestamp"]
}
def do_request(method, rel_url='', body=None, headers=default_headers):
return requests.request(method=method,
url=url+version+rel_url,
data=json.dumps(body),
headers=headers)
def verify_response_code(res, expected):
message = "Invalid response code {}, expected {}\n{}"
assert res.status_code == expected, message.format(res.status_code,
expected,
res.text)
# test version info
def test_version_list():
response = requests.request(method="GET",
url=url,
headers=default_headers)
verify_response_code(response, 200)
json_data = json.loads(response.text)
list_schema['properties']['elements']['items'] = version_schema
validate(json_data, list_schema)
version_list = []
for element in json_data['elements']:
version_list.append(element['id'])
assert version in version_list, "Version '{}' not found".format(version)
def test_version_get():
response = do_request("GET")
verify_response_code(response, 200)
json_data = json.loads(response.text)
validate(json_data, version_schema)
message = "Version '{}' did not match requested version '{}'"
assert json_data['id'] == version, message.format(json_data['id'],
version)
# test metric post and list
def test_metric_post():
body = {
"name": "name1",
"dimensions": {
"key1": "value1",
"key2": "value2"
},
"timestamp": time.time()*1000,
"value": 1.0
}
response = do_request("POST", "/metrics", body)
verify_response_code(response, 204)
def test_metric_post_value_meta():
body = {
"name": "name1",
"dimensions": {
"key1": "value1",
"key2": "value2"},
"timestamp": time.time()*1000,
"value": 1.0,
"value_meta": {
"key1": "value1",
"key2": "value2"
}
}
response = do_request("POST", "/metrics", body)
verify_response_code(response, 204)
def test_metric_post_array():
body = [
{
"name": "name1",
"dimensions": {
"key1": "value1",
"key2": "value2"},
"timestamp": time.time()*1000,
"value": 1.0},
{
"name": "name2",
"dimensions": {
"key1": "value1",
"key2": "value2"},
"timestamp": time.time()*1000,
"value": 2.0,
"value_meta": {
"key1": "value1",
"key2": "value2"}}]
response = do_request("POST", "/metrics", body)
verify_response_code(response, 204)
def test_metric_list():
response = do_request("GET", "/metrics")
verify_response_code(response, 200)
json_data = json.loads(response.text)
list_schema['properties']['elements']['items'] = metric_schema
validate(json_data, list_schema)
def test_metric_name_list():
response = do_request("GET", "/metrics/names")
verify_response_code(response, 200)
json_data = json.loads(response.text)
list_schema['properties']['elements']['items'] = metric_name_schema
validate(json_data, list_schema)
def test_measurement_list():
one_hour_ago = datetime.datetime.utcnow()-datetime.timedelta(hours=1)
one_hour_ago = one_hour_ago - datetime.timedelta(microseconds=
one_hour_ago.microsecond)
query_params = {
"name": "name1",
"start_time": one_hour_ago.isoformat()+'Z',
}
query_str = urllib.urlencode(query_params)
response = do_request("GET", "/metrics/measurements?"+query_str)
verify_response_code(response, 200)
json_data = json.loads(response.text)
list_schema['properties']['elements']['items'] = measurement_schema
validate(json_data, list_schema)
def test_statistics_get():
one_hour_ago = datetime.datetime.utcnow()-datetime.timedelta(minutes=1)
one_hour_ago = one_hour_ago - datetime.timedelta(microseconds=
one_hour_ago.microsecond)
query_params = {
"name": "name1",
"start_time": one_hour_ago.isoformat()+'Z',
"statistics": "count,max,min,avg"
}
query_str = urllib.urlencode(query_params)
response = do_request("GET", "/metrics/statistics?"+query_str)
verify_response_code(response, 200)
json_data = json.loads(response.text)
list_schema['properties']['elements']['items'] = statistics_schema
validate(json_data, list_schema)
def test_notification_CRUD():
# define a random name to reduce chances of collision
notif_name = "Test_api_func_{}".format(random.randint(1, 1000000))
body = {
"name": notif_name,
"type": "WEBHOOK",
"address": "http://somesite.com"
}
response = do_request("POST", "/notification-methods", body)
verify_response_code(response, 201)
json_data = json.loads(response.text)
validate(json_data, notification_schema)
message = "Name was {}, expected {}"
assert json_data['name'] == body['name'], message.format(json_data['name'],
body['name'])
notification_id = json_data['id']
response = do_request("GET", "/notification-methods")
verify_response_code(response, 200)
json_data = json.loads(response.text)
list_schema['properties']['elements']['items'] = notification_schema
validate(json_data, list_schema)
response = do_request("GET", "/notification-methods/"+notification_id)
verify_response_code(response, 200)
json_data = json.loads(response.text)
validate(json_data, notification_schema)
assert json_data['id'] == notification_id
body = {
"name": notif_name,
"type": "EMAIL",
"address": "someone@somewhere.com"
}
response = do_request("PUT", "/notification-methods/"+notification_id,
body)
verify_response_code(response, 200)
json_data = json.loads(response.text)
validate(json_data, notification_schema)
message = "Type was {}, expected {}"
assert json_data['type'] == body['type'], message.format(json_data['type'],
body['type'])
response = do_request("DELETE", "/notification-methods/"+notification_id)
verify_response_code(response, 204)
# test alarm definitions
def test_alarm_definition_CRUD():
# define a random name to reduce chances of collision
def_name = "Test_api_func_{}".format(random.randint(1, 1000000))
# create
body = {
"name": def_name,
"expression": "test_api_function > 0",
"match_by": [
"test-dim"
]
}
response = do_request("POST", "/alarm-definitions", body)
verify_response_code(response, 201)
json_data = json.loads(response.text)
validate(json_data, alarm_definition_schema)
definition_id = json_data['id']
response = do_request("GET", "/alarm-definitions")
verify_response_code(response, 200)
json_data = json.loads(response.text)
list_schema['properties']['elements']['items'] = alarm_definition_schema
validate(json_data, list_schema)
# list
response = do_request("GET", "/alarm-definitions/"+definition_id)
verify_response_code(response, 200)
json_data = json.loads(response.text)
validate(json_data, alarm_definition_schema)
# update
body = {
"name": def_name,
"expression": "test_api_function > 0",
"match_by": [
"test-dim"
],
"actions_enabled": True
}
response = do_request("PUT", "/alarm-definitions/"+definition_id, body)
verify_response_code(response, 200)
json_data = json.loads(response.text)
validate(json_data, alarm_definition_schema)
# patch
body = {
"name": def_name,
"severity": "HIGH"
}
response = do_request("PATCH", "/alarm-definitions/"+definition_id, body)
verify_response_code(response, 200)
json_data = json.loads(response.text)
validate(json_data, alarm_definition_schema)
# delete
response = do_request("DELETE", "/alarm-definitions/"+definition_id)
verify_response_code(response, 204)
def test_alarm_state_history_list():
response = do_request("GET", "/alarms/state-history")
verify_response_code(response, 200)
json_data = json.loads(response.text)
list_schema['properties']['elements']['items'] = alarm_history_schema
validate(json_data, list_schema)
def test_alarm_list_get_update_delete():
# alarm list
response = do_request("GET", "/alarms")
verify_response_code(response, 200)
json_data = json.loads(response.text)
list_schema['properties']['elements']['items'] = alarm_schema
validate(json_data, list_schema)
alarm_id = json_data['elements'][0]['id']
# alarm update
body = {
"state": "ALARM",
"lifecycle_state": "open",
"link": "http://somesite.com"
}
response = do_request("PUT", "/alarms/"+alarm_id, body)
verify_response_code(response, 200)
response = do_request("GET", "/alarms/"+alarm_id)
verify_response_code(response, 200)
json_data = json.loads(response.text)
validate(json_data, alarm_schema)
assert json_data['state'] == "ALARM"
assert json_data['lifecycle_state'] == "open"
assert json_data['link'] == "http://somesite.com"
# alarm patch
body = {
"state": "OK",
"lifecycle_state": "closed"
}
response = do_request("PATCH", "/alarms/"+alarm_id, body)
verify_response_code(response, 200)
json_data = json.loads(response.text)
validate(json_data, alarm_schema)
assert json_data['lifecycle_state'] == "closed"
response = do_request("GET", "/alarms/"+alarm_id)
verify_response_code(response, 200)
json_data = json.loads(response.text)
validate(json_data, alarm_schema)
assert json_data['lifecycle_state'] == "closed"
assert json_data['link'] == "http://somesite.com"
# alarm delete
response = do_request("DELETE", "/alarms/"+alarm_id)
verify_response_code(response, 204)
response = do_request("GET", "/alarms/"+alarm_id)
verify_response_code(response, 404)
def main():
test_version_list()
test_version_get()
test_notification_CRUD()
test_metric_post()
test_metric_post_array()
test_metric_post_value_meta()
test_metric_list()
test_metric_name_list()
test_measurement_list()
test_statistics_get()
test_alarm_definition_CRUD()
test_alarm_state_history_list()
test_alarm_list_get_update_delete()
print("pass")
if __name__ == "__main__":
main()