Skip to content

Diff Command

graju256 edited this page Dec 22, 2025 · 4 revisions

Diff Command

Overview

The diff command identifies differences between two Gateway configurations (bundles or live Gateways) and generates a difference bundle that can be applied to synchronize them. It's essential for environment synchronization, change tracking, and migration planning.

Syntax

Compare Bundles or Gateways

graphman diff --input-source <input-file-or-gateway> --input-target <input-file-or-gateway>
  [--input-mappings <input-mappings-file>]
  [--output <output-file>]
  [--output-report <output-report-file>]
  [--output-id-mappings <output-id-mappings-file>]
  [--options.<name> <value>,...]

Generate Bundle from Report

graphman diff --input-report <input-report-file>
  [--output <output-file>]
  [--options.<name> <value>,...]

Parameters

Comparison Mode Parameters

Parameter Description Default
--input-source Source bundle file or gateway (prefix with @) Required
--input-target Target bundle file or gateway (prefix with @) Required
--input-mappings @since 2.0.9 File with GOID/GUID mappings between environments None
--output Output file for difference bundle Standard output
--output-report Detailed difference report file <output>.diff-report.json
--output-id-mappings GOID/GUID mappings file <output>.id-mappings.json

Report Mode Parameters

Parameter Description
--input-report Previously generated diff report
--output Output file for difference bundle

Options

Option Default Description
includeInserts true Include entities that exist in source but not target
includeUpdates true Include entities that differ between source and target
includeDeletes false Include entities that exist in target but not source
useNoDefMappings false Use no-definition mappings for deletions
renewEntities false Fetch full entity details from gateways

Gateway Specification

Use the @ prefix to specify a gateway instead of a bundle file:

--input-source @dev
--input-target @prod

The gateway name must be configured in graphman.configuration.

Behavior

Difference Categories

The diff operation categorizes entities into three groups:

Category Description Default Inclusion
Inserts Entities in source but not in target Yes
Updates Entities that differ between source and target Yes
Deletes Entities in target but not in source No

Comparison Logic

  1. Entities are matched by their identifying attributes (name, GUID, etc.)
  2. Matched entities are compared using checksums
  3. If checksums differ, detailed field-by-field comparison is performed
  4. GOID/GUID mappings are tracked for cross-environment references

Output Files

When comparing, three files are generated:

  1. Difference Bundle: Entities to apply to target
  2. Difference Report: Detailed analysis with field-level differences
  3. ID Mappings: GOID/GUID mappings between environments

Examples

Compare Two Bundles

Compare source and target bundle files:

graphman diff --input-source source.json --input-target target.json --output differences.json

Compare Live Gateways

Compare two live Gateway environments:

graphman diff --input-source @dev --input-target @prod --output dev-to-prod.json

Compare Bundle to Gateway

Compare a bundle file against a live Gateway:

graphman diff --input-source release-bundle.json --input-target @prod --output changes.json

Include Deletions

Generate diff including entities to delete:

graphman diff --input-source source.json --input-target target.json \
  --output sync.json \
  --options.includeDeletes true

Exclude Updates

Generate diff with only new entities (no updates):

graphman diff --input-source source.json --input-target target.json \
  --output new-only.json \
  --options.includeUpdates false

With External Mappings

Use pre-defined mappings for resolving GOID/GUID differences: Most of the cases, GOID/GUID differences will be resolved if the entities are defined with the same identity across the environments. When they don't, external mappings would help to resolve such differences.

Prepare known mappings in known-mappings.json file

{
  "mappings": {
    "internalUsers": [
      {
        "source": {
          "login": "alice"
        },
        "target": {
          "login": "prod-alice"
        }
      },
      {
        "source": {
          "login": "bob"
        },
        "target": {
          "login": "regex:.*-bob"
        }
      }
    ]
  }
}
graphman diff --input-source source.json --input-target target.json \
  --input-mappings known-mappings.json \
  --output differences.json

Renew Entities

Fetch complete entity details from gateways:

graphman diff --input-source @dev --input-target @prod \
  --output differences.json \
  --options.renewEntities true

Generate Bundle from Report

Regenerate difference bundle from a previous report:

graphman diff --input-report differences.diff-report.json --output new-diff.json

Use Cases

1. Environment Synchronization

Synchronize development changes to production:

# Generate diff
graphman diff --input-source @dev --input-target @prod --output sync-bundle.json

# Review the diff report
cat sync-bundle.diff-report.json

# Apply changes
graphman import --input sync-bundle.json --gateway prod

2. Change Tracking

Track what changed between releases:

graphman diff --input-source release-v1.json --input-target release-v2.json \
  --output changes-v1-to-v2.json

3. Migration Planning

Plan migration from old to new environment:

graphman diff --input-source @old-gateway --input-target @new-gateway \
  --output migration-plan.json \
  --options.renewEntities true

4. Configuration Drift Detection

Detect drift between environments:

# Compare production to baseline
graphman diff --input-source baseline.json --input-target @prod \
  --output drift-report.json

# Review drift
jq '.diffs' drift-report.diff-report.json

5. Selective Synchronization

Synchronize only specific changes:

# Generate full diff
graphman diff --input-source @dev --input-target @prod --output full-diff.json

# Slice specific sections
graphman slice --input full-diff.json --sections services policies --output services-diff.json

# Apply selective changes
graphman import --input services-diff.json --gateway prod

6. Cleanup Operations

Identify and remove obsolete entities:

graphman diff --input-source current-standard.json --input-target @prod \
  --output cleanup.json \
  --options.includeDeletes true \
  --options.includeInserts false \
  --options.includeUpdates false

7. Cross-Environment Deployment

Deploy with environment-specific ID mappings:

# Generate diff with mappings
graphman diff --input-source @dev --input-target @prod \
  --output deploy.json

# Import using generated mappings
graphman import --input deploy.json \
  --input-id-mappings deploy.id-mappings.json \
  --gateway prod

Difference Report Structure

The diff report contains:

{
  "inserts": {
    "services": [...],
    "policies": [...]
  },
  "updates": {
    "services": [...],
    "policies": [...]
  },
  "deletes": {
    "services": [...],
    "policies": [...]
  },
  "diffs": {
    "services": [
      {
        "name": "MyService",
        "guid": "...",
        "details": [
          {
            "path": "$.enabled",
            "source": true,
            "target": false
          }
        ]
      }
    ]
  },
  "mappings": {
    "goids": [
      {"source": "abc123", "target": "def456"}
    ],
    "guids": [
      {"source": "guid1", "target": "guid2"}
    ]
  }
}

ID Mappings

GOID Mappings

Gateway Object IDs (GOIDs) are environment-specific. The diff operation tracks:

  • Which entities have different GOIDs between environments
  • Mappings needed for cross-references

GUID Mappings

Globally Unique Identifiers (GUIDs) may differ when entities are recreated. Mappings track:

  • Entity GUID differences
  • Required updates for policy references

Using Mappings

# Generate diff (creates mappings)
graphman diff --input-source @dev --input-target @prod --output diff.json

# Import with mappings (updates references)
graphman import --input diff.json \
  --input-id-mappings diff.id-mappings.json \
  --gateway prod

Advanced Features

Renew Entities Option

When comparing gateways (not bundles), use renewEntities to fetch complete entity details:

graphman diff --input-source @dev --input-target @prod \
  --output diff.json \
  --options.renewEntities true

This ensures:

  • Complete entity details in the diff bundle
  • Accurate field-level comparisons
  • Full policy code and configurations

Custom Mappings

Provide custom GOID/GUID mappings for complex scenarios:

{
  "mappings": {
    "services": [
      {
        "source": {"name": "OldServiceName"},
        "target": {"name": "NewServiceName"}
      }
    ],
    "policies": [
      {
        "source": {"guid": "source-guid"},
        "target": {"guid": "target-guid"}
      }
    ]
  }
}

Multiline Text Diff

The diff operation uses the multiline-text-diff extension for:

  • Policy XML comparison
  • Policy code comparison
  • Detailed field differences

Important Notes

  • Gateway Comparison: When using @gateway, a summary export is performed
  • Checksum Comparison: Primary comparison method for efficiency
  • Field-Level Details: Detailed comparison only when checksums differ
  • Automatic Sorting: Output bundles are automatically sorted
  • Dependency Tracking: ID mappings preserve entity relationships
  • Report Regeneration: Diff bundles can be regenerated from reports
  • Delete Safety: Deletions are excluded by default to prevent accidents

Performance Considerations

  • Gateway comparisons require network access and may be slow
  • Use bundle files for faster comparisons when possible
  • renewEntities option increases execution time significantly
  • Large configurations may generate large reports

Safety Best Practices

  1. Review diff reports before applying changes
  2. Test in non-production environments first
  3. Backup target before applying diff
  4. Use includeDeletes carefully - deletions are irreversible
  5. Validate ID mappings for cross-environment deployments
  6. Check diff report details for unexpected changes
  7. Use version control for diff reports and bundles

Related Commands

  • export: Export configurations for comparison
  • import: Apply difference bundles
  • combine: Merge difference bundles
  • renew: Refresh entity details

Troubleshooting

Gateway Details Missing

error: gateway details are missing

Solution: Configure the gateway profile in graphman.configuration.

Checksum Undefined

info: ignoring Entity, target entity checksum is undefined

Solution: Ensure target bundle includes checksums (use recent export).

Errors During Renewal

error: errors encountered while renewing the entities

Solution: Check gateway connectivity and permissions. Verify entity existence.

Workflow Example

Complete environment synchronization workflow:

#!/bin/bash
# Step 1: Generate diff
graphman diff --input-source @dev --input-target @prod \
  --output sync.json \
  --options.renewEntities true

# Step 2: Review diff report
echo "Review the diff report:"
jq '.diffs | keys' sync.diff-report.json

# Step 3: Backup production
graphman export --gateway prod --output backup-$(date +%Y%m%d).json

# Step 4: Apply changes
graphman import --input sync.json \
  --input-id-mappings sync.id-mappings.json \
  --gateway prod \
  --options.comment "Sync from dev $(date +%Y-%m-%d)"

echo "Synchronization complete"

Clone this wiki locally