How to use CMDBTransformUtil in Transform Maps where it requires a Dependency?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎02-06-2018 06:39 PM
Good day all,
I would like to find out if anyone used the CMDBTransformUtil in transform maps for sub-components?
Apply CI Identification and Reconciliation to Import Sets
NOTE: I've set up the identification rules, precedence etc, accordingly.
This works great for Parent components like Servers etc. However, trying to make use of this for components like IP Address, I get the "MISSING_DEPENDENCY" error
How do I set up the transform map to provide the relationship/"relations"?
I have a transform map where i set all the mappings for 1 table
The payload that gets generated look like this:
{
"items":[
{
"className":"cmdb_ci_ip_address",
"values":{
"nic":"3f493de24f8c5300c512ecfe0310c72b",
"name":"10.52.34.58",
"correlation_id":"ab3c16636f8593c4f412e79c6711a95b",
"ip_address":"10.52.34.58"
},
"lookup":[],
"related":[]
}
],
"relations":[]
}
However, it is expecting the payload to contain the dependencies, i.e. something like this (even though the IP is associated with the NIC and not the host directly):
{
"items":[
{
"className":"cmdb_ci_ip_address",
"lookup":[],
"values":{
"nic":"3f493de24f8c5300c512ecfe0310c72b",
"discovery_source":"MySource",
"correlation_id":"ab3c16636f8593c4f412e79c6711a95b",
"ip_address":"10.52.34.58"
}
},
{
"className":"cmdb_ci_solaris_server",
"lookup":[],
"values":{
"correlation_id":"ab3c16636f8593c4f412e79c6711a95b",
"discovery_source":"MySource"
}
}
],
"relations":[
{
"type":"Owns::Owned by",
"parent":1,
"child":0
}
]
}
In summary: How does one set up the transform maps to ensure it generates the required "parent", "child" and "relations" values when using CMDBTransformUtil
I've tried to map it in the transform:
But that just generates errors like:
Invalid map target parent does not exist in table cmdb_ci_ip_address
Invalid map target child does not exist in table cmdb_ci_ip_address

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎02-24-2019 03:54 PM
Yeah I recently needed to import some CI's via import sets and decided to use the createOrUpdateCIscript to do this. I notice it is just a wrapper for SNC.IdentificationEngineScriptableApi.createOrUpdateCI().
I had the exact same issue as you as there is no obvious way to include relationships using purely CMDBTransformUtil.
So I updated the CMDBTransformUtil class to be capable of adding relationships.
These are the changes I made:
Add the last line below to the initialize function.
initialize: function() {
this.json = new JSON();
this.dataSource = 'ImportSet';
this.transformEntryTable = 'sys_transform_entry';
this.cmdbTransformStatsTable = 'cmdb_import_set_run';
this.CmdbAPI = SNC.IdentificationEngineScriptableApi;
this.CmdbUtil = SNC.CMDBUtil;
this.outputPayload = '';
this.outputRecordSysId = '';
this.error = '';
this.transformResult = 'e';
this.relationships = []; //Add this
},
Add the below function to the class.
/**New function to store some relationships to build later in our payload
*@param {string} relation_class The ci class you are going to relate to
*@param {string} relation_sys_id The sys_id of the ci instance you are going to relate to
*@param {string} relation_type The CI relationship type you want to use to represent the relation
*@param {boolean} im_the_parent Indicates if the CI we are building a payload for is the parent in this relationsip ie. the relationship direction
*/
addRelationship: function(relation_class, relation_sys_id, relation_type, im_the_parent){//ie'cmdb_ci_solaris_server', sys_id, 'Instantiates::Instantiated by', false
this.relationships.push({
relation_class: relation_class,
relation_sys_id: relation_sys_id.toString(),//just in case we sent a glideelement
relation_type: relation_type,
im_the_parent: im_the_parent
});
},
Change the buildInputPayload function to include building the relationships as below.
// Builds inputPayload for given source record and transform map
buildInputPayload: function(source, map, log) {
var inputPayload = {};
inputPayload.items = [];
var item = {};
item.className = map.target_table;
var values = this.getTransformValues(source, map, log);
var isEmpty = !Object.keys(values).length;
if (!this.hasError() && !isEmpty) {
item.values = values;
inputPayload.items.push(item);
}
//Add our code for adding relationships now.
if(this.relationships.length>0){
inputPayload.relations = [];
for(var i in this.relationships){
var offset = parseInt(i)+1;
var rel = this.relationships[i];
//Add the relation to our items array
inputPayload.items.push({
"className": rel.relation_class,
"values": {
"sys_id": rel.relation_sys_id
}
});
inputPayload.relations.push({
"parent": rel.im_the_parent ? "0" : offset.toString(),
"child": !rel.im_the_parent ? "0" : offset.toString(),
"type": rel.relation_type
});
}
}
return inputPayload;
},
So then when I Import dependant classes I can use the following example code in my OnBefore script in the transform map:
var cmdbUtil = new CMDBTransformUtil();
cmdbUtil.setDataSource('ImportSet');
//Go find if we have a parent we can relate to, since it's mandatory for this class
var parent = new GlideRecord('cmdb_ci_solaris_server');
parent.addQuery('host_name',host);
parent.query();
if(parent.next()) { //If we found a valid parent, continue...
//Add our relationship which will be added to the payload later in identifyAndReconcile() function call
cmdbUtil.addRelationship('cmdb_ci_solaris_server', parent.sys_id.toString(), 'Instantiates::Instantiated by', false);
//Add more than 1 relationship if you want
cmdbUtil.addRelationship('cmdb_ci_solaris_server', parent.sys_id.toString(), 'Owns::Owned by', false);
cmdbUtil.identifyAndReconcile(source, map, log);
I also had an issue where I actually have more than 1 transform map for my import set, and that does not play nicely with the CMDBTransformUtil class, so I had to make the following adjustment to fix that:
// Get values that need to be transformed for given source record
getTransformValues: function(source, map, log) {
var values = {};
var td = GlideTableDescriptor.get(map.target_table);
var entryGr = new GlideRecord(this.transformEntryTable);
entryGr.addQuery('source_table', map.source_table);
entryGr.addQuery('map', map.sys_id); //If you have more than 1 transform map for a table then this will cause issues if this line is not present.
entryGr.query();
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎08-27-2019 01:51 PM
Thanks for posting this, I found very useful. However, I am having an issue when I try to add more than one relationship. I get a MULTIPLE_DEPENDENCIES error. Were you able to add multiple relationships successfully?