cherby 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/.rspec +3 -0
- data/.travis.yml +4 -0
- data/.yardopts +4 -0
- data/Gemfile +6 -0
- data/README.md +83 -0
- data/Rakefile +12 -0
- data/cherby.gemspec +29 -0
- data/lib/cherby.rb +11 -0
- data/lib/cherby/business_object.rb +159 -0
- data/lib/cherby/cherwell.rb +230 -0
- data/lib/cherby/client.rb +147 -0
- data/lib/cherby/exceptions.rb +6 -0
- data/lib/cherby/incident.rb +141 -0
- data/lib/cherby/journal_note.rb +13 -0
- data/lib/cherby/task.rb +37 -0
- data/lib/cherby/templates/incident.mustache +226 -0
- data/lib/cherby/templates/journal_note.mustache +30 -0
- data/lib/cherby/templates/journal_note_relationship.mustache +3 -0
- data/lib/cherby/templates/task.mustache +67 -0
- data/lib/cherby/templates/task_relationship.mustache +3 -0
- data/lib/cherby/templates/test/simple.mustache +8 -0
- data/spec/business_object_spec.rb +250 -0
- data/spec/cherwell_spec.rb +300 -0
- data/spec/client_spec.rb +149 -0
- data/spec/data/cherwell.wsdl +1568 -0
- data/spec/data/incident.xml +1411 -0
- data/spec/data/login_false.xml +8 -0
- data/spec/data/login_true.xml +6 -0
- data/spec/data/task.xml +64 -0
- data/spec/incident_spec.rb +124 -0
- data/spec/journal_note_spec.rb +13 -0
- data/spec/spec_helper.rb +40 -0
- data/spec/task_spec.rb +77 -0
- data/spec/xml/method_response_result.mustache +4 -0
- data/spec/xml/soap_envelope.mustache +6 -0
- data/tasks/pry.rake +28 -0
- data/tasks/spec.rake +8 -0
- metadata +261 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/.yardopts
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
Cherby
|
2
|
+
======
|
3
|
+
|
4
|
+
Cherby is a Ruby wrapper for the
|
5
|
+
[Cherwell Web Service](http://cherwellsupport.com/webhelp/cherwell/index.htm#1971.htm).
|
6
|
+
|
7
|
+
[Full documentation is on rdoc.info](http://rubydoc.info/github/a-e/cherby/master/frames).
|
8
|
+
|
9
|
+
[![Build Status](https://secure.travis-ci.org/a-e/cherby.png?branch=dev)](http://travis-ci.org/a-e/cherby)
|
10
|
+
|
11
|
+
|
12
|
+
Usage
|
13
|
+
-----
|
14
|
+
|
15
|
+
Connect to a Cherwell server by providing the URL of the web service:
|
16
|
+
|
17
|
+
url = "http://my.server/CherwellService/api.asmx"
|
18
|
+
cherwell = Cherby::Cherwell.new(url)
|
19
|
+
|
20
|
+
Login by providing username and password, either during instantiation, or later
|
21
|
+
when calling the `#login` method:
|
22
|
+
|
23
|
+
cherwell = Cherby::Cherwell.new(url, 'sisko', 'baseball')
|
24
|
+
cherwell.login
|
25
|
+
# => true
|
26
|
+
|
27
|
+
# or
|
28
|
+
|
29
|
+
cherwell = Cherby::Cherwell.new(url)
|
30
|
+
cherwell.login('sisko', 'baseball')
|
31
|
+
# => true
|
32
|
+
|
33
|
+
Fetch an Incident:
|
34
|
+
|
35
|
+
incident = cherwell.incident('12345')
|
36
|
+
# => #<Cherby::Incident:0x...>
|
37
|
+
|
38
|
+
View as a Hash:
|
39
|
+
|
40
|
+
incident.to_hash
|
41
|
+
# => {
|
42
|
+
# 'IncidentID' => '12345',
|
43
|
+
# 'Status' => 'Open',
|
44
|
+
# 'Priority' => '7',
|
45
|
+
# ...
|
46
|
+
# }
|
47
|
+
|
48
|
+
Make changes:
|
49
|
+
|
50
|
+
incident['Status'] = 'Closed'
|
51
|
+
incident['CloseDescription'] = 'Issue resolved'
|
52
|
+
|
53
|
+
Save back to Cherwell:
|
54
|
+
|
55
|
+
cherwell.save_incident(incident)
|
56
|
+
|
57
|
+
|
58
|
+
Copyright
|
59
|
+
---------
|
60
|
+
|
61
|
+
The MIT License
|
62
|
+
|
63
|
+
Copyright (c) 2014 Eric Pierce
|
64
|
+
|
65
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
66
|
+
a copy of this software and associated documentation files (the
|
67
|
+
"Software"), to deal in the Software without restriction, including
|
68
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
69
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
70
|
+
permit persons to whom the Software is furnished to do so, subject to
|
71
|
+
the following conditions:
|
72
|
+
|
73
|
+
The above copyright notice and this permission notice shall be
|
74
|
+
included in all copies or substantial portions of the Software.
|
75
|
+
|
76
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
77
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
78
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
79
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
80
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
81
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
82
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
83
|
+
|
data/Rakefile
ADDED
data/cherby.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "cherby"
|
3
|
+
s.version = "0.0.1"
|
4
|
+
s.summary = "Cherwell-Ruby bridge"
|
5
|
+
s.description = <<-EOS
|
6
|
+
Cherby is a Ruby wrapper for the Cherwell Web Service.
|
7
|
+
EOS
|
8
|
+
s.authors = ["Eric Pierce"]
|
9
|
+
s.email = "wapcaplet88@gmail.com"
|
10
|
+
s.homepage = "http://github.com/a-e/cherby"
|
11
|
+
s.platform = Gem::Platform::RUBY
|
12
|
+
|
13
|
+
s.add_dependency "httpclient"
|
14
|
+
s.add_dependency 'savon', '>= 2.3.0'
|
15
|
+
s.add_dependency 'yajl-ruby'
|
16
|
+
s.add_dependency 'nokogiri'
|
17
|
+
s.add_dependency 'mustache'
|
18
|
+
|
19
|
+
s.add_development_dependency "rake"
|
20
|
+
s.add_development_dependency "simplecov"
|
21
|
+
s.add_development_dependency "pry"
|
22
|
+
s.add_development_dependency "rspec"
|
23
|
+
s.add_development_dependency 'yard'
|
24
|
+
s.add_development_dependency 'redcarpet'
|
25
|
+
|
26
|
+
s.files = `git ls-files`.split("\n")
|
27
|
+
s.require_path = 'lib'
|
28
|
+
end
|
29
|
+
|
data/lib/cherby.rb
ADDED
@@ -0,0 +1,159 @@
|
|
1
|
+
require 'mustache'
|
2
|
+
require 'nokogiri'
|
3
|
+
|
4
|
+
module Cherby
|
5
|
+
# Cherwell BusinessObject wrapper, with data represented as an XML DOM
|
6
|
+
class BusinessObject
|
7
|
+
|
8
|
+
# Override this with the value of the BusinessObject's 'Name' attribute
|
9
|
+
@object_name = ''
|
10
|
+
# Override this with the name of the Mustache XML template used to render
|
11
|
+
# your BusinessObject
|
12
|
+
@template = ''
|
13
|
+
# Fill this with default values for new instances of your BusinessObject
|
14
|
+
@default_values = {}
|
15
|
+
|
16
|
+
class << self
|
17
|
+
attr_accessor :object_name, :template, :default_values, :template_path
|
18
|
+
end
|
19
|
+
|
20
|
+
# Create a new BusinessObject subclass instance from the given hash of
|
21
|
+
# options.
|
22
|
+
# FIXME: Make this method accept CamelCase string field names instead of
|
23
|
+
# just :snake_case symbols, as part of a larger strategy to treat field names
|
24
|
+
# consistently throughout (using Cherwell's CamelCase strings everywhere)
|
25
|
+
def self.create(options={})
|
26
|
+
if self.template.empty?
|
27
|
+
# TODO: Exception subclass
|
28
|
+
raise RuntimeError, "No template defined for BusinessObject"
|
29
|
+
end
|
30
|
+
Mustache.template_path = File.join(File.dirname(__FILE__), 'templates')
|
31
|
+
xml = Mustache.render_file(
|
32
|
+
self.template, self.default_values.merge(options))
|
33
|
+
return self.new(xml)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Instance methods
|
37
|
+
|
38
|
+
attr_reader :dom
|
39
|
+
|
40
|
+
# Create a new instance populated with the given XML string
|
41
|
+
def initialize(xml)
|
42
|
+
@dom = Nokogiri::XML(xml)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Return the XML representation of this BusinessObject
|
46
|
+
def to_xml
|
47
|
+
return @dom.to_xml
|
48
|
+
end
|
49
|
+
|
50
|
+
# Return the node of the field with the given name.
|
51
|
+
def get_field_node(field_name)
|
52
|
+
selector = "BusinessObject > FieldList > Field[@Name=#{field_name}]"
|
53
|
+
return @dom.css(selector).first
|
54
|
+
end
|
55
|
+
|
56
|
+
# Return a hash of field names and values
|
57
|
+
def to_hash
|
58
|
+
result = {}
|
59
|
+
selector = "BusinessObject > FieldList > Field"
|
60
|
+
@dom.css(selector).each do |node|
|
61
|
+
result[node['Name']] = node.content
|
62
|
+
end
|
63
|
+
return result
|
64
|
+
end
|
65
|
+
alias :field_values :to_hash # For backwards compatibility
|
66
|
+
|
67
|
+
|
68
|
+
# Parse a Cherwell date/time string and return a DateTime object in UTC.
|
69
|
+
#
|
70
|
+
# This method mostly exists to work around the fact that Cherwell does
|
71
|
+
# not report a time zone offset in its datestamps. Since a BusinessObject
|
72
|
+
# may be initialized from a Jira entity (which *does* store time zone
|
73
|
+
# offset), any dt_string that includes a time zone offset at the end is
|
74
|
+
# correctly included in the result.
|
75
|
+
#
|
76
|
+
# @param [String] dt_string
|
77
|
+
# The date/time string to parse. May or may not include a trailing
|
78
|
+
# [+-]HH:MM or [+-]HHMM.
|
79
|
+
#
|
80
|
+
# @param [Integer] tz_offset
|
81
|
+
# Offset in hours (positive or negative) between UTC and the given
|
82
|
+
# `dt_string`. For example, Eastern Time is `-5`. This is ONLY used if
|
83
|
+
# `dt_string` does NOT include a trailing offset component.
|
84
|
+
#
|
85
|
+
def self.parse_datetime(dt_string, tz_offset=-5)
|
86
|
+
begin
|
87
|
+
result = DateTime.parse(dt_string)
|
88
|
+
rescue
|
89
|
+
raise ArgumentError, "Could not parse date/time '#{dt_string}'"
|
90
|
+
end
|
91
|
+
# If offset was part of the dt_string, use new_offset to get UTC
|
92
|
+
if dt_string =~ /[+-]\d\d:?\d\d$/
|
93
|
+
return result.new_offset(0)
|
94
|
+
# Otherwise, subtract the numeric offset to get UTC time
|
95
|
+
else
|
96
|
+
return result - Rational(tz_offset.to_i, 24)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Return the last-modified date/time of this BusinessObject
|
101
|
+
# (LastModDateTime converted to DateTime)
|
102
|
+
def modified
|
103
|
+
last_mod = self['LastModDateTime']
|
104
|
+
if last_mod.nil?
|
105
|
+
raise RuntimeError, "BusinessObject is missing LastModDateTime field."
|
106
|
+
end
|
107
|
+
begin
|
108
|
+
return BusinessObject.parse_datetime(last_mod)
|
109
|
+
rescue(ArgumentError)
|
110
|
+
raise RuntimeError, "Cannot parse LastModDateTime: '#{last_mod}'"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Return the last-modified time as a human-readable string
|
115
|
+
def mod_s
|
116
|
+
return modified.strftime('%Y-%m-%d %H:%M:%S')
|
117
|
+
end
|
118
|
+
|
119
|
+
# Return True if this BusinessObject was modified more recently than
|
120
|
+
# another BusinessObject.
|
121
|
+
def newer_than?(business_object)
|
122
|
+
return modified > business_object.modified
|
123
|
+
end
|
124
|
+
|
125
|
+
# Return the content in the field with the given name.
|
126
|
+
# TODO: Exception for unknown field name
|
127
|
+
def [](field_name)
|
128
|
+
if field = get_field_node(field_name)
|
129
|
+
return field.content
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# Modify the content in the field with the given name.
|
134
|
+
# TODO: Exception for unknown field name
|
135
|
+
def []=(field_name, value)
|
136
|
+
if field = get_field_node(field_name)
|
137
|
+
field.content = value.to_s
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
# Copy designated fields from one BusinessObject to another.
|
142
|
+
#
|
143
|
+
# @example
|
144
|
+
# object_a.copy_fields_from(object_b, 'Status', 'Description')
|
145
|
+
# # object_a['Status'] = object_b['Status']
|
146
|
+
# # object_a['Description'] = object_b['Description']
|
147
|
+
#
|
148
|
+
# @param [BusinessObject] other_object
|
149
|
+
# The object to copy field values from
|
150
|
+
# @param [Array<String>] field_names
|
151
|
+
# Names of fields whose values you want to copy
|
152
|
+
#
|
153
|
+
def copy_fields_from(other_object, *field_names)
|
154
|
+
field_names.each do |field|
|
155
|
+
self[field] = other_object[field]
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1,230 @@
|
|
1
|
+
require 'savon'
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'cherby/client'
|
4
|
+
require 'cherby/incident'
|
5
|
+
require 'cherby/task'
|
6
|
+
require 'cherby/exceptions'
|
7
|
+
|
8
|
+
module Cherby
|
9
|
+
# Top-level Cherwell interface
|
10
|
+
class Cherwell
|
11
|
+
attr_reader :url, :username, :client
|
12
|
+
|
13
|
+
# Connect to a Cherwell server.
|
14
|
+
#
|
15
|
+
# @param [String] web_service_url
|
16
|
+
# Full URL to the Cherwell web service API (typically ending in
|
17
|
+
# `api.asmx`)
|
18
|
+
# @param [String] username
|
19
|
+
# Default Cherwell user ID to use
|
20
|
+
# @param [String] password
|
21
|
+
# Default Cherwell password to use
|
22
|
+
#
|
23
|
+
def initialize(web_service_url, username=nil, password=nil)
|
24
|
+
@url = web_service_url
|
25
|
+
@url.chop! if @url =~ /\/$/ # Remove any trailing slash
|
26
|
+
@username = username
|
27
|
+
@password = password
|
28
|
+
@client = Cherby::Client.new(@url)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Login to Cherwell using the given credentials. Return true if
|
32
|
+
# login succeeded, or raise `LoginFailed` if login failed.
|
33
|
+
#
|
34
|
+
# @param [String] username
|
35
|
+
# User ID to login with. If omitted, the username that was passed to
|
36
|
+
# `Cherwell.new` is used.
|
37
|
+
# @param [String] password
|
38
|
+
# Password to login with. If omitted, the password that was passed to
|
39
|
+
# `Cherwell.new` is used.
|
40
|
+
#
|
41
|
+
# @return [Boolean]
|
42
|
+
# `true` if login was successful
|
43
|
+
#
|
44
|
+
# @raise [LoginFailed]
|
45
|
+
# If login failed for any reason
|
46
|
+
#
|
47
|
+
def login(username=nil, password=nil)
|
48
|
+
creds = {
|
49
|
+
:userId => username || @username,
|
50
|
+
:password => password || @password,
|
51
|
+
}
|
52
|
+
begin
|
53
|
+
response = @client.call(:login, :message => creds)
|
54
|
+
rescue => e
|
55
|
+
# This can happen if a bad URL is given
|
56
|
+
raise LoginFailed, e.message
|
57
|
+
else
|
58
|
+
if response.body[:login_response][:login_result] == true
|
59
|
+
# FIXME: Using the workaround described in this issue:
|
60
|
+
# https://github.com/savonrb/savon/issues/363
|
61
|
+
# because the version recommended in the documentation:
|
62
|
+
# auth_cookies = response.http.cookies
|
63
|
+
# does not work, giving:
|
64
|
+
# NoMethodError: undefined method `cookies' for #<HTTPI::Response:0x...>
|
65
|
+
@client.globals[:headers] = {"Cookie" => response.http.headers["Set-Cookie"]}
|
66
|
+
return true
|
67
|
+
# This can happen if invalid credentials are given
|
68
|
+
else
|
69
|
+
raise LoginFailed, "Cherwell returned false status"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Log out of Cherwell.
|
75
|
+
#
|
76
|
+
# @return [Boolean]
|
77
|
+
# Logout response as reported by Cherwell.
|
78
|
+
#
|
79
|
+
def logout
|
80
|
+
return @client.logout
|
81
|
+
end
|
82
|
+
|
83
|
+
# Get the Cherwell incident with the given public ID, and return an
|
84
|
+
# Incident object.
|
85
|
+
#
|
86
|
+
# @return [Incident]
|
87
|
+
#
|
88
|
+
def incident(id)
|
89
|
+
incident_xml = get_object_xml('Incident', id)
|
90
|
+
return Incident.new(incident_xml.to_s)
|
91
|
+
end
|
92
|
+
|
93
|
+
# Get the Cherwell task with the given public ID, and return a Task
|
94
|
+
# object.
|
95
|
+
#
|
96
|
+
# @return [Task]
|
97
|
+
#
|
98
|
+
def task(id)
|
99
|
+
task_xml = get_object_xml('Task', id)
|
100
|
+
return Task.new(task_xml.to_s)
|
101
|
+
end
|
102
|
+
|
103
|
+
# Get a business object based on its public ID or RecID, and return the
|
104
|
+
# XML response.
|
105
|
+
#
|
106
|
+
# @example
|
107
|
+
# incident_xml = cherwell.get_object_xml(
|
108
|
+
# 'Incident', '12345')
|
109
|
+
#
|
110
|
+
# note_xml = cherwell.get_object_xml(
|
111
|
+
# 'JournalNote', '93bd7e3e067f1dafb454d14cb399dda1ef3f65d36d')
|
112
|
+
#
|
113
|
+
# @param [String] object_type
|
114
|
+
# What type of object to fetch, for example "Incident", "Customer",
|
115
|
+
# "Task", "JournalNote", "SLA" etc. May also be the `IDREF` of an
|
116
|
+
# object type. Cherwell's API knows this as `busObNameOrId`.
|
117
|
+
# @param [String] id
|
118
|
+
# The public ID or RecID of the object. If this is 32 characters or
|
119
|
+
# more, it's assumed to be a RecID. For incidents, the public ID is a
|
120
|
+
# numeric identifier like "50629", while the RecID is a long
|
121
|
+
# hexadecimal string like "93bd7e3e067f1dafb454d14cb399dda1ef3f65d36d".
|
122
|
+
#
|
123
|
+
# This invokes `GetBusinessObject` or `GetBusinessObjectByPublicId`,
|
124
|
+
# depending on the length of `id`. The returned XML is the content of the
|
125
|
+
# `GetBusinessObjectResult` or `GetBusinessObjectByPublicIdResult`.
|
126
|
+
#
|
127
|
+
# @return [String]
|
128
|
+
# Raw XML response string.
|
129
|
+
#
|
130
|
+
def get_object_xml(object_type, id)
|
131
|
+
# Assemble the SOAP body
|
132
|
+
body = {:busObNameOrId => object_type}
|
133
|
+
|
134
|
+
# If ID is really long, it's probably a RecID
|
135
|
+
if id.to_s.length >= 32
|
136
|
+
method = :get_business_object
|
137
|
+
body[:busObRecId] = id
|
138
|
+
# Otherwise, assume it's a public ID
|
139
|
+
else
|
140
|
+
method = :get_business_object_by_public_id
|
141
|
+
body[:busObPublicId] = id
|
142
|
+
end
|
143
|
+
|
144
|
+
begin
|
145
|
+
result = @client.call_wrap(method, body)
|
146
|
+
rescue Savon::Error => e
|
147
|
+
raise SoapError, e.message
|
148
|
+
else
|
149
|
+
return result
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
|
154
|
+
# Update a given Cherwell object by submitting its XML to the SOAP
|
155
|
+
# interface.
|
156
|
+
#
|
157
|
+
# @param [String] object_type
|
158
|
+
# The kind of object you're updating ('Incident', 'Task'), or the
|
159
|
+
# IDREF of the object type.
|
160
|
+
# @param [String] id
|
161
|
+
# The public ID of the object
|
162
|
+
# @param [String] xml
|
163
|
+
# The XML body containing all the updates you want to make
|
164
|
+
#
|
165
|
+
def update_object_xml(object_type, id, xml)
|
166
|
+
@client.update_business_object_by_public_id({
|
167
|
+
:busObNameOrId => object_type,
|
168
|
+
:busObPublicId => id,
|
169
|
+
:updateXml => xml
|
170
|
+
})
|
171
|
+
return last_error
|
172
|
+
end
|
173
|
+
|
174
|
+
# Save the given Cherwell incident
|
175
|
+
def save_incident(incident)
|
176
|
+
update_object_xml('Incident', incident.id, incident.to_xml)
|
177
|
+
end
|
178
|
+
|
179
|
+
# Save the given Cherwell task
|
180
|
+
def save_task(task)
|
181
|
+
update_object_xml('Task', task.id, task.to_xml)
|
182
|
+
end
|
183
|
+
|
184
|
+
# Create a new Cherwell incident with the given data. If creation
|
185
|
+
# succeeds, return the Incident instance; otherwise, return `nil`.
|
186
|
+
#
|
187
|
+
# @example
|
188
|
+
# create_incident(
|
189
|
+
# :service => 'Consulting Services',
|
190
|
+
# :sub_category => 'New/Modified Functionality',
|
191
|
+
# :priority => '4',
|
192
|
+
# )
|
193
|
+
#
|
194
|
+
# @param [Hash] data
|
195
|
+
# Incident fields to initialize. All required fields must be filled
|
196
|
+
# in, or creation will fail. At minimum this includes `:service`,
|
197
|
+
# `:sub_category`, and `:priority`.
|
198
|
+
#
|
199
|
+
# @return [Incident, nil]
|
200
|
+
# The created incident, or `nil` if creation failed.
|
201
|
+
#
|
202
|
+
def create_incident(data)
|
203
|
+
incident = Incident.create(data)
|
204
|
+
result = @client.create_business_object({
|
205
|
+
:busObNameOrId => 'Incident',
|
206
|
+
:creationXml => incident.to_xml
|
207
|
+
})
|
208
|
+
|
209
|
+
# Result contains the public ID of the new incident, or nil if the
|
210
|
+
# incident-creation failed.
|
211
|
+
if !result.nil?
|
212
|
+
incident['IncidentID'] = result
|
213
|
+
return incident
|
214
|
+
else
|
215
|
+
return nil
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
# Get the last error reported by Cherwell.
|
220
|
+
#
|
221
|
+
# @return [String, nil]
|
222
|
+
# Text of the last error that occurred, or `nil` if there was no error.
|
223
|
+
#
|
224
|
+
def last_error
|
225
|
+
return @client.get_last_error
|
226
|
+
end
|
227
|
+
|
228
|
+
end # class Cherwell
|
229
|
+
end # module Cherby
|
230
|
+
|