# Plugin Data Sources Learn how to configure different data sources for your plugin. ## Overview Data sources determine **where the plugin gets its data** and **what format it returns**. NetAlertX supports multiple data source types, each suited for different use cases. | Data Source | Type | Purpose | Returns | Example | |-------------|------|---------|---------|---------| | `script` | Code Execution | Execute Linux commands or Python scripts | Pipeline | Scan network, collect metrics, call APIs | | `app-db-query` | Database Query | Query the NetAlertX database | Result set | Show devices, open ports, recent events | | `sqlite-db-query` | External DB | Query external SQLite databases | Result set | PiHole database, external logs | | `template` | Template | Generate values from templates | Values | Initialize default settings | ## Data Source: `script` Execute any Linux command or Python script and capture its output. ### Configuration ```json { "data_source": "script", "show_ui": true, "mapped_to_table": "CurrentScan" } ``` ### How It Works 1. Command specified in `CMD` setting is executed 2. Script writes results to `/tmp/log/plugins/last_result..log` 3. Core reads file and parses pipe-delimited results 4. Results inserted into database ### Example: Simple Python Script ```json { "function": "CMD", "type": {"dataType": "string", "elements": [{"elementType": "input", "elementOptions": [], "transformers": []}]}, "default_value": "python3 /app/front/plugins/my_plugin/script.py", "localized": ["name"], "name": [{"language_code": "en_us", "string": "Command"}] } ``` ### Example: Bash Script ```json { "function": "CMD", "default_value": "bash /app/front/plugins/my_plugin/script.sh", "localized": ["name"], "name": [{"language_code": "en_us", "string": "Command"}] } ``` ### Best Practices - **Always use absolute paths** (e.g., `/app/front/plugins/...`) - **Use `plugin_helper.py`** for output formatting - **Add timeouts** via `RUN_TIMEOUT` setting (default: 60s) - **Log errors** to `/tmp/log/plugins/.log` - **Handle missing dependencies gracefully** ### Output Format Must write to: `/tmp/log/plugins/last_result..log` Format: Pipe-delimited, 9 or 13 columns See [Plugin Data Contract](PLUGINS_DEV_DATA_CONTRACT.md) for exact format --- ## Data Source: `app-db-query` Query the NetAlertX SQLite database and display results. ### Configuration ```json { "data_source": "app-db-query", "show_ui": true, "mapped_to_table": "CurrentScan" } ``` ### How It Works 1. SQL query specified in `CMD` setting is executed against `app.db` 2. Results parsed according to column definitions 3. Inserted into plugin display/database ### SQL Query Requirements - Must return exactly **9 or 13 columns** matching the [data contract](PLUGINS_DEV_DATA_CONTRACT.md) - Column names must match (order matters!) - Must be **readable SQLite SQL** (not vendor-specific) ### Example: Open Ports from Nmap ```json { "function": "CMD", "type": {"dataType": "string", "elements": [{"elementType": "input", "elementOptions": [], "transformers": []}]}, "default_value": "SELECT dv.devName as Object_PrimaryID, cast(dv.devLastIP as VARCHAR(100)) || ':' || cast(SUBSTR(ns.Port, 0, INSTR(ns.Port, '/')) as VARCHAR(100)) as Object_SecondaryID, datetime() as DateTime, ns.Service as Watched_Value1, ns.State as Watched_Value2, null as Watched_Value3, null as Watched_Value4, ns.Extra as Extra, dv.devMac as ForeignKey FROM (SELECT * FROM Nmap_Scan) ns LEFT JOIN (SELECT devName, devMac, devLastIP FROM Devices) dv ON ns.MAC = dv.devMac", "localized": ["name"], "name": [{"language_code": "en_us", "string": "SQL to run"}], "description": [{"language_code": "en_us", "string": "This SQL query populates the plugin table"}] } ``` ### Example: Recent Device Events ```sql SELECT e.EventValue as Object_PrimaryID, d.devName as Object_SecondaryID, e.EventDateTime as DateTime, e.EventType as Watched_Value1, d.devLastIP as Watched_Value2, null as Watched_Value3, null as Watched_Value4, e.EventDetails as Extra, d.devMac as ForeignKey FROM Events e LEFT JOIN Devices d ON e.DeviceMac = d.devMac WHERE e.EventDateTime > datetime('now', '-24 hours') ORDER BY e.EventDateTime DESC ``` See the [Database documentation](./DATABASE.md) for a list of common columns. --- ## Data Source: `sqlite-db-query` Query an **external SQLite database** mounted in the container. ### Configuration First, define the database path in a setting: ```json { "function": "DB_PATH", "type": {"dataType": "string", "elements": [{"elementType": "input", "elementOptions": [], "transformers": []}]}, "default_value": "/etc/pihole/pihole-FTL.db", "localized": ["name"], "name": [{"language_code": "en_us", "string": "Database path"}], "description": [{"language_code": "en_us", "string": "Path to external SQLite database"}] } ``` Then set data source and query: ```json { "data_source": "sqlite-db-query", "show_ui": true } ``` ### How It Works 1. External database file path specified in `DB_PATH` setting 2. Database mounted at that path (e.g., via Docker volume) 3. SQL query executed against external database using `EXTERNAL_.` prefix 4. Results returned in standard format ### SQL Query Example: PiHole Data ```json { "function": "CMD", "default_value": "SELECT hwaddr as Object_PrimaryID, cast('http://' || (SELECT ip FROM EXTERNAL_PIHOLE.network_addresses WHERE network_id = id ORDER BY lastseen DESC LIMIT 1) as VARCHAR(100)) || ':' || cast(SUBSTR((SELECT name FROM EXTERNAL_PIHOLE.network_addresses WHERE network_id = id ORDER BY lastseen DESC LIMIT 1), 0, INSTR((SELECT name FROM EXTERNAL_PIHOLE.network_addresses WHERE network_id = id ORDER BY lastseen DESC LIMIT 1), '/')) as VARCHAR(100)) as Object_SecondaryID, datetime() as DateTime, macVendor as Watched_Value1, lastQuery as Watched_Value2, (SELECT name FROM EXTERNAL_PIHOLE.network_addresses WHERE network_id = id ORDER BY lastseen DESC LIMIT 1) as Watched_Value3, null as Watched_Value4, '' as Extra, hwaddr as ForeignKey FROM EXTERNAL_PIHOLE.network WHERE hwaddr NOT LIKE 'ip-%' AND hwaddr <> '00:00:00:00:00:00'", "localized": ["name"], "name": [{"language_code": "en_us", "string": "SQL to run"}] } ``` ### Key Points - **Prefix all external tables** with `EXTERNAL_.` - For PiHole (`PIHOLE` prefix): `EXTERNAL_PIHOLE.network` - For custom database (`CUSTOM` prefix): `EXTERNAL_CUSTOM.my_table` - **Database must be valid SQLite** - **Path must be accessible** inside the container - **No columns beyond the data contract** required ### Docker Volume Setup To mount external database in docker-compose: ```yaml services: netalertx: volumes: - /path/on/host/pihole-FTL.db:/etc/pihole/pihole-FTL.db:ro ``` --- ## Data Source: `template` Generate values from a template. Usually used for initialization and default settings. ### Configuration ```json { "data_source": "template" } ``` ### How It Works - **Not widely used** in standard plugins - Used internally for generating default values - Check `newdev_template` plugin for implementation example ### Example: Default Device Template ```json { "function": "DEFAULT_DEVICE_PROPERTIES", "type": {"dataType": "string", "elements": [{"elementType": "textarea", "elementOptions": [], "transformers": []}]}, "default_value": "type=Unknown|vendor=Unknown", "localized": ["name"], "name": [{"language_code": "en_us", "string": "Default properties"}] } ``` --- ## Data Source: `plugin_type` Declare the plugin category. Controls where settings appear in the UI. ### Configuration ```json { "data_source": "plugin_type", "value": "scanner" } ``` ### Supported Values | Value | Section | Purpose | |-------|---------|---------| | `scanner` | Device Scanners | Discovers devices on network | | `system` | System Plugins | Core system functionality | | `publisher` | Notification/Alert Plugins | Sends notifications/alerts | | `importer` | Data Importers | Imports devices from external sources | | `other` | Other Plugins | Miscellaneous functionality | ### Example ```json { "settings": [ { "function": "plugin_type", "type": {"dataType": "string", "elements": []}, "default_value": "scanner", "options": ["scanner"], "data_source": "plugin_type", "value": "scanner", "localized": [] } ] } ``` --- ## Execution Order Control plugin execution priority. Higher priority plugins run first. ```json { "execution_order": "Layer_0" } ``` ### Levels (highest to lowest priority) - `Layer_0` - Highest priority (run first) - `Layer_1` - `Layer_2` - ... ### Example: Device Discovery ```json { "code_name": "device_scanner", "unique_prefix": "DEVSCAN", "execution_order": "Layer_0", "data_source": "script", "mapped_to_table": "CurrentScan" } ``` --- ## Performance Considerations ### Script Source - **Pros:** Flexible, can call external tools - **Cons:** Slower than database queries - **Optimization:** Add caching, use timeouts - **Default timeout:** 60 seconds (set `RUN_TIMEOUT`) ### Database Query Source - **Pros:** Fast, native query optimization - **Cons:** Limited to SQL capabilities - **Optimization:** Use indexes, avoid complex joins - **Timeout:** Usually instant ### External DB Query Source - **Pros:** Direct access to external data - **Cons:** Network latency, external availability - **Optimization:** Use indexes in external DB, selective queries - **Timeout:** Depends on DB response time --- ## Debugging Data Sources ### Check Script Output ```bash # Run script manually python3 /app/front/plugins/my_plugin/script.py # Check result file cat /tmp/log/plugins/last_result.MYPREFIX.log ``` ### Test SQL Query ```bash # Connect to app database sqlite3 /data/db/app.db # Run query sqlite> SELECT ... ; ``` ### Monitor Execution ```bash # Watch backend logs tail -f /tmp/log/stdout.log | grep -i "data_source\|MYPREFIX" ``` --- ## See Also - [Plugin Data Contract](PLUGINS_DEV_DATA_CONTRACT.md) - Output format specification - [Plugin Settings System](PLUGINS_DEV_SETTINGS.md) - How to define settings - [Quick Start Guide](PLUGINS_DEV_QUICK_START.md) - Create your first plugin - [Database Schema](DATABASE.md) - Available tables and columns - [Debugging Plugins](DEBUG_PLUGINS.md) - Troubleshooting data issues