Skip to content
lewisgf edited this page Apr 25, 2015 · 2 revisions

NAME

ServiceNow::SOAP - Second Generation SOAP API for ServiceNow

SYNOPSIS

# return a reference to a session object
my $sn = ServiceNow("https://mycompany.service-now.com", $username, $password);
# or
my $sn = ServiceNow("mycompany", $username, $password);

# return a reference to a table object
my $table = $sn->table($tablename);

# count records
my $count = $table->count(%parameters);
# or
my $count = $table->count($encoded_query);

# return a list of sys_ids
my @keys = $table->getKeys(%parameters);
# or
my @keys = $table->getKeys($encoded_query);

# return a reference to a hash
my $rec = $table->get(sys_id => $sys_id);
# or
my $rec = $table->get($sys_id);

# return a list of references to hashes
my @recs = $table->getRecords(%parameters);

# call getKeys and return a query object
my $query = $table->query(%parameters);
# or
my $query = $table->query($encoded_query);

# convert a list of keys into a query object
my $query = $table->asQuery(@keys);

# fetch the next chunk of records
my @recs = $query->fetch($numrecs);

# retrieve a record based on unique key other than sys_id
my $rec = $table->getRecord($name => $value);

# insert a record
$table->insert(%parameters);

# update a record
$table->update(%parameters);

EXAMPLES

use ServiceNow::SOAP;

my $sn = ServiceNow("https://mycompany.service-now.com", "soap.perl", $password);
# or
my $sn = ServiceNow("mycompany", "soap.perl", $password);

my $cmdb_ci_computer = $sn->table("cmdb_ci_computer");

# retrieve a small number of records     
my @recs = $cmdb_ci_computer->getRecords(
    sys_class_name => "cmdb_ci_computer", 
    operational_status => 1,
    __order_by => "name", 
    __limit => 500);
foreach my $rec (@recs) {
    print $rec->{name}, "\n";
}

# count records
my $count = $cmdb_ci_computer->count(
    sys_class_name => "cmdb_ci_computer",
    operational_status => 1);

# retrieve records in chunks 
my @keys = $cmdb_ci_computer->getKeys(
    sys_class_name => "cmdb_ci_computer",
    operational_status => 1,
    __order_by => "name");
my $qry = $cmdb_ci_computer->asQuery(@keys);    
while (@recs = $qry->fetch(200)) {
    foreach my $rec (@recs) {
        print $rec->{name}, "\n";
    }
}

# retrieve all the records in a large table 
my $recs = $cmdb_ci_computer->query()->fetchAll();

# insert a record
my $incident = $sn->table("incident");
my $sys_id = $incident->insert(
    assignment_group => "Network Support",
    short_description => $short_description,
    impact => 2);

# retrieve a single record based on sys_id
my $rec = $incident->get(sys_id => $sys_id);
print "number=", $rec->{number}, "\n";

# retrieve a single record based on number
my $rec = $incident->getRecord(number => $number);
print "sys_id=", $rec->{sys_id}, "\n";

# update a record
$incident->update(
    sys_id => $sys_id,
    assigned_to => "Fred Luddy",
    incident_state => 2);

DESCRIPTION

Introduction

This module is a second generation Perl API for ServiceNow. It incorporates what I have learned over several years of accessing ServiceNow via the Web Services API, and also what I have learned by studying the ServiceNow::Simple API written by Greg George.

Goals

The goals in implementing this Perl module were as follows.

  • Provide an easy to use and performative method for querying large tables. Please refer to examples below of Query objects.

  • Make it even more simple. Eliminate unnecessary curly brackets. The core functions should adhere as closely as possible to ServiceNow's wiki documentation for the Direct Web Service API (http://wiki.servicenow.com/index.php?title=SOAP_Direct_Web_Service_API). Extended functionality is placed separate functions.

  • Leverage lists. If you are using the Web Services API to access ServiceNow, you will frequently find yourself dealing with lists of sys_ids. Since Perl is particularly good at dealing with lists, we should surface that opportunity. The getKeys method here returns a list of keys (not a comma delimited string). Methods are provided which allow a list of records to be easily retrieved based on a list of keys.

    By the way, throughout this document I will frequently use key as a synonym for sys_id.

  • Make the functions intelligent where it is easy to do so.

    In this example the first syntax can be distinguished from the second because we assume that a single parameter must be an encoded query.

    @recs = $server_tbl->getRecord("operational_status=1^virtual=false");
    @recs = $server_tbl->getRecord(operational_status => 1, virtual => "false");
  • Provide good documentation with lots of examples. You are reading it now. I hope you agree that this goal has been met.

Querying large tables

ServiceNow provides two mechanisms to query large tables using the Direct Web Services API.

  1. First row last row windowing. Specify the __first_row and __last_row parameter in each call to getRecords and gradually work your way through the table.

  2. Get a complete list of keys up front by calling getKeys. Then read the records in chunks by passing in a slice of that array with each call to getRecords.

There are several reasons to prefer the 2nd approach.

  • The performance of the first method degrades with the size of the table. As __first_row gets larger, each call to getRecords takes longer. For medium sized tables the first method is slower than the second. For very large tables the first method is completely unusable.

  • The first method can sometimes cause existing records to be skipped if new records are inserted while the retrieval process is running (e.g. if Discovery is running).

  • Given the inherent limitations of SOAP Web Services, it is a bad idea in general to try to read a lot of data without having some idea of how long it might take. If you are going to make a Web Service query up front to count the number of records, you might as well use that call instead to return a list of the keys.

This module provides support for the second method through Query objects. A Query object is essentially a list of keys with a pointer to keep track of the current position.

Session Methods

new

Description

Used to obtain a reference to an Session object. The Session object essentially holds the URL and connection credentials for your ServiceNow instance. The first argument is the URL or instance name. The second argument is the user name. The third argument is the password.

The fourth (optional) argument to this method is a trace level which can be helpful for debugging. Sometimes, when you are developing a new script, it seems to hang at a certain point, and you just want to know what it is doing. Set the trace level to 1 to enable tracing messages for SOAP calls. Set the trace level to 2 to dump the complete XML of all SOAP results.

Syntax

my $sn = ServiceNow($instancename, $username, $password);
my $sn = ServiceNow($instanceurl, $username, $password);
my $sn = ServiceNow($instancename, $username, $password, $tracelevel);

Examples

The following two statements are equivalent.

my $sn = ServiceNow("https://mycompanydev.service-now.com", "soap.perl", $password);
my $sn = ServiceNow("mycompanydev", "soap.perl", $password);

Tracing of Web Services calls can be enabled by passing in a fourth parameter.

my $sn = ServiceNow("mycompanydev", "soap.perl", $password, 1);

Usage Notes

If you are using this API for the first time, then you may want to verify connectivity by using an admin account in a sub-production instance.

my $sn = ServiceNow("mycompanydev", "admin", $adminpass);

However, once connectivity has been verified you should switch to a dedicated application account which has been granted the necessary access controls. For example, if you are not performing updates, you might create an account named soap.perl which only has soap_query role.

my $sn = ServiceNow($instance, "soap.perl", $password);

For security reasons you should never use an admin account to access a production ServiceNow instance via the Web Services API.

For security reasons you should never embed a password in a perl script. Instead store the password in a configuration file where it can be easily updated when the password is rotated.

table

Description

Used to obtain a reference to a Table object. The Table object is subsequently used for "TABLE METHODS" described below.

Syntax

my $table = $sn->table($tablename);

Example

my $cmdb_ci_computer = $sn->table("cmdb_ci_computer");

saveSession

Description

Saves the session information to a file. See "loadSession" below.

Syntax

$sn->saveSession($filename);

loadSession

Description

Loads the session information from a file. This may be required if you are running the same perl script over and over (each time in a separate process) and you do not want to establish a separate ServiceNow session each time the script is run.

Syntax

$sn->loadSession($filename);

Table Methods

Refer to "table" above for instructions on obtaining a reference to a Table object.

get

Description

Retrieves a single record. The result is returned as a reference to a hash.

If no matching record is found then null is returned.

For additional information refer to the ServiceNow documentation on the get Direct SOAP API method at http://wiki.servicenow.com/index.php?title=SOAP_Direct_Web_Service_API#get

Syntax

$rec = $table->get(sys_id => $sys_id);
$rec = $table->get($sys_id);

Example

my $rec = $table->get($sys_id);
print $rec->{name};

getKeys

Description

Returns a list of keys. Note that this method returns a list of keys, NOT a comma delimited list.

For additional information on available parameters refer to the ServiceNow documentation on the getKeys Direct SOAP API method at http://wiki.servicenow.com/index.php?title=SOAP_Direct_Web_Service_API#getKeys

Syntax

@keys = $table->getKeys(%parameters);
@keys = $table->getKeys($encoded_query);

Examples

my $cmdb_ci_computer = $sn->table("cmdb_ci_computer");

my @keys = $cmdb_ci_computer->getKeys(operational_status => 1, virtual => "false");
# or
my @keys = $cmdb_ci_computer->getKeys("operational_status=1^virtual=false");

getRecords

Description

Returns a list of records. Actually, it returns a list of hash references.

For additional information on available parameters refer to the ServiceNow documentation on the getRecords Direct SOAP API method at http://wiki.servicenow.com/index.php?title=SOAP_Direct_Web_Service_API#getRecords

Important Note: This rmethod will return at most 250 records, unless you specify a __limit parameter as documented here: http://wiki.servicenow.com/index.php?title=Direct_Web_Services

Syntax

@recs = $table->getRecords(%parameters);
@recs = $table->getRecords($encoded_query);

Example

my $sys_user_group = $sn->table("sys_user_group");
my @grps = $sys_user_group->getRecords(
    active => true, __limit => 500, __order_by => "name");
foreach my $grp (@grps) {
    print $grp->{name}, "\n";
}

getRecord

Description

Returns a single qualifying records. Return null if there are no qualifying records. Die if more than one record is returned.

Syntax

$rec = $table->getRecord(%parameters);
$rec = $table->getRecord($encoded_query);

Example

my $number = "CHG12345";
my $chgRec = $sn->table("change_request")->getRecord(number => $number);
if ($chgRec) {
    print "Short description = ", $chgRec->{short_description}, "\n";
}
else {
    print "$number not found\n";
}

The following two examples are equivalent.

my $rec = $table->getRecord(%parameters);

my @recs = $table->getRecords(%parameters);
die "Too many records" if scalar(@recs) > 1;
my $rec = $recs[0];

count

Description

Counts the number of records in a table, or the number of records that match a set of parameters.

This method requres installation of the Aggregate Web Service plugin.

Syntax

my $count = $table->count();
my $count = $table->count(%parameters);
my $count = $table->count($encoded_query);

Examples

Count the total number of users:

my $count = $sys_user->count();

Count the number of active users:

my $count = $sys_user->count(active => true);

insert

Description

Inserts a record.

Syntax

my $sys_id = $table->insert(%values);
my %result = $table->insert(%values);

Examples

my $incident = $sn->table("incident");

my $sys_id = $incident->insert(
    short_description => $short_description,
    assignment_group => "Network Support",
    impact => 3);
print "sys_id=", $sys_id, "\n";

my %result = $incident->insert(
    short_description => $short_description,
    assignment_group => "Network Support",
    impact => 3);
print "number=", $result{number}, "\n";
print "sys_id=", $result{sys_id}, "\n";

my %rec;
$rec{short_description} = $short_description;
$rec{assignment_group} = "Network Support";
$rec{impact} = 3;
my $sys_id = $incident->insert(%rec);

Usage Notes

For reference fields (e.g. assignment_group, assigned_to) you may pass in either a sys_id or a display value.

update

Description

Update a record.

Syntax

$table->update(%parameters);
$table->update($sys_id, %parameters);

Note: If the first syntax is used, then the sys_id must be included among the parameters. If the second syntax is used, then the sys_id must be the first parameter.

Examples

$incident->update(
    sys_id => $sys_id, 
    assigned_to => "5137153cc611227c000bbd1bd8cd2005",
    incient_state => 2);
    
$incident->update(
    sys_id => $sys_id, 
    assigned_to => "Fred Luddy", 
    incident_state => 2);

$incident->update($sys_id, 
    assigned_to => "Fred Luddy", 
    incident_state => 2);

Usage Notes

For reference fields (e.g. assignment_group, assigned_to) you may pass in either a sys_id or a display value.

deleteRecord

Description

Delete a record.

Syntax

$table->deleteRecord(sys_id => $sys_id);
$table->deleteRecord($sys_id);

query

Description

Syntax

Example

asQuery

Description

Creates a new Query object from a list of keys. Note that since a Query object is essentially just a list of key, this method simply makes a copy of the list. Each item in the list must be a sys_id for the respective table.

Syntax

my $query = $table->asQuery(@keys);

Example

my $sys_user = $sn->table("sys_user");
my @keys = $sys_user->getKeys();
my $query = $sys_user->asQuery(@keys);

attachFile

Description

If you are using Perl to create incident tickets, then you may have a requirement to attach files to those tickets.

This function requires write access to the ecc_queue table in ServiceNow.

When you attach a file to a ServiceNow record, you can specify an attachment name which is different from the actual file name. If no attachment name is specified, this function will assume that the attachment name is the same as the file name.

You will need to specify a MIME type. If no type is specified, this function will use a default type of "text/plain" For a list of MIME types, refer to http://en.wikipedia.org/wiki/Internet_media_type.

Syntax

$table->attachFile($sys_id, $filename, $attachment_name, $mime_type);

Example

$incident->attachFile($sys_id, "screenshot.png", "", "image/png");

getVariables

Description

This function returns a list of the variables attached to a Requested Item (RITM).

Note: This function currently works only for the sc_req_item table.

Each item in the list is a reference to a hash. Each hash contains the following four fields:

  • name - Name of the variable.

  • question - The question text.

  • value - Value of the question response. If the variable is a reference, then value will contain a sys_id.

  • order - Order (useful for sorting).

Syntax

$sc_req_item = $sn->table("sc_req_item");
@vars = $sc_req_item->getVariables($sys_id);

Example

my $sc_req_item = $sn->table("sc_req_item");
my $ritm = $sc_req_item->getRecord(number => $ritm_number);
my @vars = $sc_req_item->getVariables($ritm->{sys_id});
foreach my $var (@vars) {
    print "$var->{name} = $var->{value}\n";
}

setDV

Description

Used to enable (or disable) display values in queries. All subsequent calls to "get", "getRecords" or "getRecord" for this table will be affected. This function returns the modified Table object.

For additional information regarding display values refer to http://wiki.servicenow.com/index.php?title=Direct_Web_Services#Return_Display_Value_for_Reference_Variables

Syntax

$table->setDV("true");
$table->setDV("all");
$table->setDV(1);  # same as "all"
$table->setDv(0);  # restore default setting

Examples

my $sys_user_group = $session->table("sys_user_group")->setDV("true");
my $grp = $sys_user_group->getRecord(name => "Network Support");
print "manager=", $grp->{manager}, "\n";

my $sys_user_group = $session->table("sys_user_group")->setDV("all");
my $grp = $sys_user_group->getRecord(name => "Network Support");
print "manager=", $grp->{dv_manager}, "\n";

getSchemaFields

Description

Returns a hash of the fields in an sequence (complex type) from the WSDL. The hash key is the field name. The hash value is the field type.

Syntax

%fields = $table->getSchemaFields($type);

Example

my %fields = $sn->table("sys_user_group")->getSchemaFields("getRecordsResponse");
foreach my $name (sort keys %fields) {
    print "name=$name type=$fields{$name}\n";
}

Query Methods

Description

A Query object is essentially a list of keys (sys_ids) to a particular table, and a pointer to the current position in that list.

To construct a new Query object use the query or asQuery functions. query makes a Web Services call (getKeys) to retrieve a list of keys. asQuery simply converts an exsiting list of keys into a Query object.

Once constructed, the fetch and fetchAll functions can be used to get the actual records in chunks.

Example

This example illustrates the use of Query objects to traverse the cmdb_rel_ci table. The example involves two tables: cmdb_ci and cmdb_rel_ci.

my $cmdb_ci = $sn->table("cmdb_ci");
my $cmdb_rel_ci = $sn->table("cmdb_rel_ci");

We assume that $parentKey is the sys_id of a known configuration item. The object is to print a list of all other configuration items on which this item immediately depends. In otherwords, all items which are one level downstream.

First we query cmdb_rel_ci to retrieve a list of records for which this item is the parent. @relData is a list of cmdb_rel_ci records.

my @relData = $cmdb_rel_ci->query(parent => $parentKey)->fetchAll();

Next we extract the child field from each of these cmdb_rel_ci records to create a new list of sys_ids

my @childKeys = map { $_->{child} } @relData;

@childKeys now contains a lists of sys_ids for configuration items. We convert this list of keys into a query object and fetch athe records from the cmdb_ci table. If there are more than 200 records, fetchAll will loop internally until all records have been retrieved.

@childRecs = $cmdb_ci->asQuery(@childKeys)->fetchAll();
foreach my $childRec (@childRecs) {
    print $childRec->{name}, "\n";            
}

fetch

Description

Fetch the next chunk of records from a table. This function calls "getRecords" to retrieve the records. An optional parameter allows specification of the number of records to be retrieved. If not specified, then the number of records will be based on the default chunk size for this Query object. If there are no remaining records, then an empty list will be returned.

Syntax

my @recs = $query->fetch();
my @recs = $query->fetch($numrecs);

Example

This example prints the names of all active users. Each call to "getRecords" returns up to 100 users.

my $query = $sn->table("sys_user")->query(active => "true", __order_by => "name");
while (@recs = $query->fetch(100)) {
    foreach my $rec (@recs) {
        print $rec->{name}, "\n";
    }
}

fetchAll

Description

Fetch all the records in a Query by calling "fetch" repeatedly.

Syntax

my @recs = $query->fetchAll();
my @recs = $query->fetchAll($chunkSize);

Example

This example prints the names of all active users. Each call to "getRecords" returns up to 200 users since no chunk size was specified and the default is 200.

my @recs = $sn->table("sys_user")->query(active => "true", __order_by => "name")->fetchAll();
foreach my $rec (@recs) {
     print $rec->{name}, "\n";
}

AUTHOR

Giles Lewis

MAINTAINER

SEE ALSO

LICENSE

This program is free software; you can redistribute it and/or modify it under the terms of the the Artistic License (2.0). You may obtain a copy of the full license at:

http://www.perlfoundation.org/artistic_license_2_0

Any use, modification, and distribution of the Standard or Modified Versions is governed by this Artistic License. By using, modifying or distributing the Package, you accept this license. Do not use, modify, or distribute the Package, if you do not accept this license.

If your Modified Version has been derived from a Modified Version made by someone other than you, you are nevertheless required to ensure that your Modified Version complies with the requirements of this license.

This license does not grant you the right to use any trademark, service mark, tradename, or logo of the Copyright Holder.

This license includes the non-exclusive, worldwide, free-of-charge patent license to make, have made, use, offer to sell, sell, import and otherwise transfer the Package with respect to any patent claims licensable by the Copyright Holder that are necessarily infringed by the Package. If you institute patent litigation (including a cross-claim or counterclaim) against any party alleging that the Package constitutes direct or contributory patent infringement, then this Artistic License to you shall terminate on the date that such litigation is filed.

Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.