relationship-mapping

Installation
SKILL.md

CI Relationship Mapping

Overview

CI relationships form the backbone of CMDB value. Without relationships, CIs are isolated islands of data. This skill covers:

  • Understanding relationship types and their semantics
  • Creating and validating relationships between CIs
  • Analyzing dependency chains for impact assessment
  • Detecting orphan CIs that lack relationships
  • Maintaining relationship health over time

When to use: When modeling service dependencies, preparing for change impact analysis, auditing CMDB completeness, or troubleshooting service outages.

Value proposition: Well-mapped relationships enable accurate impact analysis, reducing change failures by up to 50% and decreasing MTTR during incidents.

Prerequisites

  • Roles: cmdb_admin or itil with CMDB write access
  • Access: cmdb_rel_ci, cmdb_rel_type, cmdb_ci tables
  • Knowledge: CI class hierarchy, dependency modeling concepts
  • Related skills: Complete cmdb/ci-discovery first

Procedure

Step 1: Understand Relationship Types

ServiceNow provides relationship types in cmdb_rel_type. Each relationship has:

  • Parent descriptor: How the parent relates to the child
  • Child descriptor: How the child relates to the parent

Common Relationship Types:

Relationship Parent Descriptor Child Descriptor Use Case
Runs on Runs on Hosts Application on Server
Depends on Depends on Used by Service dependencies
Contains Contains Contained by Physical containment
Connects to Connects to Connected by Network connectivity
Sends data to Sends data to Receives data from Data flows
Cluster of Cluster of Cluster member Clusters
Uses Uses Is used by Generic dependency

Query available relationship types:

Tool: SN-Query-Table
Parameters:
  table_name: cmdb_rel_type
  query: active=true
  fields: sys_id,name,parent_descriptor,child_descriptor
  limit: 100

REST API:

GET /api/now/table/cmdb_rel_type?sysparm_query=active=true&sysparm_fields=sys_id,name,parent_descriptor,child_descriptor&sysparm_limit=100

Step 2: Query Existing Relationships

Before creating relationships, understand what exists:

Find all relationships for a CI:

Tool: SN-Query-Table
Parameters:
  table_name: cmdb_rel_ci
  query: parent=[ci_sys_id]^ORchild=[ci_sys_id]
  fields: parent,child,type,sys_created_on
  limit: 50

Find downstream dependencies (what depends on this CI):

Tool: SN-Query-Table
Parameters:
  table_name: cmdb_rel_ci
  query: child=[ci_sys_id]^type.parent_descriptorLIKEDepends
  fields: parent,parent.name,type,type.parent_descriptor

Find upstream dependencies (what this CI depends on):

Tool: SN-Query-Table
Parameters:
  table_name: cmdb_rel_ci
  query: parent=[ci_sys_id]^type.parent_descriptorLIKEDepends
  fields: child,child.name,type,type.child_descriptor

Step 3: Create Relationships

Determine the correct relationship type first:

Decision Matrix:

Parent CI Type Child CI Type Recommended Relationship
Application Server Runs on
Business Service Application Depends on
Server Rack Contained by
Server Server Connects to (if network)
Database Server Runs on
Load Balancer Server Pool Contains

Find relationship type sys_id:

Tool: SN-Query-Table
Parameters:
  table_name: cmdb_rel_type
  query: nameLIKERuns on::Runs on
  fields: sys_id,name,parent_descriptor,child_descriptor

Create the relationship:

Tool: SN-Create-Record
Parameters:
  table_name: cmdb_rel_ci
  data:
    parent: [parent_ci_sys_id]
    child: [child_ci_sys_id]
    type: [relationship_type_sys_id]

Example - Application runs on Server:

Tool: SN-Create-Record
Parameters:
  table_name: cmdb_rel_ci
  data:
    parent: "abc123..."  # Application CI sys_id
    child: "def456..."   # Server CI sys_id
    type: "55c95bf6c0a8010e0118ec7056e1c57d"  # Runs on::Hosts

Step 4: Validate Relationships

Check for invalid relationships:

Find relationships with missing CIs:

Tool: SN-Execute-Background-Script
Parameters:
  description: Find invalid relationships with missing CIs
  script: |
    var gr = new GlideRecord('cmdb_rel_ci');
    gr.addQuery('parent.sys_idISEMPTY^ORchild.sys_idISEMPTY');
    gr.query();
    gs.info('Invalid relationships found: ' + gr.getRowCount());
    while (gr.next()) {
      gs.info('Invalid rel: ' + gr.sys_id + ' parent=' + gr.parent + ' child=' + gr.child);
    }

Find duplicate relationships:

Tool: SN-Execute-Background-Script
Parameters:
  description: Detect duplicate relationships
  script: |
    var duplicates = new GlideAggregate('cmdb_rel_ci');
    duplicates.addAggregate('COUNT');
    duplicates.groupBy('parent');
    duplicates.groupBy('child');
    duplicates.groupBy('type');
    duplicates.addHaving('COUNT', '>', 1);
    duplicates.query();
    gs.info('Duplicate relationship combinations found: ' + duplicates.getRowCount());
    while (duplicates.next()) {
      gs.info('Duplicate: parent=' + duplicates.parent + ' child=' + duplicates.child + ' type=' + duplicates.type + ' count=' + duplicates.getAggregate('COUNT'));
    }

Validate relationship type appropriateness:

Some relationship types are only valid for certain CI classes. Check the relationship type's parent_ci_class and child_ci_class fields if populated.

Step 5: Analyze Dependency Chains

Understanding full dependency chains is critical for impact analysis.

Get complete dependency tree (recursive):

Tool: SN-Execute-Background-Script
Parameters:
  description: Build dependency tree for CI
  script: |
    var ciSysId = 'YOUR_CI_SYS_ID';
    var maxDepth = 5;
    var visited = {};
    var tree = [];

    function getDependencies(parentId, depth, direction) {
      if (depth > maxDepth || visited[parentId]) return;
      visited[parentId] = true;

      var gr = new GlideRecord('cmdb_rel_ci');
      if (direction === 'down') {
        gr.addQuery('child', parentId);
        gr.addQuery('type.parent_descriptor', 'CONTAINS', 'Depends');
      } else {
        gr.addQuery('parent', parentId);
        gr.addQuery('type.parent_descriptor', 'CONTAINS', 'Depends');
      }
      gr.query();

      while (gr.next()) {
        var targetId = direction === 'down' ? gr.parent.toString() : gr.child.toString();
        var targetName = direction === 'down' ? gr.parent.name.toString() : gr.child.name.toString();
        tree.push({
          depth: depth,
          direction: direction,
          ci_name: targetName,
          ci_sys_id: targetId
        });
        getDependencies(targetId, depth + 1, direction);
      }
    }

    getDependencies(ciSysId, 1, 'down');
    gs.info('Upstream dependencies (what depends on this CI):');
    tree.forEach(function(item) {
      gs.info('  '.repeat(item.depth) + item.ci_name);
    });

Identify critical path:

Services with single points of failure have critical paths:

Tool: SN-Query-Table
Parameters:
  table_name: cmdb_rel_ci
  query: parent.sys_class_name=cmdb_ci_service^type.parent_descriptorLIKEDepends
  fields: parent.name,child.name,child.sys_class_name

Step 6: Detect Orphan CIs

Orphan CIs (those without relationships) reduce CMDB value and complicate impact analysis.

Find CIs with no relationships:

Tool: SN-Execute-Background-Script
Parameters:
  description: Find orphan CIs with no relationships
  script: |
    var orphans = [];
    var ciClasses = ['cmdb_ci_server', 'cmdb_ci_appl', 'cmdb_ci_database_instance'];

    ciClasses.forEach(function(ciClass) {
      var gr = new GlideRecord(ciClass);
      gr.addQuery('operational_status', '1');
      gr.query();

      while (gr.next()) {
        var relGr = new GlideRecord('cmdb_rel_ci');
        relGr.addQuery('parent', gr.sys_id);
        relGr.addOrCondition('child', gr.sys_id);
        relGr.setLimit(1);
        relGr.query();

        if (!relGr.hasNext()) {
          orphans.push({
            sys_id: gr.sys_id.toString(),
            name: gr.name.toString(),
            class: ciClass
          });
        }
      }
    });

    gs.info('Orphan CIs found: ' + orphans.length);
    orphans.forEach(function(o) {
      gs.info('  ' + o.class + ': ' + o.name + ' (' + o.sys_id + ')');
    });

MCP Alternative - Query-based approach:

Tool: SN-Query-Table
Parameters:
  table_name: cmdb_ci_server
  query: operational_status=1^sys_idNOT IN(SELECT parent FROM cmdb_rel_ci)^sys_idNOT IN(SELECT child FROM cmdb_rel_ci)
  fields: name,ip_address,sys_class_name
  limit: 50

Note: Complex subqueries may not work via REST API. Use background script for reliability.

Step 7: Maintain Relationship Health

Periodic cleanup script:

Tool: SN-Execute-Background-Script
Parameters:
  description: Clean up invalid relationships
  script: |
    var deleted = 0;

    // Delete relationships where parent CI was deleted
    var gr = new GlideRecord('cmdb_rel_ci');
    gr.addNullQuery('parent');
    gr.query();
    while (gr.next()) {
      gr.deleteRecord();
      deleted++;
    }

    // Delete relationships where child CI was deleted
    gr = new GlideRecord('cmdb_rel_ci');
    gr.addNullQuery('child');
    gr.query();
    while (gr.next()) {
      gr.deleteRecord();
      deleted++;
    }

    gs.info('Deleted ' + deleted + ' invalid relationships');

Update stale relationships: When a CI's operational status changes, relationships may need updates:

Tool: SN-Query-Table
Parameters:
  table_name: cmdb_rel_ci
  query: parent.operational_status!=1^ORchild.operational_status!=1
  fields: sys_id,parent.name,child.name,parent.operational_status,child.operational_status

Tool Usage Summary

Operation MCP Tool REST Endpoint
List relationship types SN-Query-Table GET /cmdb_rel_type
Query relationships SN-Query-Table GET /cmdb_rel_ci
Create relationship SN-Create-Record POST /cmdb_rel_ci
Delete relationship SN-Update-Record (set inactive) DELETE /cmdb_rel_ci/{id}
Complex queries SN-Execute-Background-Script POST /api/sn_chg_rest/change
CI relationships API N/A GET /cmdb/instance/{id}/relation

Best Practices

  • Bidirectional Awareness: Remember relationships have two perspectives (parent/child)
  • Minimum Relationships: Every operational CI should have at least one relationship
  • Type Consistency: Use consistent relationship types across similar CI patterns
  • Avoid Circular Dependencies: A should not depend on B if B depends on A
  • Document Business Context: Use relationship attributes to explain why the relationship exists
  • Regular Audits: Run orphan detection monthly; invalid relationship cleanup weekly
  • Discovery Integration: Align manual relationships with discovery-created relationships

Troubleshooting

Relationship Not Showing in Dependency View

Symptom: Created relationship doesn't appear in CI dependency views Cause: Relationship type not configured for dependency visualization Solution: Check cmdb_rel_type record - ensure is_used_by and is_dependency flags are set appropriately

Duplicate Relationships After Discovery

Symptom: Same relationship exists multiple times Cause: Manual creation overlapped with discovery Solution: Run duplicate detection script; delete duplicates keeping discovery-created records

Circular Dependency Detected

Symptom: Impact analysis shows infinite loop warning Cause: CI A depends on B, B depends on C, C depends on A Solution: Review and break the circular chain; often indicates incorrect relationship type usage

Relationship Type Not Found

Symptom: Cannot find appropriate relationship type for use case Cause: OOB types may not cover all scenarios Solution: Create custom relationship type via cmdb_rel_type table (requires cmdb_admin)

Examples

Example 1: Map a Three-Tier Application

# 1. Identify the CIs
Business Service: "Customer Portal"
Web Application: "Portal Frontend"
App Server: "prod-app-01"
Database: "Portal DB"
DB Server: "prod-db-01"

# 2. Find relationship type sys_ids
Tool: SN-Query-Table
Parameters:
  table_name: cmdb_rel_type
  query: nameLIKEDepends on^ORnameLIKERuns on
  fields: sys_id,name,parent_descriptor

# 3. Create relationships (batch in one message)
# Service depends on Web App
SN-Create-Record: cmdb_rel_ci
  parent: [service_sys_id], child: [webapp_sys_id], type: [depends_on_type]

# Web App runs on App Server
SN-Create-Record: cmdb_rel_ci
  parent: [webapp_sys_id], child: [appserver_sys_id], type: [runs_on_type]

# Web App depends on Database
SN-Create-Record: cmdb_rel_ci
  parent: [webapp_sys_id], child: [database_sys_id], type: [depends_on_type]

# Database runs on DB Server
SN-Create-Record: cmdb_rel_ci
  parent: [database_sys_id], child: [dbserver_sys_id], type: [runs_on_type]

Example 2: Orphan Detection and Remediation

# 1. Find orphan servers
Tool: SN-Execute-Background-Script
Parameters:
  script: [orphan detection script from Step 6]

# 2. For each orphan, determine what it hosts
Tool: SN-Query-Table
Parameters:
  table_name: cmdb_ci_appl
  query: install_dateLIKE[orphan_ip_address]
  fields: name,sys_id

# 3. Create missing relationships
Tool: SN-Create-Record
Parameters:
  table_name: cmdb_rel_ci
  data:
    parent: [app_sys_id]
    child: [orphan_server_sys_id]
    type: [runs_on_type_sys_id]

Related Skills

  • cmdb/ci-discovery - CI creation and classification
  • cmdb/impact-analysis - Using relationships for impact analysis
  • cmdb/data-quality - CMDB data quality management
  • itsm/change-management - Changes and CI relationships

References

Related skills
Installs
3
GitHub Stars
23
First Seen
11 days ago