feat: IT Glue integration, workflow engine, pipelines, Zabbix WAN, notification channels, backup status UI improvements, nav alignment fixes
This commit is contained in:
parent
ed6c4a8b65
commit
19605f82aa
97 changed files with 17080 additions and 304 deletions
157
migrations/033_create_pipeline_engine_tables.sql
Normal file
157
migrations/033_create_pipeline_engine_tables.sql
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
-- Pipeline Engine Tables
|
||||
-- Webhook-triggered automation pipelines with multi-step execution,
|
||||
-- notification channels, and human-in-the-loop approvals.
|
||||
|
||||
-- ============================================================================
|
||||
-- Notification Channels — UI-configured notification providers
|
||||
-- ============================================================================
|
||||
CREATE TABLE IF NOT EXISTS notification_channels (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(200) NOT NULL,
|
||||
channel_type VARCHAR(20) NOT NULL, -- 'teams', 'telegram', 'ntfy', 'webhook'
|
||||
config JSONB NOT NULL DEFAULT '{}', -- type-specific: webhook_url, bot_token, chat_id, topic, etc.
|
||||
is_active BOOLEAN DEFAULT true,
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ============================================================================
|
||||
-- Webhook Pipelines — workflow definitions
|
||||
-- ============================================================================
|
||||
CREATE TABLE IF NOT EXISTS webhook_pipelines (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(200) NOT NULL,
|
||||
description TEXT,
|
||||
is_active BOOLEAN DEFAULT true,
|
||||
trigger_source VARCHAR(50) NOT NULL, -- 'datto_rmm', 'autotask', 'veeam', 'manual'
|
||||
trigger_conditions JSONB NOT NULL DEFAULT '[]', -- array of {field, operator, value}
|
||||
sort_order INTEGER DEFAULT 0,
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ============================================================================
|
||||
-- Pipeline Steps — ordered actions within a pipeline
|
||||
-- ============================================================================
|
||||
CREATE TABLE IF NOT EXISTS pipeline_steps (
|
||||
id SERIAL PRIMARY KEY,
|
||||
pipeline_id INTEGER NOT NULL REFERENCES webhook_pipelines(id) ON DELETE CASCADE,
|
||||
step_order INTEGER NOT NULL,
|
||||
step_type VARCHAR(50) NOT NULL, -- 'filter','transform','enrich_device','create_ticket','notify','approval','rmm_quick_job', etc.
|
||||
name VARCHAR(200) NOT NULL,
|
||||
config JSONB NOT NULL DEFAULT '{}',
|
||||
on_failure VARCHAR(20) DEFAULT 'stop', -- 'continue', 'stop', 'skip_to'
|
||||
skip_to_step INTEGER,
|
||||
is_active BOOLEAN DEFAULT true,
|
||||
timeout_ms INTEGER,
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ============================================================================
|
||||
-- Pipeline Executions — runtime log
|
||||
-- ============================================================================
|
||||
CREATE TABLE IF NOT EXISTS pipeline_executions (
|
||||
id SERIAL PRIMARY KEY,
|
||||
pipeline_id INTEGER NOT NULL REFERENCES webhook_pipelines(id) ON DELETE CASCADE,
|
||||
trigger_source VARCHAR(50) NOT NULL,
|
||||
trigger_payload JSONB,
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'pending', -- 'pending','running','waiting','completed','failed','skipped'
|
||||
current_step INTEGER,
|
||||
context JSONB NOT NULL DEFAULT '{}', -- accumulated data from steps
|
||||
started_at TIMESTAMP DEFAULT NOW(),
|
||||
completed_at TIMESTAMP,
|
||||
duration_ms INTEGER,
|
||||
error_message TEXT,
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ============================================================================
|
||||
-- Pipeline Execution Steps — per-step log
|
||||
-- ============================================================================
|
||||
CREATE TABLE IF NOT EXISTS pipeline_execution_steps (
|
||||
id SERIAL PRIMARY KEY,
|
||||
execution_id INTEGER NOT NULL REFERENCES pipeline_executions(id) ON DELETE CASCADE,
|
||||
step_order INTEGER NOT NULL,
|
||||
step_type VARCHAR(50) NOT NULL,
|
||||
step_name VARCHAR(200),
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'pending', -- 'pending','running','completed','failed','waiting','skipped'
|
||||
input_data JSONB,
|
||||
output_data JSONB,
|
||||
started_at TIMESTAMP,
|
||||
completed_at TIMESTAMP,
|
||||
duration_ms INTEGER,
|
||||
error_message TEXT
|
||||
);
|
||||
|
||||
-- ============================================================================
|
||||
-- Approval Requests — human-in-the-loop
|
||||
-- ============================================================================
|
||||
CREATE TABLE IF NOT EXISTS approval_requests (
|
||||
id SERIAL PRIMARY KEY,
|
||||
execution_id INTEGER NOT NULL REFERENCES pipeline_executions(id) ON DELETE CASCADE,
|
||||
step_order INTEGER NOT NULL,
|
||||
channel_id INTEGER REFERENCES notification_channels(id),
|
||||
message TEXT NOT NULL,
|
||||
options JSONB NOT NULL DEFAULT '["Approve","Reject"]',
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'pending', -- 'pending','approved','rejected','timeout'
|
||||
responded_by TEXT,
|
||||
responded_at TIMESTAMP,
|
||||
response_data JSONB,
|
||||
expires_at TIMESTAMP,
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ============================================================================
|
||||
-- Indexes
|
||||
-- ============================================================================
|
||||
CREATE INDEX IF NOT EXISTS idx_notification_channels_type ON notification_channels(channel_type, is_active);
|
||||
CREATE INDEX IF NOT EXISTS idx_webhook_pipelines_source ON webhook_pipelines(trigger_source, is_active, sort_order);
|
||||
CREATE INDEX IF NOT EXISTS idx_pipeline_steps_pipeline ON pipeline_steps(pipeline_id, step_order);
|
||||
CREATE INDEX IF NOT EXISTS idx_pipeline_executions_pipeline ON pipeline_executions(pipeline_id, created_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_pipeline_executions_status ON pipeline_executions(status, created_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_pipeline_execution_steps_exec ON pipeline_execution_steps(execution_id, step_order);
|
||||
CREATE INDEX IF NOT EXISTS idx_approval_requests_exec ON approval_requests(execution_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_approval_requests_status ON approval_requests(status, expires_at);
|
||||
|
||||
-- ============================================================================
|
||||
-- SEED: Example pipeline — "RMM Alert → Autotask Ticket"
|
||||
-- ============================================================================
|
||||
INSERT INTO webhook_pipelines (name, description, is_active, trigger_source, trigger_conditions, sort_order) VALUES
|
||||
('RMM Alert → Autotask Ticket',
|
||||
'Creates an Autotask ticket when a Datto RMM alert fires (triggered=True). Enriches with device and company data.',
|
||||
false,
|
||||
'datto_rmm',
|
||||
'[{"field": "triggered", "operator": "equals", "value": "True"}]',
|
||||
10);
|
||||
|
||||
INSERT INTO pipeline_steps (pipeline_id, step_order, step_type, name, config) VALUES
|
||||
((SELECT id FROM webhook_pipelines WHERE name = 'RMM Alert → Autotask Ticket'), 1, 'transform', 'Extract alert fields', '{
|
||||
"mappings": {
|
||||
"alert_type": "{{trigger.alert_type}}",
|
||||
"alert_priority": "{{trigger.alert_priority}}",
|
||||
"alert_message": "{{trigger.alert_message_en}}",
|
||||
"device_hostname": "{{trigger.device_hostname}}",
|
||||
"device_uid": "{{trigger.device_uid}}",
|
||||
"site_name": "{{trigger.site_name}}",
|
||||
"site_uid": "{{trigger.site_uid}}",
|
||||
"device_ip": "{{trigger.device_ip}}",
|
||||
"device_os": "{{trigger.device_os}}",
|
||||
"last_user": "{{trigger.last_user}}"
|
||||
}
|
||||
}'),
|
||||
((SELECT id FROM webhook_pipelines WHERE name = 'RMM Alert → Autotask Ticket'), 2, 'enrich_company', 'Lookup company from site', '{
|
||||
"lookup_by": "site_name",
|
||||
"source_field": "{{context.site_name}}"
|
||||
}'),
|
||||
((SELECT id FROM webhook_pipelines WHERE name = 'RMM Alert → Autotask Ticket'), 3, 'create_ticket', 'Create Autotask ticket', '{
|
||||
"template": {
|
||||
"title": "[RMM {{context.alert_type}}] {{context.device_hostname}} - {{context.alert_message}}",
|
||||
"description": "Datto RMM Alert\n\nType: {{context.alert_type}}\nPriority: {{context.alert_priority}}\nDevice: {{context.device_hostname}} ({{context.device_ip}})\nOS: {{context.device_os}}\nSite: {{context.site_name}}\nLast User: {{context.last_user}}\n\nMessage:\n{{context.alert_message}}",
|
||||
"companyID": "{{context.company_id}}",
|
||||
"ticketType": 2,
|
||||
"ticketCategory": 3,
|
||||
"priority": 1,
|
||||
"queueID": 29682833
|
||||
}
|
||||
}');
|
||||
Loading…
Add table
Add a link
Reference in a new issue