ServiceNow-JSON/lib/ServiceNow/JSON.pm
package ServiceNow::JSON;
use Moose;
use REST::Client;
use MIME::Base64;
use JSON;
our $VERSION = 0.02;
has 'instance' => (
is => 'rw',
isa => 'Str',
);
has 'user' => (
is => 'rw',
isa => 'Str',
);
has 'password' => (
is => 'rw',
isa => 'Str',
);
has 'client' => (
is => 'rw',
isa => 'REST::Client',
);
has 'legacy' => (
is => 'rw',
isa => 'Any',
default => '0',
);
sub BUILD {
my ( $self ) = @_;
my $client = REST::Client->new();
$client->setHost( "https://" . $self->instance . ".service-now.com" );
$client->addHeader( 'Accept', '*/*' );
$client->addHeader( 'Authorization', 'Basic ' . encode_base64( $self->user . ":" . $self->password ) );
$self->client( $client );
}
sub _do_request {
my ( $self, $table, $action, $json ) = @_;
my $api_version = "JSONv2";
$api_version = "JSON" if $self->legacy;
my $url = $table . ".do?$api_version&$action";
if( $json ) {
$self->client->POST( $url, to_json( $json ), { "Content-type" => 'application/json' } );
if( $self->client->responseCode != 200 ) {
print STDERR "ERROR!\n";
print STDERR $self->client->responseContent();
} else {
my $data = from_json( $self->client->responseContent() );
if( exists( $data->{records} ) ) {
return $data->{records};
} else {
return $data;
}
}
} else {
$self->client->GET( $url );
if( $self->client->responseCode != 200 ) {
print STDERR "ERROR!\n";
print STDERR $self->client->responseContent();
} else {
if( $self->client->responseContent() ) {
my $data = from_json( $self->client->responseContent() );
if( exists( $data->{records} ) ) {
return $data->{records};
} else {
return $data;
}
} else {
return [];
}
}
}
}
sub getRecords {
my ( $self, $table, $search ) = @_;
my $search_str = $self->_build_search_string( $search );
return $self->_do_request( $table, "sysparm_action=getRecords$search_str" );
}
sub getKeys {
my ( $self, $table, $search ) = @_;
my $search_str = $self->_build_search_string( $search );
return $self->_do_request( $table, "sysparm_action=getKeys$search_str" );
}
sub get {
my ( $self, $table, $sysparm_id ) = @_;
return $self->_do_request( $table, "sysparm_action=get&sysparm_sys_id=$sysparm_id" );
}
sub _build_search_string {
my ( $self, $search ) = @_;
my $search_str = "";
if( scalar( keys( %{ $search } ) ) > 0 ) {
$search_str = "&sysparm_query=";
my @terms;
foreach my $key ( keys %{ $search } ) {
push( @terms, "$key=" . ( $search->{$key} ? $search->{$key} : "" ) );
}
$search_str .= join( '^', @terms );
}
return $search_str;
}
sub update {
my ( $self, $table, $search, $changes ) = @_;
my $search_str = $self->_build_search_string( $search );
return $self->_do_request( $table, "sysparm_action=update$search_str", $changes );
}
sub insert {
my ( $self, $table, $data ) = @_;
if( ref( $data ) eq "ARRAY" ) {
return $self->insertMultiple( $table, $data );
}
return $self->_do_request( $table, "sysparm_action=insert", $data );
}
sub insertMultiple {
my ( $self, $table, $data ) = @_;
if( ref( $data ) eq "ARRAY" ) {
$data = { records => $data };
}
return $self->_do_request( $table, "sysparm_action=insertMultiple", $data );
}
sub delete {
my ( $self, $table, $sysparm_id ) = @_;
return $self->_do_request( $table, "sysparm_action=deleteRecord&sysparm_sys_id=$sysparm_id" );
}
sub deleteMultiple {
my ( $self, $table, $search ) = @_;
my $search_str = $self->_build_search_string( $search );
return $self->_do_request( $table, "sysparm_action=deleteMultiple$search_str" );
}
=head1 NAME
ServiceNow::JSON - Absraction Library for ServiceNow JSON WebServices
=head1 DESCRIPTION
Allows for easy use of the ServiceNow JSON REST api from perl. Supports
both ServiceNow JSON and ServiceNow JSONv2 implementations.
=head1 SYNOPSIS
use ServiceNow::JSON;
my $sn = new ServiceNow::JSON( instance => "my_sn_instance",
user => "foo", password => "bar" );
my $record = $sn->get( "cmdb_ci_computer",
"72542ce36f015500e5f95afc5d3ee423" );
my $records = $sn->getRecords( "cmdb_ci_computer",
{ serial_number => '1234567' } );
my $keys = $sn->getKeys( "cmdb_ci_computer",
{ active => "true" } );
my $update = $sn->update( "cmdb_ci_computer",
{ sys_id => '0014eca36f015500e5f95afc5d3ee4af' },
{ cpu_name => "kevin_test_another" } );
my $insert = $sn->insert( "cmdb_ci_computer",
{ serial_number => "1234567" } );
my $multi_insert = $sn->insert( "cmdb_ci_computer",
[ { serial_number => "222222" },
{ serial_number => "111111" } ] );
my $delete = $sn->delete( "cmdb_ci_computer",
'0014eca36f015500e5f95afc5d3ee4af' );
my $delete_multi = $sn->deleteMultiple( "cmdb_ci_computer",
{ serial_number => "111111" } );
=head1 DESCRIPTION
If you need to use version 1 of the ServiceNow JSON API, pass legacy => 1
to the contructor. "Instance" in the contructor represents the part of the
service now url that is before service-now.com. So instance.service-now.com.
=head1 METHODS
=head2 get
Accepts a table/record name and a sys_id for that record, returns an arrayref with either
0 or 1 elements. The elements will be a hashref of the ServiceNow object.
=head2 getRecords
Accepts a table/record name and a hashref of query terms, multiple terms are ANDed together,
API does not support OR type clauses. Returns all objects in an arrayref that match that
query.
=head2 getKeys
Accepts a table/record name and a hashref of query terms. Returns an arrayref of sys_ids
for all objects that match the query criteria.
=head2 update
Accepts a table/record name, a hashref of query parameters and a hashref of the changes
you wish to make. Multiple query parameters are ANDed together, works the same as getRecords
and getKeys. Returns an arrayref of the objects that were updated.
=head2 insert
Accepts a table/record name and either an array or hashref of the data you wish to enter.
If you pass an arrayref it will detect this and pass the call onto insertMultiple.
Returns an arrayref of the records that were just created.
=head2 insertMultiple
Accepts a table/record name and an arrayref of the records you want to insert. Returns an
arrayref of the records that were just created.
=head2 delete
Accepts a table/record name and a sys_id of the record you wish to delete. Will only ever
delete a single record. Returns the record that you just deleted in an arrayref.
=head2 deleteMultiple
Accepts a table/record name and a hashref of query terms. Will delete ALL records that match
those query terms. Returns arrayref of the objects that were deleted.
=head1 SEE ALSO
L<Moose|Moose>
L<REST::Client|REST::Client>
L<MIME::Base64|MIME::Base64>
L<JSON|JSON>
L<https://wiki.servicenow.com/index.php?title=JSON_Web_Service|ServiceNow JSON Web Service Documentation>
L<https://github.com/klkane/servicenow-json|ServiceNow::JSON Github Repository>
=head1 AUTHOR
Kevin L. Kane, E<lt>kkane@cpan.orgE<gt>
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2014 by Kevin L. Kane
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=cut
__PACKAGE__->meta->make_immutable;
1;