discovery-patterns

Discovery Patterns for ServiceNow

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "discovery-patterns" with this command: npx skills add groeimetai/snow-flow/groeimetai-snow-flow-discovery-patterns

Discovery Patterns for ServiceNow

Discovery automatically populates the CMDB by scanning networks and systems.

Discovery Architecture

Discovery Schedule ↓ MID Server ↓ Probes (collect data) ↓ Sensors (process data) ↓ Identification Rules (match/create CIs) ↓ CMDB Population

Key Tables

Table Purpose

discovery_schedule

Discovery schedules

discovery_credentials

Discovery credentials

discovery_range

IP ranges to scan

cmdb_identification_rule

CI identification

ecc_agent

MID Server records

discovery_status

Discovery run status

Discovery Schedules (ES5)

Create Discovery Schedule

// Create discovery schedule (ES5 ONLY!) var schedule = new GlideRecord("discovery_schedule") schedule.initialize()

// Basic info schedule.setValue("name", "Data Center Discovery") schedule.setValue("description", "Weekly discovery of data center infrastructure")

// Type schedule.setValue("discover", "IP") // IP, CI, Cloud Resources

// Schedule schedule.setValue("run_type", "weekly") schedule.setValue("run_dayofweek", "sunday") schedule.setValue("run_time", "02:00:00")

// MID Server schedule.setValue("mid_server", getMIDServerSysId("DataCenterMID"))

// Enable schedule.setValue("active", true)

var scheduleSysId = schedule.insert()

// Add IP range addDiscoveryRange(scheduleSysId, "10.0.0.0", "10.0.255.255", "Data Center Network")

Add Discovery Range

// Add IP range to discovery schedule (ES5 ONLY!) function addDiscoveryRange(scheduleSysId, startIP, endIP, name) { var range = new GlideRecord("discovery_range") range.initialize() range.setValue("schedule", scheduleSysId) range.setValue("name", name) range.setValue("type", "range") range.setValue("range_start", startIP) range.setValue("range_end", endIP) range.setValue("active", true) return range.insert() }

// Add CIDR range function addDiscoveryCIDR(scheduleSysId, cidr, name) { var range = new GlideRecord("discovery_range") range.initialize() range.setValue("schedule", scheduleSysId) range.setValue("name", name) range.setValue("type", "cidr") range.setValue("range", cidr) // e.g., '10.0.0.0/24' range.setValue("active", true) return range.insert() }

Discovery Credentials (ES5)

Create Credentials

// Create Windows credential (ES5 ONLY!) var cred = new GlideRecord("discovery_credentials") cred.initialize() cred.setValue("name", "Windows Domain Admin") cred.setValue("type", "windows") cred.setValue("user_name", "domain\admin") cred.setValue("password", "") // Set via secure method cred.setValue("active", true)

// Credential order cred.setValue("order", 100)

// Assign to credential affinity cred.setValue("credential_alias", credentialAliasSysId)

cred.insert()

Credential Affinity

// Create credential affinity (map credentials to IP ranges) (ES5 ONLY!) var affinity = new GlideRecord("dscy_credentials_affinity") affinity.initialize() affinity.setValue("credential", credentialSysId) affinity.setValue("range", discoveryRangeSysId) affinity.setValue("order", 100) affinity.insert()

Custom Probes and Sensors (ES5)

Custom Probe

// Create custom probe script (ES5 ONLY!) // Probes run on MID Server to collect data

// Table: discovery_probes_script var probe = new GlideRecord("discovery_probes_script") probe.initialize() probe.setValue("name", "Custom Application Version") probe.setValue("active", true)

// Probe script (runs on MID Server - ES5 ONLY!) probe.setValue( "script", "var output = {};\n" + "\n" + "// Command to run\n" + 'var cmd = "cat /opt/myapp/version.txt";\n' + "\n" + "try {\n" + " var result = Packages.com.service_now.mid.probe.tpcon.OperatingSystemCommand.execute(cmd);\n" + " output.app_version = result.getOutput().trim();\n" + " output.success = true;\n" + "} catch (e) {\n" + " output.success = false;\n" + " output.error = e.message;\n" + "}\n" + "\n" + "output;", )

probe.insert()

Custom Sensor

// Create custom sensor (ES5 ONLY!) // Sensors run on ServiceNow instance to process probe results

// Table: discovery_sensors_script var sensor = new GlideRecord("discovery_sensors_script") sensor.initialize() sensor.setValue("name", "Process Custom Application Version") sensor.setValue("active", true) sensor.setValue("probe", probeSysId)

// Sensor script (runs on instance - ES5 ONLY!) sensor.setValue( "script", "(function process(result, source) {\n" + " var output = JSON.parse(result.output);\n" + " \n" + " if (!output.success) {\n" + ' gs.warn("Custom app discovery failed: " + output.error);\n' + " return;\n" + " }\n" + " \n" + " // Find or create CI\n" + " var ci = source.getDeviceRecord();\n" + " if (ci) {\n" + " ci.u_custom_app_version = output.app_version;\n" + " ci.update();\n" + ' gs.info("Updated CI with app version: " + output.app_version);\n' + " }\n" + "})(result, source);", )

sensor.insert()

Identification Rules (ES5)

CI Identification Rule

// Create identification rule (ES5 ONLY!) var rule = new GlideRecord("cmdb_identifier") rule.initialize()

rule.setValue("name", "Server Identification") rule.setValue("table", "cmdb_ci_server") rule.setValue("active", true)

// Priority (lower = higher priority) rule.setValue("order", 100)

// Identification entries (criteria) rule.insert()

// Add identification criteria var entry = new GlideRecord("cmdb_identifier_entry") entry.initialize() entry.setValue("identifier", rule.getUniqueValue()) entry.setValue("criterion_attributes", "serial_number") // Match by serial entry.setValue("search_type", "equals") entry.setValue("active", true) entry.insert()

Custom Identification Script

// Identification script for complex matching (ES5 ONLY!) // Table: cmdb_identifier_script

var script = new GlideRecord("cmdb_identifier_script") script.initialize() script.setValue("name", "Custom Server Match") script.setValue("table", "cmdb_ci_server") script.setValue("active", true)

script.setValue( "script", "(function identify(source) {\n" + ' var serial = source.getValue("serial_number");\n' + ' var hostname = source.getValue("name");\n' + " \n" + " // Try serial match first\n" + ' var gr = new GlideRecord("cmdb_ci_server");\n' + " if (serial) {\n" + ' gr.addQuery("serial_number", serial);\n' + " gr.query();\n" + " if (gr.next()) {\n" + " return gr.getUniqueValue();\n" + " }\n" + " }\n" + " \n" + " // Try hostname + IP match\n" + ' gr = new GlideRecord("cmdb_ci_server");\n' + ' gr.addQuery("name", hostname);\n' + ' gr.addQuery("ip_address", source.getValue("ip_address"));\n' + " gr.query();\n" + " if (gr.next()) {\n" + " return gr.getUniqueValue();\n" + " }\n" + " \n" + " // No match - return null to create new CI\n" + " return null;\n" + "})(source);", )

script.insert()

Discovery Status (ES5)

Monitor Discovery Status

// Check discovery run status (ES5 ONLY!) function getDiscoveryStatus(scheduleSysId) { var status = new GlideRecord("discovery_status") status.addQuery("dscheduler", scheduleSysId) status.orderByDesc("sys_created_on") status.setLimit(1) status.query()

if (status.next()) { return { state: status.state.getDisplayValue(), started: status.getValue("started"), completed: status.getValue("completed"), devices_found: status.getValue("devices_found"), devices_completed: status.getValue("devices_completed"), errors: status.getValue("error_count"), } } return null }

Discovery Device Results

// Get discovered devices from a run (ES5 ONLY!) function getDiscoveredDevices(statusSysId) { var devices = []

var device = new GlideRecord("discovery_device_history") device.addQuery("status", statusSysId) device.query()

while (device.next()) { devices.push({ ip_address: device.getValue("source"), ci: device.cmdb_ci.getDisplayValue(), ci_class: device.getValue("ci_type"), state: device.state.getDisplayValue(), issues: device.getValue("issue_count"), }) }

return devices }

MCP Tool Integration

Available Tools

Tool Purpose

snow_query_table

Query discovery tables

snow_find_artifact

Find discovery configs

snow_execute_script_with_output

Test discovery scripts

snow_cmdb_search

Search discovered CIs

Example Workflow

// 1. Query active schedules await snow_query_table({ table: "discovery_schedule", query: "active=true", fields: "name,discover,run_type,mid_server", })

// 2. Check recent discovery status await snow_execute_script_with_output({ script: var status = getDiscoveryStatus('schedule_sys_id'); gs.info(JSON.stringify(status)); , })

// 3. Find discovery errors await snow_query_table({ table: "discovery_log", query: "level=error^sys_created_on>=javascript:gs.daysAgo(1)", fields: "message,source,sys_created_on", })

Best Practices

  • Credential Security - Use credential vault

  • Schedule Off-Peak - Minimize network impact

  • Range Management - Organize by network segment

  • MID Server - Proper placement and sizing

  • Identification - Clear matching criteria

  • Reconciliation - Regular CMDB validation

  • Monitoring - Track discovery health

  • ES5 Only - No modern JavaScript syntax

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

predictive-intelligence

No summary provided by upstream source.

Repository SourceNeeds Review
General

scheduled-jobs

No summary provided by upstream source.

Repository SourceNeeds Review
General

document-management

No summary provided by upstream source.

Repository SourceNeeds Review
General

reporting-dashboards

No summary provided by upstream source.

Repository SourceNeeds Review