120 lines
6.5 KiB
Python
120 lines
6.5 KiB
Python
"""Add enhanced alert features for Phase 5
|
|
|
|
Revision ID: 004
|
|
Revises: 003
|
|
Create Date: 2025-11-18
|
|
|
|
"""
|
|
from alembic import op
|
|
import sqlalchemy as sa
|
|
|
|
|
|
# revision identifiers, used by Alembic
|
|
revision = '004'
|
|
down_revision = '003'
|
|
branch_labels = None
|
|
depends_on = None
|
|
|
|
|
|
def upgrade():
|
|
"""
|
|
Add enhancements for Phase 5 Alert Rule Engine:
|
|
- Enhanced alert_rules fields
|
|
- Enhanced alerts fields
|
|
- New webhooks table
|
|
- New webhook_delivery_log table
|
|
"""
|
|
|
|
# Enhance alert_rules table
|
|
with op.batch_alter_table('alert_rules') as batch_op:
|
|
batch_op.add_column(sa.Column('name', sa.String(255), nullable=True, comment='User-friendly rule name'))
|
|
batch_op.add_column(sa.Column('webhook_enabled', sa.Boolean(), nullable=False, server_default='0', comment='Whether to send webhooks for this rule'))
|
|
batch_op.add_column(sa.Column('severity', sa.String(20), nullable=True, comment='Alert severity level (critical, warning, info)'))
|
|
batch_op.add_column(sa.Column('filter_conditions', sa.Text(), nullable=True, comment='JSON filter conditions for the rule'))
|
|
batch_op.add_column(sa.Column('config_file', sa.String(255), nullable=True, comment='Optional: specific config file this rule applies to'))
|
|
batch_op.add_column(sa.Column('updated_at', sa.DateTime(), nullable=True, comment='Last update timestamp'))
|
|
|
|
# Enhance alerts table
|
|
with op.batch_alter_table('alerts') as batch_op:
|
|
batch_op.add_column(sa.Column('rule_id', sa.Integer(), nullable=True, comment='Associated alert rule'))
|
|
batch_op.add_column(sa.Column('webhook_sent', sa.Boolean(), nullable=False, server_default='0', comment='Whether webhook was sent'))
|
|
batch_op.add_column(sa.Column('webhook_sent_at', sa.DateTime(), nullable=True, comment='When webhook was sent'))
|
|
batch_op.add_column(sa.Column('acknowledged', sa.Boolean(), nullable=False, server_default='0', comment='Whether alert was acknowledged'))
|
|
batch_op.add_column(sa.Column('acknowledged_at', sa.DateTime(), nullable=True, comment='When alert was acknowledged'))
|
|
batch_op.add_column(sa.Column('acknowledged_by', sa.String(255), nullable=True, comment='User who acknowledged the alert'))
|
|
batch_op.create_foreign_key('fk_alerts_rule_id', 'alert_rules', ['rule_id'], ['id'])
|
|
batch_op.create_index('idx_alerts_rule_id', ['rule_id'])
|
|
batch_op.create_index('idx_alerts_acknowledged', ['acknowledged'])
|
|
|
|
# Create webhooks table
|
|
op.create_table('webhooks',
|
|
sa.Column('id', sa.Integer(), nullable=False),
|
|
sa.Column('name', sa.String(255), nullable=False, comment='Webhook name'),
|
|
sa.Column('url', sa.Text(), nullable=False, comment='Webhook URL'),
|
|
sa.Column('enabled', sa.Boolean(), nullable=False, server_default='1', comment='Whether webhook is enabled'),
|
|
sa.Column('auth_type', sa.String(20), nullable=True, comment='Authentication type: none, bearer, basic, custom'),
|
|
sa.Column('auth_token', sa.Text(), nullable=True, comment='Encrypted authentication token'),
|
|
sa.Column('custom_headers', sa.Text(), nullable=True, comment='JSON custom headers'),
|
|
sa.Column('alert_types', sa.Text(), nullable=True, comment='JSON array of alert types to trigger on'),
|
|
sa.Column('severity_filter', sa.Text(), nullable=True, comment='JSON array of severities to trigger on'),
|
|
sa.Column('timeout', sa.Integer(), nullable=True, server_default='10', comment='Request timeout in seconds'),
|
|
sa.Column('retry_count', sa.Integer(), nullable=True, server_default='3', comment='Number of retry attempts'),
|
|
sa.Column('created_at', sa.DateTime(), nullable=False),
|
|
sa.Column('updated_at', sa.DateTime(), nullable=False),
|
|
sa.PrimaryKeyConstraint('id')
|
|
)
|
|
|
|
# Create webhook_delivery_log table
|
|
op.create_table('webhook_delivery_log',
|
|
sa.Column('id', sa.Integer(), nullable=False),
|
|
sa.Column('webhook_id', sa.Integer(), nullable=False, comment='Associated webhook'),
|
|
sa.Column('alert_id', sa.Integer(), nullable=False, comment='Associated alert'),
|
|
sa.Column('status', sa.String(20), nullable=True, comment='Delivery status: success, failed, retrying'),
|
|
sa.Column('response_code', sa.Integer(), nullable=True, comment='HTTP response code'),
|
|
sa.Column('response_body', sa.Text(), nullable=True, comment='Response body from webhook'),
|
|
sa.Column('error_message', sa.Text(), nullable=True, comment='Error message if failed'),
|
|
sa.Column('attempt_number', sa.Integer(), nullable=True, comment='Which attempt this was'),
|
|
sa.Column('delivered_at', sa.DateTime(), nullable=False, comment='Delivery timestamp'),
|
|
sa.ForeignKeyConstraint(['webhook_id'], ['webhooks.id'], ),
|
|
sa.ForeignKeyConstraint(['alert_id'], ['alerts.id'], ),
|
|
sa.PrimaryKeyConstraint('id')
|
|
)
|
|
|
|
# Create indexes for webhook_delivery_log
|
|
op.create_index('idx_webhook_delivery_alert_id', 'webhook_delivery_log', ['alert_id'])
|
|
op.create_index('idx_webhook_delivery_webhook_id', 'webhook_delivery_log', ['webhook_id'])
|
|
op.create_index('idx_webhook_delivery_status', 'webhook_delivery_log', ['status'])
|
|
|
|
|
|
def downgrade():
|
|
"""Remove Phase 5 alert enhancements."""
|
|
|
|
# Drop webhook_delivery_log table and its indexes
|
|
op.drop_index('idx_webhook_delivery_status', table_name='webhook_delivery_log')
|
|
op.drop_index('idx_webhook_delivery_webhook_id', table_name='webhook_delivery_log')
|
|
op.drop_index('idx_webhook_delivery_alert_id', table_name='webhook_delivery_log')
|
|
op.drop_table('webhook_delivery_log')
|
|
|
|
# Drop webhooks table
|
|
op.drop_table('webhooks')
|
|
|
|
# Remove enhancements from alerts table
|
|
with op.batch_alter_table('alerts') as batch_op:
|
|
batch_op.drop_index('idx_alerts_acknowledged')
|
|
batch_op.drop_index('idx_alerts_rule_id')
|
|
batch_op.drop_constraint('fk_alerts_rule_id', type_='foreignkey')
|
|
batch_op.drop_column('acknowledged_by')
|
|
batch_op.drop_column('acknowledged_at')
|
|
batch_op.drop_column('acknowledged')
|
|
batch_op.drop_column('webhook_sent_at')
|
|
batch_op.drop_column('webhook_sent')
|
|
batch_op.drop_column('rule_id')
|
|
|
|
# Remove enhancements from alert_rules table
|
|
with op.batch_alter_table('alert_rules') as batch_op:
|
|
batch_op.drop_column('updated_at')
|
|
batch_op.drop_column('config_file')
|
|
batch_op.drop_column('filter_conditions')
|
|
batch_op.drop_column('severity')
|
|
batch_op.drop_column('webhook_enabled')
|
|
batch_op.drop_column('name') |