ServiceNow Adapter Customization Cookbook
The behavior of the ServiceNow adapter can be customized with scripts attached to the ServiceNow Transform Maps. Following are some typical scenarios and example scripts to handle those scenarios.
Scenario 1: Handling delete events
When an entity or association is deleted in BarometerIT, it results in an Import Set row being created in ServiceNow with the barometerdeleted
flag set to true
. The following script (set on the Transform Map's onBefore
event) would set an active flag in the target record when the delete event is received:
|
NOTE
It is possible to actually delete the ServiceNow target record from the script. However, this is not recommended for two reasons: (1) It makes it harder to audit the process and recover from user errors such as entities being accidentally deleted, and (2) ServiceNow will return an error code from the REST API, which makes it look like (from the barometerIT perspective) that the ServiceNow operation failed.
Scenario 2: Mapping values in barometerIT to different values in ServiceNow
Sometimes an integration should transform values in barometerIT to different values in ServiceNow. Following is a script (set on the Transform Map's onBefore
event) that maps lifecycle state values:
(function runTransformScript(source, map, log, target
/*undefined onStart*/
) {
var incomingLifecycle = source.u_lifecyclestate;
log.info(
"lifecycle state="
+ incomingLifecycle);
if
(incomingLifecycle ==
"Stable"
|| incomingLifecycle ==
"Enhancing"
) {
target.u_barometer_lifecycle =
"Active"
;
}
else
if
(incomingLifecycle ==
"Retired"
) {
target.u_barometer_lifecycle =
"Inactive"
;
}
})(source, map, log, target);
Scenario 3: Mapping relationships in barometerIT to relationships in ServiceNow
Here is an example of a script (set on the Transform Map's onBefore
event) that would map relationships where the relationshipType is "HAS_CHILD" to a relationship in ServiceNow of type "Contains::Contained by":
(function runTransformScript(source, map, log, target
/*undefined onStart*/
) {
if
(source.u_barometerdeleted ==
"true"
) {
log.info(
"association was deleted"
);
//handle deletion here
}
else
if
(source.u_relationshiptype ==
"HAS_CHILD"
) {
var gr =
new
GlideRecord(
'cmdb_rel_type'
);
gr.addQuery(
'name'
,
"Contains::Contained by"
);
gr.query();
while
(gr.next()) {
target.setValue(
'type'
, gr.sys_id);
}
}
})(source, map, log, target);
Scenario 4: Conditional Mapping to different tables in ServiceNow
A typical scenario is when records from the same catalog in barometerIT should be mapped to different tables in ServiceNow, depending on a particular value. In this example, Systems with type = "Custom Application" or "Packaged Application" should go to the Business Application table, whereas Systems with type = "Web Service" should go to the Web Service table. To achieve this, create one import set for Systems (u_barometer_system_import), and two transform maps, each mapping from the import set to one of the two destination tables. This script (set on the Business Application Transform Map's onBefore
event - there would be a similar script on the other transform amp) would accept only Systems with the desired types:
(function runTransformScript(source, map, log, target
/*undefined onStart*/
) {
var type = source.u_systemtype;
if
(action ==
'insert'
) {
log.info(
'insert'
);
if
(type !=
'Custom Application'
&&
type !=
'Packaged Application'
) {
ignore =
true
;
}
}
else
if
(action ==
'update'
) {
log.info(
"update to an existing record, don't ignore"
);
log.info(target.sys_id);
}
else
{
//this shouldn't happen, since the only valid values are insert and update
ignore =
true
;
//but ignore just to be on the safe side
}
})(source, map, log, target);
Scenario 5: Conditional value in ServiceNow
A True/False value in ServiceNow should be set depending on the value of a (non-boolean) field in barometerIT. This script (mapping to a column in ServiceNow that should be True if Lifecycle State is Active, and False otherwise) is on a Field Map to the True/False field:
|
Scenario 6: A relationship in barometerIT is modeled as a reference in ServiceNow
ServiceNow has a field type called "Reference Field" which stores a reference to a row in another table. Sometimes it might make sense to map a relationship in barometerIT to a reference field in ServiceNow.
Example: in barometerIT, Systems have relationships to People. The types of relationships allowed are stored in the configurable "System Contact Types" option list. It's conventional in ServiceNow to model these relationships as Reference Fields. This example shows how to do this.
In the ServiceNow Adapter configuration screen, make sure the System-Person relationship type is selected. This will cause the adapter to push any changes to System-Person relationships to the barometer_system_person_import import set. In the ServiceNow Import Set, make sure at least the following fields are being imported: source_bn, target_name, qualifier, barometerdeleted.
Next, create a ServiceNow transform map from barometer_system_person_import to the table in ServiceNow storing applications (for example cmdb_ci_appl). Map the field u_source_bn to the field in the application table containing the Barometer Number (for example cmdb_ci_appl). Set coalesce equal to true.
Finally, create a transform script for the onBefore event that will look up the person in the appropriate ServiceNow table and put it in the reference field. See below for an example that maps four different types of System Contacts to four different reference fields in ServiceNow.
NOTE
barometerIT allows multiple relationships of each type. Using the same example, there could be more than one Product Manager. Since the adapter is event-based, if there are two or more Product Managers selected, they will each be pushed to the barometer_system_person_import import set separately. This script will simply set the reference fields to be the last corresponding event received by the adapter.
var lookupUser = function(name, barometerdeleted) {
if
(barometerdeleted)
return
''
;
var gr =
new
GlideRecord(
'sys_user'
);
gr.addQuery(
'name'
, name);
gr.query();
if
(gr.next()) {
return
gr.sys_id;
}
};
(function runTransformScript(source, map, log, target
/*undefined onStart*/
) {
var barometerdeleted = source.u_barometerdeleted;
var name = source.u_target_name;
var user = lookupUser(name, barometerdeleted);
var qualifier = source.u_qualifier;
log.info(
'qualifier ['
+ qualifier +
']'
);
log.info(
'user ['
+ user +
']'
);
if
(qualifier ==
'Product Manager'
) {
target.managed_by = user;
}
else
if
(qualifier ==
'Business Owner'
) {
target.owned_by = user;
}
else
if
(qualifier ==
'Technical Support'
) {
target.supported_by = user;
}
else
if
(qualifier ==
'IT Owner'
) {
target.u_it_owner = user;
}
})(source, map, log, target);