-
Notifications
You must be signed in to change notification settings - Fork 6
Diff Command
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.
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>,...]graphman diff --input-report <input-report-file>
[--output <output-file>]
[--options.<name> <value>,...]| 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 |
| Parameter | Description |
|---|---|
--input-report |
Previously generated diff report |
--output |
Output file for difference bundle |
| 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 |
Use the @ prefix to specify a gateway instead of a bundle file:
--input-source @dev
--input-target @prodThe gateway name must be configured in graphman.configuration.
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 |
- Entities are matched by their identifying attributes (name, GUID, etc.)
- Matched entities are compared using checksums
- If checksums differ, detailed field-by-field comparison is performed
- GOID/GUID mappings are tracked for cross-environment references
When comparing, three files are generated:
- Difference Bundle: Entities to apply to target
- Difference Report: Detailed analysis with field-level differences
- ID Mappings: GOID/GUID mappings between environments
Compare source and target bundle files:
graphman diff --input-source source.json --input-target target.json --output differences.jsonCompare two live Gateway environments:
graphman diff --input-source @dev --input-target @prod --output dev-to-prod.jsonCompare a bundle file against a live Gateway:
graphman diff --input-source release-bundle.json --input-target @prod --output changes.jsonGenerate diff including entities to delete:
graphman diff --input-source source.json --input-target target.json \
--output sync.json \
--options.includeDeletes trueGenerate diff with only new entities (no updates):
graphman diff --input-source source.json --input-target target.json \
--output new-only.json \
--options.includeUpdates falseUse 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.jsonFetch complete entity details from gateways:
graphman diff --input-source @dev --input-target @prod \
--output differences.json \
--options.renewEntities trueRegenerate difference bundle from a previous report:
graphman diff --input-report differences.diff-report.json --output new-diff.jsonSynchronize 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 prodTrack what changed between releases:
graphman diff --input-source release-v1.json --input-target release-v2.json \
--output changes-v1-to-v2.jsonPlan migration from old to new environment:
graphman diff --input-source @old-gateway --input-target @new-gateway \
--output migration-plan.json \
--options.renewEntities trueDetect 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.jsonSynchronize 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 prodIdentify 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 falseDeploy 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 prodThe 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"}
]
}
}Gateway Object IDs (GOIDs) are environment-specific. The diff operation tracks:
- Which entities have different GOIDs between environments
- Mappings needed for cross-references
Globally Unique Identifiers (GUIDs) may differ when entities are recreated. Mappings track:
- Entity GUID differences
- Required updates for policy references
# 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 prodWhen comparing gateways (not bundles), use renewEntities to fetch complete entity details:
graphman diff --input-source @dev --input-target @prod \
--output diff.json \
--options.renewEntities trueThis ensures:
- Complete entity details in the diff bundle
- Accurate field-level comparisons
- Full policy code and configurations
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"}
}
]
}
}The diff operation uses the multiline-text-diff extension for:
- Policy XML comparison
- Policy code comparison
- Detailed field differences
-
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
- Gateway comparisons require network access and may be slow
- Use bundle files for faster comparisons when possible
-
renewEntitiesoption increases execution time significantly - Large configurations may generate large reports
- Review diff reports before applying changes
- Test in non-production environments first
- Backup target before applying diff
- Use includeDeletes carefully - deletions are irreversible
- Validate ID mappings for cross-environment deployments
- Check diff report details for unexpected changes
- Use version control for diff reports and bundles
- export: Export configurations for comparison
- import: Apply difference bundles
- combine: Merge difference bundles
- renew: Refresh entity details
error: gateway details are missing
Solution: Configure the gateway profile in graphman.configuration.
info: ignoring Entity, target entity checksum is undefined
Solution: Ensure target bundle includes checksums (use recent export).
error: errors encountered while renewing the entities
Solution: Check gateway connectivity and permissions. Verify entity existence.
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"