Name
global.CMDBTransformUtil
Description
CMDB Utility class for calling Identification and Reconciliation API within transform maps
Script
var CMDBTransformUtil = Class.create();
CMDBTransformUtil.prototype = {
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.options = {};
this.inputPayload = {};
this.isPayloadProvided = false;
},
// Identify and Reconcile given source record and transform map
identifyAndReconcile: function(source, map, log) {
if(!this.isPayloadProvided) {
this.inputPayload = this.buildInputPayload(source, map, log);
}
this.identifyAndReconcileFromPayload(this.inputPayload, map, log);
},
// Enhanced Identify and Reconcile given source record and transform map
identifyAndReconcileEnhanced: function(source, map, log) {
if(!this.isPayloadProvided) {
this.inputPayload = this.buildInputPayload(source, map, log);
}
this.identifyAndReconcileFromPayloadEnhanced(this.inputPayload, map, log);
},
// Identify and Reconcile given an input payload and transform map
identifyAndReconcileFromPayload: function(inputPayload, map, log) {
if (!this.hasError() && inputPayload.items.length !== 0) {
this.outputPayload = this.CmdbAPI.createOrUpdateCI(this.dataSource, this.json.encode(inputPayload));
log.info("Identification and Reconciliation Result: " + this.outputPayload);
this.setTransformResult();
}
this._updateTransformStats(map, log);
},
// Enhanced Identify and Reconcile given an input payload and transform map
identifyAndReconcileFromPayloadEnhanced: function(inputPayload, map, log) {
if (!this.hasError() && inputPayload.items.length !== 0) {
this.outputPayload = this.CmdbAPI.createOrUpdateCIEnhanced(this.dataSource, this.json.encode(inputPayload), this.options);
log.info("Identification and Reconciliation Result: " + this.outputPayload);
this.setTransformResult();
}
this._updateTransformStats(map, log);
},
// Update the transform result
setTransformResult: function() {
if (!gs.nil(this.outputPayload)) {
var output = this.json.decode(this.outputPayload);
var item = output.items[0];
if (item && item.sysId && item.sysId !== 'Unknown') {
this.outputRecordSysId = item.sysId;
if (item.operation == 'INSERT')
this.transformResult = 'i';
else if (item.operation == 'UPDATE' || item.operation == 'UPDATE_WITH_UPGRADE' || item.operation == 'UPDATE_WITH_DOWNGRADE' || item.operation == 'UPDATE_WITH_SWITCH')
this.transformResult = 'u';
else if (item.operation == 'NO_CHANGE')
this.transformResult = 'g';
}
else
this.error = 'createOrUpdateCI failed.';
}
},
// Builds inputPayload for given source record and transform map
buildInputPayload: function(source, map, log) {
var inputPayload = {};
inputPayload.items = [];
var item = {};
var values = this.getTransformValues(source, map, log);
var recordClassName = this.getClassNameFromMappedValues(values);
item.className = recordClassName === null ? map.target_table : recordClassName;
//remove sys_class_name from the list of attributes in the payload
if (recordClassName !== null) {
delete values['sys_class_name'];
}
var isEmpty = !Object.keys(values).length;
if (!this.hasError() && !isEmpty) {
item.values = values;
inputPayload.items.push(item);
}
return inputPayload;
},
// Get values that need to be transformed for given source record
getTransformValues: function(source, map, log) {
var values = {};
var entryGr = new GlideRecord(this.transformEntryTable);
entryGr.addQuery('map', map.sys_id);
entryGr.addQuery('source_table', map.source_table);
entryGr.query();
while(entryGr.next()) {
var targetField = entryGr.getValue('target_field');
var targetValue = "";
if (entryGr.getValue('use_source_script') == true) {
var evaluator = new GlideScopedEvaluator();
evaluator.putVariable('answer', null);
evaluator.putVariable('source', source);
evaluator.putVariable('error', false);
evaluator.putVariable('error_message', '');
evaluator.evaluateScript(entryGr, 'source_script');
if (evaluator.getVariable('error') == true) {
this.error = 'Error executing source script to populate target field ' + targetField;
var errMsg = evaluator.getVariable('error_message');
if (!gs.nil(errMsg))
this.error += ' : ' + errMsg;
log.error(this.error);
values = {};
return values;
}
targetValue = "" + evaluator.getVariable('answer');
} else {
var sourceField = entryGr.getValue('source_field');
targetValue = source.getValue(sourceField);
if (targetValue == null)
targetValue = "";
}
// Choose the target table from the field map to determine reference and mapping column
// Example, if field map has cmdb_ci_server and transform map has cmdb_ci_computer and field is host_name
// check if host_name is valid field on cmdb_ci_server not from cmdb_ci_computer
var targetTable = entryGr.getValue('target_table');
var td = GlideTableDescriptor.get(targetTable);
var ed = td.getElementDescriptor(targetField);
// ed can be null if field is missing on the table and can throw null pointer exception for ed.isReference()
// On null pointer exception,IRE will not be called and platform transformation will be applied
if (!gs.nil(targetValue) && !gs.nil(ed) && ed.isReference()) {
var result = this.CmdbUtil.resolveReferenceField(entryGr, targetValue, this.dataSource, false);
var retObj = JSON.parse(result);
if (retObj && !gs.nil(retObj.error)) {
if (retObj.error == "reject") {
log.info("Skipping record as the value for reference field " + targetField + " could not be resolved.");
this.transformResult = 's';
}
else {
log.error(retObj.error);
this.error = retObj.error;
}
values = {};
return values;
}
else if (retObj && !gs.nil(retObj.reference_field_value))
values[targetField] = retObj.reference_field_value;
} else
values[targetField] = targetValue;
}
return values;
},
getOutputPayload: function() {
return this.outputPayload;
},
hasError: function() {
return !gs.nil(this.error);
},
getError: function() {
return this.error;
},
getOutputRecordSysId: function() {
return this.outputRecordSysId;
},
setDataSource: function(ds) {
this.dataSource = ds;
},
setOptions: function(options) {
this.options = options;
},
getPayload: function(source, map, log) {
this.inputPayload = this.buildInputPayload(source, map, log);
return this.inputPayload;
},
setPayload: function(payload) {
this.inputPayload = payload;
this.isPayloadProvided = true;
},
// log current stats about the import set run
logTransformStats: function(log, statGr) {
if (!statGr) {
if (typeof import_set !== "undefined" && import_set !== null) {
statGr = new GlideRecord(this.cmdbTransformStatsTable);
statGr.addQuery('set', import_set.sys_id);
statGr.query();
if (!statGr.next())
return;
}
else
return;
}
var total = statGr.getValue('total');
var inserts = statGr.getValue('inserts');
var updates = statGr.getValue('updates');
var ignored = statGr.getValue('ignored');
var skipped = statGr.getValue('skipped');
var errors = statGr.getValue('errors');
log.info("CMDBTransformUtil Transform stats:total " + total + ", inserts " + inserts
+ ", updates " + updates + ", ignored " + ignored + ", skipped " + skipped
+ ", errors " + errors);
},
_updateTransformStats: function(map, log) {
if (typeof import_set !== "undefined" && import_set !== null) {
var statGr = new GlideRecord(this.cmdbTransformStatsTable);
statGr.addQuery('set', import_set.sys_id);
statGr.query();
if (statGr.next()) {
var total = statGr.getValue('total');
statGr.setValue('total' , ++total);
var incrField = 'errors';
switch (this.transformResult) {
case 'i': incrField = 'inserts'; break;
case 'u': incrField = 'updates'; break;
case 'g': incrField = 'ignored'; break;
case 's': incrField = 'skipped'; break;
}
var statValue = statGr.getValue(incrField);
statGr.setValue(incrField , ++statValue);
statGr.update();
} else {
statGr.initialize();
statGr.setValue('set', import_set.sys_id);
statGr.setValue('sys_transform_map', map.sys_id);
statGr.setValue('total' , '1');
statGr.setValue('inserts', this.transformResult == 'i' ? '1': '0');
statGr.setValue('updates', this.transformResult == 'u' ? '1': '0');
statGr.setValue('ignored', this.transformResult == 'g' ? '1': '0');
statGr.setValue('skipped', this.transformResult == 's' ? '1': '0');
statGr.setValue('errors', this.transformResult == 'e' ? '1': '0');
statGr.insert();
}
}
},
getClassNameFromMappedValues : function(values) {
if (values.hasOwnProperty('sys_class_name')) {
return values['sys_class_name'];
}
return null;
},
type: 'CMDBTransformUtil'
};
Sys ID
86665601531002007c949096a11c0858