mirror of
https://github.com/alerta/alerta.git
synced 2025-03-13 04:53:16 +00:00
Add auditing info to blackout model (#609)
* Add auditing info to blackout model * Add tests for extended blackout info
This commit is contained in:
parent
e0bce26a58
commit
d358fdf025
9 changed files with 91 additions and 23 deletions
|
@ -23,7 +23,7 @@ last to support Python 2.7. Only critical bug fixes will be backported to Releas
|
|||
|
||||
The only mandatory dependency is MongoDB or PostgreSQL. Everything else is optional.
|
||||
|
||||
- Postgres version 9.6 or better
|
||||
- Postgres version 9.5 or better
|
||||
- MongoDB version 3.x
|
||||
|
||||
Installation
|
||||
|
|
|
@ -20,22 +20,15 @@ class Backend(Database):
|
|||
self.uri = uri
|
||||
self.dbname = dbname
|
||||
|
||||
db = self.connect()
|
||||
self._create_indexes(db)
|
||||
|
||||
def connect(self):
|
||||
self.client = MongoClient(self.uri)
|
||||
if self.dbname:
|
||||
db = self.client[self.dbname]
|
||||
return self.client[self.dbname]
|
||||
else:
|
||||
db = self.client.get_default_database()
|
||||
|
||||
# create unique indexes
|
||||
try:
|
||||
self._create_indexes(db)
|
||||
except Exception as e:
|
||||
if current_app.config['MONGO_RAISE_ON_ERROR']:
|
||||
raise
|
||||
current_app.logger.warning(e)
|
||||
|
||||
return db
|
||||
return self.client.get_default_database()
|
||||
|
||||
@staticmethod
|
||||
def _create_indexes(db):
|
||||
|
@ -709,7 +702,10 @@ class Backend(Database):
|
|||
"environment": blackout.environment,
|
||||
"startTime": blackout.start_time,
|
||||
"endTime": blackout.end_time,
|
||||
"duration": blackout.duration
|
||||
"duration": blackout.duration,
|
||||
"user": blackout.user,
|
||||
"createTime": blackout.create_time,
|
||||
"text": blackout.text,
|
||||
}
|
||||
if blackout.service:
|
||||
data["service"] = blackout.service
|
||||
|
|
|
@ -501,8 +501,10 @@ class Backend(Database):
|
|||
|
||||
def create_blackout(self, blackout):
|
||||
insert = """
|
||||
INSERT INTO blackouts (id, priority, environment, service, resource, event, "group", tags, customer, start_time, end_time, duration)
|
||||
VALUES (%(id)s, %(priority)s, %(environment)s, %(service)s, %(resource)s, %(event)s, %(group)s, %(tags)s, %(customer)s, %(start_time)s, %(end_time)s, %(duration)s)
|
||||
INSERT INTO blackouts (id, priority, environment, service, resource, event, "group", tags,
|
||||
customer, start_time, end_time, duration, "user", create_time, text)
|
||||
VALUES (%(id)s, %(priority)s, %(environment)s, %(service)s, %(resource)s, %(event)s, %(group)s, %(tags)s,
|
||||
%(customer)s, %(start_time)s, %(end_time)s, %(duration)s, %(user)s, %(create_time)s, %(text)s)
|
||||
RETURNING *
|
||||
"""
|
||||
return self._insert(insert, vars(blackout))
|
||||
|
|
|
@ -43,7 +43,12 @@ class Database(Base):
|
|||
cls = load_backend(backend)
|
||||
self.__class__ = type('DatabaseImpl', (cls.Backend, Database), {})
|
||||
|
||||
self.create_engine(app, uri=app.config['DATABASE_URL'], dbname=app.config['DATABASE_NAME'])
|
||||
try:
|
||||
self.create_engine(app, uri=app.config['DATABASE_URL'], dbname=app.config['DATABASE_NAME'])
|
||||
except Exception as e:
|
||||
if app.config['DATABASE_RAISE_ON_ERROR']:
|
||||
raise
|
||||
app.logger.warning(e)
|
||||
|
||||
app.before_request(self.get_db)
|
||||
app.teardown_request(self.teardown_db)
|
||||
|
|
|
@ -35,6 +35,10 @@ class Blackout(object):
|
|||
self.end_time = end_time
|
||||
self.duration = duration
|
||||
|
||||
self.user = kwargs.get('user', None)
|
||||
self.create_time = kwargs['create_time'] if 'create_time' in kwargs else datetime.utcnow()
|
||||
self.text = kwargs.get('text', None)
|
||||
|
||||
if self.environment:
|
||||
self.priority = 1
|
||||
if self.resource and not self.event:
|
||||
|
@ -78,7 +82,9 @@ class Blackout(object):
|
|||
customer=json.get('customer', None),
|
||||
start_time=DateTime.parse(json.get('startTime')),
|
||||
end_time=DateTime.parse(json.get('endTime')),
|
||||
duration=json.get('duration', None)
|
||||
duration=json.get('duration', None),
|
||||
user=json.get('user', None),
|
||||
text=json.get('text', None)
|
||||
)
|
||||
|
||||
@property
|
||||
|
@ -98,7 +104,10 @@ class Blackout(object):
|
|||
'endTime': self.end_time,
|
||||
'duration': self.duration,
|
||||
'status': self.status,
|
||||
'remaining': self.remaining
|
||||
'remaining': self.remaining,
|
||||
'user': self.user,
|
||||
'createTime': self.create_time,
|
||||
'text': self.text
|
||||
}
|
||||
|
||||
def __repr__(self):
|
||||
|
@ -141,7 +150,10 @@ class Blackout(object):
|
|||
customer=doc.get('customer', None),
|
||||
start_time=doc.get('startTime', None),
|
||||
end_time=doc.get('endTime', None),
|
||||
duration=doc.get('duration', None)
|
||||
duration=doc.get('duration', None),
|
||||
user=doc.get('user', None),
|
||||
create_time=doc.get('createTime', None),
|
||||
text=doc.get('text', None)
|
||||
)
|
||||
|
||||
@classmethod
|
||||
|
@ -158,7 +170,10 @@ class Blackout(object):
|
|||
customer=rec.customer,
|
||||
start_time=rec.start_time,
|
||||
end_time=rec.end_time,
|
||||
duration=rec.duration
|
||||
duration=rec.duration,
|
||||
user=rec.user,
|
||||
create_time=rec.create_time,
|
||||
text=rec.text
|
||||
)
|
||||
|
||||
@classmethod
|
||||
|
|
|
@ -35,6 +35,7 @@ POSTGRES_DB = None
|
|||
|
||||
DATABASE_URL = MONGO_URI # default: MongoDB
|
||||
DATABASE_NAME = MONGO_DATABASE or POSTGRES_DB
|
||||
DATABASE_RAISE_ON_ERROR = MONGO_RAISE_ON_ERROR # True - terminate, False - ignore and continue
|
||||
|
||||
AUTH_REQUIRED = False
|
||||
ADMIN_USERS = [] # type: List[str]
|
||||
|
|
|
@ -62,6 +62,33 @@ CREATE TABLE IF NOT EXISTS blackouts (
|
|||
duration integer
|
||||
);
|
||||
|
||||
-- Support for "IF NOT EXISTS" added to "ADD COLUMN" in Postgres 9.6
|
||||
-- ALTER TABLE blackouts
|
||||
-- ADD COLUMN IF NOT EXISTS "user" text,
|
||||
-- ADD COLUMN IF NOT EXISTS create_time timestamp without time zone,
|
||||
-- ADD COLUMN IF NOT EXISTS text text;
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
ALTER TABLE blackouts ADD COLUMN "user" text;
|
||||
EXCEPTION
|
||||
WHEN duplicate_column THEN RAISE NOTICE 'column "user" already exists in blackouts.';
|
||||
END$$;
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
ALTER TABLE blackouts ADD COLUMN create_time timestamp without time zone;
|
||||
EXCEPTION
|
||||
WHEN duplicate_column THEN RAISE NOTICE 'column create_time already exists in blackouts.';
|
||||
END$$;
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
ALTER TABLE blackouts ADD COLUMN text text;
|
||||
EXCEPTION
|
||||
WHEN duplicate_column THEN RAISE NOTICE 'column text already exists in blackouts.';
|
||||
END$$;
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS customers (
|
||||
id text PRIMARY KEY,
|
||||
|
|
|
@ -20,6 +20,11 @@ def create_blackout():
|
|||
except Exception as e:
|
||||
raise ApiError(str(e), 400)
|
||||
|
||||
if 'admin' in g.scopes or 'admin:blackouts' in g.scopes:
|
||||
blackout.user = blackout.user or g.user
|
||||
else:
|
||||
blackout.user = g.user
|
||||
|
||||
blackout.customer = assign_customer(wanted=blackout.customer, permission='admin:blackouts')
|
||||
|
||||
try:
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
|
||||
import json
|
||||
import unittest
|
||||
from datetime import datetime
|
||||
|
||||
from alerta.app import create_app, db, plugins
|
||||
from alerta.exceptions import BlackoutPeriod
|
||||
from alerta.models.key import ApiKey
|
||||
from alerta.plugins import PluginBase
|
||||
from alerta.utils.format import DateTime
|
||||
|
||||
|
||||
class BlackoutsTestCase(unittest.TestCase):
|
||||
|
@ -32,12 +34,12 @@ class BlackoutsTestCase(unittest.TestCase):
|
|||
with self.app.test_request_context('/'):
|
||||
self.app.preprocess_request()
|
||||
self.admin_api_key = ApiKey(
|
||||
user='admin',
|
||||
user='admin@alerta.io',
|
||||
scopes=['admin', 'read', 'write'],
|
||||
text='demo-key'
|
||||
)
|
||||
self.customer_api_key = ApiKey(
|
||||
user='admin',
|
||||
user='admin@alerta.io',
|
||||
scopes=['admin', 'read', 'write'],
|
||||
text='demo-key',
|
||||
customer='Foo'
|
||||
|
@ -197,6 +199,21 @@ class BlackoutsTestCase(unittest.TestCase):
|
|||
data = json.loads(response.data.decode('utf-8'))
|
||||
self.assertEqual(data['alert']['status'], 'closed')
|
||||
|
||||
def test_user_info(self):
|
||||
|
||||
self.headers = {
|
||||
'Authorization': 'Key %s' % self.admin_api_key.key,
|
||||
'Content-type': 'application/json'
|
||||
}
|
||||
|
||||
# create new blackout
|
||||
response = self.client.post('/blackout', data=json.dumps({"environment": "Production", "service": ["Network"], "text": "administratively down"}), headers=self.headers)
|
||||
self.assertEqual(response.status_code, 201)
|
||||
data = json.loads(response.data.decode('utf-8'))
|
||||
self.assertEqual(data['blackout']['user'], 'admin@alerta.io')
|
||||
self.assertIsInstance(DateTime.parse(data['blackout']['createTime']), datetime)
|
||||
self.assertEqual(data['blackout']['text'], 'administratively down')
|
||||
|
||||
|
||||
class SuppressionBlackout(PluginBase):
|
||||
|
||||
|
|
Loading…
Reference in a new issue