309 lines
13 KiB
Python
309 lines
13 KiB
Python
"""
|
|
Serializers for Automation & Orchestration models
|
|
"""
|
|
from rest_framework import serializers
|
|
from django.contrib.auth import get_user_model
|
|
from ..models import (
|
|
Runbook,
|
|
RunbookExecution,
|
|
Integration,
|
|
ChatOpsIntegration,
|
|
ChatOpsCommand,
|
|
AutoRemediation,
|
|
AutoRemediationExecution,
|
|
MaintenanceWindow,
|
|
WorkflowTemplate,
|
|
WorkflowExecution,
|
|
)
|
|
|
|
User = get_user_model()
|
|
|
|
|
|
class RunbookSerializer(serializers.ModelSerializer):
|
|
"""Serializer for Runbook model"""
|
|
|
|
created_by_username = serializers.CharField(source='created_by.username', read_only=True)
|
|
last_modified_by_username = serializers.CharField(source='last_modified_by.username', read_only=True)
|
|
can_trigger = serializers.SerializerMethodField()
|
|
|
|
class Meta:
|
|
model = Runbook
|
|
fields = [
|
|
'id', 'name', 'description', 'version', 'trigger_type', 'trigger_conditions',
|
|
'steps', 'estimated_duration', 'category', 'tags', 'status', 'is_public',
|
|
'created_by', 'created_by_username', 'last_modified_by', 'last_modified_by_username',
|
|
'execution_count', 'success_rate', 'created_at', 'updated_at', 'last_executed_at',
|
|
'can_trigger'
|
|
]
|
|
read_only_fields = [
|
|
'id', 'created_by_username', 'last_modified_by_username', 'execution_count',
|
|
'success_rate', 'created_at', 'updated_at', 'last_executed_at', 'can_trigger'
|
|
]
|
|
|
|
def get_can_trigger(self, obj):
|
|
"""Check if current user can trigger this runbook"""
|
|
request = self.context.get('request')
|
|
if request and request.user:
|
|
return obj.can_be_triggered_by(request.user)
|
|
return False
|
|
|
|
def validate_steps(self, value):
|
|
"""Validate runbook steps"""
|
|
if not isinstance(value, list):
|
|
raise serializers.ValidationError("Steps must be a list")
|
|
|
|
for i, step in enumerate(value):
|
|
if not isinstance(step, dict):
|
|
raise serializers.ValidationError(f"Step {i+1} must be a dictionary")
|
|
|
|
required_fields = ['name', 'action', 'timeout']
|
|
for field in required_fields:
|
|
if field not in step:
|
|
raise serializers.ValidationError(f"Step {i+1} missing required field: {field}")
|
|
|
|
return value
|
|
|
|
|
|
class RunbookExecutionSerializer(serializers.ModelSerializer):
|
|
"""Serializer for RunbookExecution model"""
|
|
|
|
runbook_name = serializers.CharField(source='runbook.name', read_only=True)
|
|
triggered_by_username = serializers.CharField(source='triggered_by.username', read_only=True)
|
|
incident_title = serializers.CharField(source='incident.title', read_only=True)
|
|
is_running = serializers.BooleanField(read_only=True)
|
|
is_completed = serializers.BooleanField(read_only=True)
|
|
|
|
class Meta:
|
|
model = RunbookExecution
|
|
fields = [
|
|
'id', 'runbook', 'runbook_name', 'triggered_by', 'triggered_by_username',
|
|
'trigger_type', 'trigger_data', 'incident', 'incident_title', 'status',
|
|
'current_step', 'total_steps', 'execution_log', 'error_message', 'output_data',
|
|
'started_at', 'completed_at', 'duration', 'is_running', 'is_completed'
|
|
]
|
|
read_only_fields = [
|
|
'id', 'runbook_name', 'triggered_by_username', 'incident_title',
|
|
'is_running', 'is_completed', 'started_at', 'completed_at', 'duration'
|
|
]
|
|
|
|
|
|
class IntegrationSerializer(serializers.ModelSerializer):
|
|
"""Serializer for Integration model"""
|
|
|
|
created_by_username = serializers.CharField(source='created_by.username', read_only=True)
|
|
is_healthy = serializers.BooleanField(read_only=True)
|
|
|
|
class Meta:
|
|
model = Integration
|
|
fields = [
|
|
'id', 'name', 'integration_type', 'description', 'configuration',
|
|
'authentication_config', 'status', 'last_health_check', 'health_status',
|
|
'error_message', 'request_count', 'last_used_at', 'created_by',
|
|
'created_by_username', 'created_at', 'updated_at', 'is_healthy'
|
|
]
|
|
read_only_fields = [
|
|
'id', 'created_by_username', 'last_health_check', 'health_status',
|
|
'error_message', 'request_count', 'last_used_at', 'created_at',
|
|
'updated_at', 'is_healthy'
|
|
]
|
|
|
|
def validate_configuration(self, value):
|
|
"""Validate integration configuration"""
|
|
if not isinstance(value, dict):
|
|
raise serializers.ValidationError("Configuration must be a dictionary")
|
|
return value
|
|
|
|
def validate_authentication_config(self, value):
|
|
"""Validate authentication configuration"""
|
|
if not isinstance(value, dict):
|
|
raise serializers.ValidationError("Authentication configuration must be a dictionary")
|
|
return value
|
|
|
|
|
|
class ChatOpsIntegrationSerializer(serializers.ModelSerializer):
|
|
"""Serializer for ChatOpsIntegration model"""
|
|
|
|
created_by_username = serializers.CharField(source='created_by.username', read_only=True)
|
|
|
|
class Meta:
|
|
model = ChatOpsIntegration
|
|
fields = [
|
|
'id', 'name', 'platform', 'webhook_url', 'bot_token', 'channel_id',
|
|
'command_prefix', 'available_commands', 'allowed_users', 'allowed_channels',
|
|
'is_active', 'last_activity', 'created_by', 'created_by_username',
|
|
'created_at', 'updated_at'
|
|
]
|
|
read_only_fields = [
|
|
'id', 'created_by_username', 'last_activity', 'created_at', 'updated_at'
|
|
]
|
|
|
|
def validate_available_commands(self, value):
|
|
"""Validate available commands"""
|
|
if not isinstance(value, list):
|
|
raise serializers.ValidationError("Available commands must be a list")
|
|
|
|
for i, command in enumerate(value):
|
|
if not isinstance(command, dict):
|
|
raise serializers.ValidationError(f"Command {i+1} must be a dictionary")
|
|
|
|
required_fields = ['name', 'description']
|
|
for field in required_fields:
|
|
if field not in command:
|
|
raise serializers.ValidationError(f"Command {i+1} missing required field: {field}")
|
|
|
|
return value
|
|
|
|
|
|
class ChatOpsCommandSerializer(serializers.ModelSerializer):
|
|
"""Serializer for ChatOpsCommand model"""
|
|
|
|
chatops_integration_name = serializers.CharField(source='chatops_integration.name', read_only=True)
|
|
triggered_runbook_name = serializers.CharField(source='triggered_runbook.name', read_only=True)
|
|
related_incident_title = serializers.CharField(source='related_incident.title', read_only=True)
|
|
|
|
class Meta:
|
|
model = ChatOpsCommand
|
|
fields = [
|
|
'id', 'chatops_integration', 'chatops_integration_name', 'command', 'arguments',
|
|
'user_id', 'channel_id', 'triggered_runbook', 'triggered_runbook_name',
|
|
'related_incident', 'related_incident_title', 'status', 'response_message',
|
|
'execution_log', 'error_message', 'executed_at', 'completed_at'
|
|
]
|
|
read_only_fields = [
|
|
'id', 'chatops_integration_name', 'triggered_runbook_name',
|
|
'related_incident_title', 'executed_at', 'completed_at'
|
|
]
|
|
|
|
|
|
class AutoRemediationSerializer(serializers.ModelSerializer):
|
|
"""Serializer for AutoRemediation model"""
|
|
|
|
created_by_username = serializers.CharField(source='created_by.username', read_only=True)
|
|
approval_users_usernames = serializers.SerializerMethodField()
|
|
success_rate = serializers.FloatField(read_only=True)
|
|
|
|
class Meta:
|
|
model = AutoRemediation
|
|
fields = [
|
|
'id', 'name', 'description', 'remediation_type', 'trigger_conditions',
|
|
'trigger_condition_type', 'remediation_config', 'timeout_seconds',
|
|
'requires_approval', 'approval_users', 'approval_users_usernames',
|
|
'max_executions_per_incident', 'is_active', 'created_by', 'created_by_username',
|
|
'created_at', 'updated_at', 'execution_count', 'success_count',
|
|
'last_executed_at', 'success_rate'
|
|
]
|
|
read_only_fields = [
|
|
'id', 'created_by_username', 'approval_users_usernames', 'created_at',
|
|
'updated_at', 'execution_count', 'success_count', 'last_executed_at', 'success_rate'
|
|
]
|
|
|
|
def get_approval_users_usernames(self, obj):
|
|
"""Get usernames of approval users"""
|
|
return [user.username for user in obj.approval_users.all()]
|
|
|
|
|
|
class AutoRemediationExecutionSerializer(serializers.ModelSerializer):
|
|
"""Serializer for AutoRemediationExecution model"""
|
|
|
|
auto_remediation_name = serializers.CharField(source='auto_remediation.name', read_only=True)
|
|
incident_title = serializers.CharField(source='incident.title', read_only=True)
|
|
approved_by_username = serializers.CharField(source='approved_by.username', read_only=True)
|
|
|
|
class Meta:
|
|
model = AutoRemediationExecution
|
|
fields = [
|
|
'id', 'auto_remediation', 'auto_remediation_name', 'incident', 'incident_title',
|
|
'status', 'trigger_data', 'approved_by', 'approved_by_username', 'approved_at',
|
|
'approval_notes', 'execution_log', 'output_data', 'error_message',
|
|
'triggered_at', 'started_at', 'completed_at', 'duration'
|
|
]
|
|
read_only_fields = [
|
|
'id', 'auto_remediation_name', 'incident_title', 'approved_by_username',
|
|
'triggered_at', 'started_at', 'completed_at', 'duration'
|
|
]
|
|
|
|
|
|
class MaintenanceWindowSerializer(serializers.ModelSerializer):
|
|
"""Serializer for MaintenanceWindow model"""
|
|
|
|
created_by_username = serializers.CharField(source='created_by.username', read_only=True)
|
|
is_active = serializers.BooleanField(read_only=True)
|
|
is_scheduled = serializers.BooleanField(read_only=True)
|
|
|
|
class Meta:
|
|
model = MaintenanceWindow
|
|
fields = [
|
|
'id', 'name', 'description', 'start_time', 'end_time', 'timezone',
|
|
'affected_services', 'affected_components', 'suppress_incident_creation',
|
|
'suppress_notifications', 'suppress_escalations', 'status', 'created_by',
|
|
'created_by_username', 'created_at', 'updated_at', 'incidents_suppressed',
|
|
'notifications_suppressed', 'is_active', 'is_scheduled'
|
|
]
|
|
read_only_fields = [
|
|
'id', 'created_by_username', 'created_at', 'updated_at',
|
|
'incidents_suppressed', 'notifications_suppressed', 'is_active', 'is_scheduled'
|
|
]
|
|
|
|
def validate(self, data):
|
|
"""Validate maintenance window data"""
|
|
if data.get('start_time') and data.get('end_time'):
|
|
if data['start_time'] >= data['end_time']:
|
|
raise serializers.ValidationError("Start time must be before end time")
|
|
return data
|
|
|
|
|
|
class WorkflowTemplateSerializer(serializers.ModelSerializer):
|
|
"""Serializer for WorkflowTemplate model"""
|
|
|
|
created_by_username = serializers.CharField(source='created_by.username', read_only=True)
|
|
|
|
class Meta:
|
|
model = WorkflowTemplate
|
|
fields = [
|
|
'id', 'name', 'description', 'template_type', 'workflow_steps',
|
|
'input_parameters', 'output_schema', 'usage_count', 'is_public',
|
|
'created_by', 'created_by_username', 'created_at', 'updated_at'
|
|
]
|
|
read_only_fields = [
|
|
'id', 'created_by_username', 'usage_count', 'created_at', 'updated_at'
|
|
]
|
|
|
|
def validate_workflow_steps(self, value):
|
|
"""Validate workflow steps"""
|
|
if not isinstance(value, list):
|
|
raise serializers.ValidationError("Workflow steps must be a list")
|
|
|
|
for i, step in enumerate(value):
|
|
if not isinstance(step, dict):
|
|
raise serializers.ValidationError(f"Step {i+1} must be a dictionary")
|
|
|
|
required_fields = ['name', 'action', 'conditions']
|
|
for field in required_fields:
|
|
if field not in step:
|
|
raise serializers.ValidationError(f"Step {i+1} missing required field: {field}")
|
|
|
|
return value
|
|
|
|
|
|
class WorkflowExecutionSerializer(serializers.ModelSerializer):
|
|
"""Serializer for WorkflowExecution model"""
|
|
|
|
workflow_template_name = serializers.CharField(source='workflow_template.name', read_only=True)
|
|
triggered_by_username = serializers.CharField(source='triggered_by.username', read_only=True)
|
|
related_incident_title = serializers.CharField(source='related_incident.title', read_only=True)
|
|
related_maintenance_name = serializers.CharField(source='related_maintenance.name', read_only=True)
|
|
|
|
class Meta:
|
|
model = WorkflowExecution
|
|
fields = [
|
|
'id', 'workflow_template', 'workflow_template_name', 'name', 'triggered_by',
|
|
'triggered_by_username', 'trigger_type', 'related_incident', 'related_incident_title',
|
|
'related_maintenance', 'related_maintenance_name', 'status', 'current_step',
|
|
'total_steps', 'input_data', 'output_data', 'execution_log', 'error_message',
|
|
'started_at', 'completed_at', 'duration'
|
|
]
|
|
read_only_fields = [
|
|
'id', 'workflow_template_name', 'triggered_by_username', 'related_incident_title',
|
|
'related_maintenance_name', 'started_at', 'completed_at', 'duration'
|
|
]
|