ticket_abstractor_client 1.29.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +199 -159
- data/lib/ticket_abstractor_client.rb +11 -39
- data/lib/ticket_abstractor_client/base/attachment.rb +52 -0
- data/lib/ticket_abstractor_client/base/client.rb +54 -0
- data/lib/ticket_abstractor_client/base/comment.rb +35 -0
- data/lib/ticket_abstractor_client/base/errors.rb +25 -0
- data/lib/ticket_abstractor_client/base/fields_filter.rb +15 -0
- data/lib/ticket_abstractor_client/base/response_handler.rb +28 -0
- data/lib/ticket_abstractor_client/base/ticket.rb +79 -0
- data/lib/ticket_abstractor_client/client_helper.rb +29 -0
- data/lib/ticket_abstractor_client/configuration.rb +61 -0
- data/lib/ticket_abstractor_client/jira/attachment.rb +42 -0
- data/lib/ticket_abstractor_client/jira/client.rb +83 -0
- data/lib/ticket_abstractor_client/jira/comment.rb +35 -0
- data/lib/ticket_abstractor_client/jira/errors.rb +25 -0
- data/lib/ticket_abstractor_client/jira/fields_meta.rb +36 -0
- data/lib/ticket_abstractor_client/jira/params_builder.rb +96 -0
- data/lib/ticket_abstractor_client/jira/ticket.rb +131 -0
- data/lib/ticket_abstractor_client/service_now/attachment.rb +41 -0
- data/lib/ticket_abstractor_client/service_now/client.rb +78 -0
- data/lib/ticket_abstractor_client/service_now/comment.rb +30 -0
- data/lib/ticket_abstractor_client/service_now/errors.rb +25 -0
- data/lib/ticket_abstractor_client/service_now/params_builder.rb +56 -0
- data/lib/ticket_abstractor_client/service_now/ticket.rb +120 -0
- data/lib/ticket_abstractor_client/version.rb +1 -1
- metadata +52 -9
- data/lib/ticket_abstractor_client/brouha_client.rb +0 -33
- data/lib/ticket_abstractor_client/client.rb +0 -31
- data/lib/ticket_abstractor_client/i_logger_client.rb +0 -5
- data/lib/ticket_abstractor_client/itrc_client.rb +0 -33
- data/lib/ticket_abstractor_client/jira_client.rb +0 -128
- data/lib/ticket_abstractor_client/service_now_client.rb +0 -61
- data/lib/ticket_abstractor_client/sev_one_client.rb +0 -21
@@ -0,0 +1,41 @@
|
|
1
|
+
module TicketAbstractorClient
|
2
|
+
module ServiceNow
|
3
|
+
class Attachment < Base::Attachment
|
4
|
+
attr_accessor :ticket_id, :endpoint, :project
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def fetch(ticket_id, endpoint, project)
|
8
|
+
download_files(ticket_id, endpoint).map do |filepath|
|
9
|
+
new(file_path: filepath, ticket_id: ticket_id, endpoint: endpoint, project: project)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
protected
|
14
|
+
|
15
|
+
def download_files(ticket_id, endpoint)
|
16
|
+
response = Client.new(endpoint).get_attachments(ticket_id: ticket_id)
|
17
|
+
return [] if response.blank?
|
18
|
+
decode_and_save(Array.wrap(response['payload']), Array.wrap(response['file_name']))
|
19
|
+
end
|
20
|
+
|
21
|
+
def decode_and_save(payload, files_names)
|
22
|
+
payload.each.with_index.with_object([]) do |(payload, index), files|
|
23
|
+
next if payload.blank?
|
24
|
+
file_name = files_names[index]
|
25
|
+
decoded_payload = Base64.decode64(payload)
|
26
|
+
files << save_content(decoded_payload, file_name)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def initialize(opts)
|
32
|
+
super(opts)
|
33
|
+
@ticket_id, @endpoint, @project = opts.values_at(:ticket_id, :endpoint, :project)
|
34
|
+
end
|
35
|
+
|
36
|
+
def sync!
|
37
|
+
Client.new(@endpoint).create_attachment(self)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module TicketAbstractorClient
|
2
|
+
module ServiceNow
|
3
|
+
class Client < Base::Client
|
4
|
+
include ServiceNow::ParamsBuilder
|
5
|
+
|
6
|
+
SYS_ID_LENGTH = 32
|
7
|
+
|
8
|
+
def initialize(endpoint = 'default')
|
9
|
+
super()
|
10
|
+
@service_now_endpoint = endpoint
|
11
|
+
end
|
12
|
+
|
13
|
+
def get_all_tickets(opts)
|
14
|
+
get_tickets_by_query(build_all_tickets_params(opts))
|
15
|
+
end
|
16
|
+
|
17
|
+
def get_attachments(opts)
|
18
|
+
get(__method__, opts)
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_comments(opts)
|
22
|
+
opts[:ticket_id] = get_ticket_sys_id(opts)
|
23
|
+
opts[:display_value] ||= TicketAbstractorClient.configuration.snow_display_value
|
24
|
+
get(__method__, opts)
|
25
|
+
end
|
26
|
+
|
27
|
+
def get_ticket_by_id(opts)
|
28
|
+
opts[:ticket_id] = get_ticket_sys_id(opts)
|
29
|
+
opts[:display_value] ||= TicketAbstractorClient.configuration.snow_display_value
|
30
|
+
get(__method__, opts)
|
31
|
+
end
|
32
|
+
|
33
|
+
def get_tickets_by_query(opts)
|
34
|
+
opts[:display_value] ||= TicketAbstractorClient.configuration.snow_display_value
|
35
|
+
get(__method__, opts)
|
36
|
+
end
|
37
|
+
|
38
|
+
def create_attachment(attachment)
|
39
|
+
attachment.ticket_id = get_ticket_sys_id(ticket_id: attachment.ticket_id, table_name: attachment.project)
|
40
|
+
post(__method__, build_attachment_params(attachment))
|
41
|
+
end
|
42
|
+
|
43
|
+
def create_comment(comment)
|
44
|
+
comment.ticket_id = get_ticket_sys_id(ticket_id: comment.ticket_id, table_name: comment.project)
|
45
|
+
post(__method__, build_comment_params(comment))
|
46
|
+
end
|
47
|
+
|
48
|
+
def create_ticket(ticket)
|
49
|
+
post(__method__, build_ticket_params(ticket))
|
50
|
+
end
|
51
|
+
|
52
|
+
def update_ticket(ticket)
|
53
|
+
ticket.ticket_id = get_ticket_sys_id(ticket_id: ticket.ticket_id, table_name: ticket.project)
|
54
|
+
post(__method__, build_ticket_params(ticket))
|
55
|
+
end
|
56
|
+
|
57
|
+
def update_ticket_status(ticket)
|
58
|
+
post(:update_ticket, build_status_params(ticket))
|
59
|
+
end
|
60
|
+
|
61
|
+
protected
|
62
|
+
|
63
|
+
def get_ticket_sys_id(opts)
|
64
|
+
return opts[:ticket_id] if opts[:ticket_id].length == SYS_ID_LENGTH
|
65
|
+
|
66
|
+
get(__method__, opts)[0]['sys_id']
|
67
|
+
end
|
68
|
+
|
69
|
+
def get(path, args = {}, params = {})
|
70
|
+
super("service_now/#{path}", args, params.merge(service_now_endpoint: @service_now_endpoint))
|
71
|
+
end
|
72
|
+
|
73
|
+
def post(path, args = {}, params = {})
|
74
|
+
super("service_now/#{path}", args, params.merge(service_now_endpoint: @service_now_endpoint))
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module TicketAbstractorClient
|
2
|
+
module ServiceNow
|
3
|
+
class Comment < Base::Comment
|
4
|
+
attr_accessor :ticket_id, :endpoint, :project
|
5
|
+
|
6
|
+
def self.fetch(ticket_id, endpoint, project)
|
7
|
+
response = Client.new(endpoint).get_comments(ticket_id: ticket_id, table_name: project)
|
8
|
+
response.map do |raw_comment|
|
9
|
+
new({
|
10
|
+
author: raw_comment['sys_created_by_name'],
|
11
|
+
body: raw_comment['value'],
|
12
|
+
external_created_at: raw_comment['sys_created_on'],
|
13
|
+
ticket_id: ticket_id,
|
14
|
+
endpoint: endpoint,
|
15
|
+
project: project
|
16
|
+
})
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(opts)
|
21
|
+
super(opts)
|
22
|
+
@ticket_id, @endpoint, @project = opts.values_at(:ticket_id, :endpoint, :project)
|
23
|
+
end
|
24
|
+
|
25
|
+
def sync!
|
26
|
+
Client.new(@endpoint).create_comment(self)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module TicketAbstractorClient
|
2
|
+
module ServiceNow
|
3
|
+
module Errors
|
4
|
+
class BaseError < Base::Errors::BaseError; end
|
5
|
+
class NotImplementedError < BaseError; end
|
6
|
+
class ConfigurationError < Base::Errors::ConfigurationError; end
|
7
|
+
class UnexpectedError < Base::Errors::UnexpectedError; end
|
8
|
+
|
9
|
+
class AttachmentArgumentError < Base::Errors::AttachmentArgumentError; end
|
10
|
+
class CommentArgumentError < Base::Errors::CommentArgumentError; end
|
11
|
+
class ClientArgumentError < Base::Errors::ClientArgumentError; end
|
12
|
+
class TicketArgumentError < Base::Errors::TicketArgumentError; end
|
13
|
+
|
14
|
+
class AttachmentError < Base::Errors::AttachmentError; end
|
15
|
+
class CommentError < Base::Errors::CommentError; end
|
16
|
+
class TicketError < Base::Errors::TicketError; end
|
17
|
+
|
18
|
+
class ConnectionError < Base::Errors::ConnectionError; end
|
19
|
+
class NotFoundError < Base::Errors::NotFoundError; end
|
20
|
+
class ParseError < Base::Errors::ParseError; end
|
21
|
+
class RequsetFormatError < Base::Errors::RequsetFormatError; end
|
22
|
+
class AccessError < Base::Errors::AccessError; end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module TicketAbstractorClient
|
2
|
+
module ServiceNow
|
3
|
+
module ParamsBuilder
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
def biuld_all_tickets_params(opts)
|
7
|
+
opts[:sysparm_query] = build_sysparm_query(opts)
|
8
|
+
opts[:sysparm_fields] = Array.wrap(opts.delete(:fields))
|
9
|
+
opts.except!(:service_desk, :states)
|
10
|
+
opts[:display_value] ||= TicketAbstractorClient.configuration.snow_display_value
|
11
|
+
opts
|
12
|
+
end
|
13
|
+
|
14
|
+
def build_attachment_params(attachment)
|
15
|
+
file_path = attachment.file_path
|
16
|
+
mime_type = MIME::Types.type_for(file_path).first.try(:to_s) || '*/*'
|
17
|
+
file = File.open(file_path, 'rb')
|
18
|
+
{
|
19
|
+
agent: 'AttachmentCreator',
|
20
|
+
topic: 'AttachmentCreator',
|
21
|
+
name: "#{File.basename(file_path)}:#{mime_type}",
|
22
|
+
source: "#{attachment.project}:#{attachment.ticket_id}",
|
23
|
+
payload: Base64.encode64(file.read)
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
def build_comment_params(comment)
|
28
|
+
{
|
29
|
+
comment_params: { comments: comment.body },
|
30
|
+
ticket_id: comment.ticket_id,
|
31
|
+
table_name: comment.project,
|
32
|
+
display_value: TicketAbstractorClient.configuration.snow_display_value
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
def build_status_params(ticket)
|
37
|
+
{ ticket_params: { state: ticket.status }, ticket_id: ticket.ticket_id, table_name: ticket.project }
|
38
|
+
end
|
39
|
+
|
40
|
+
def build_ticket_params(ticket)
|
41
|
+
opts = { ticket_params: ticket.fields, table_name: ticket.project }
|
42
|
+
opts.merge!(ticket_id: ticket.ticket_id) if ticket.ticket_id.present?
|
43
|
+
opts
|
44
|
+
end
|
45
|
+
|
46
|
+
def build_sysparm_query(opts)
|
47
|
+
sysparm_query = {
|
48
|
+
'u_support_fieldLIKE' => opts[:service_desk],
|
49
|
+
'u_input_source=' => 'OIV',
|
50
|
+
'' => opts.fetch(:states, '').split(',').map { |st| "state=#{st}" }.join('^OR')
|
51
|
+
}
|
52
|
+
sysparm_query.select { |_, v| v.present? }.map { |k, v| [k, v].join }.join('^')
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
module TicketAbstractorClient
|
2
|
+
module ServiceNow
|
3
|
+
class Ticket < Base::Ticket
|
4
|
+
|
5
|
+
def self.fetch_by_id(opts)
|
6
|
+
fetch(:by_id, opts).first
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.fetch_all_tickets(opts)
|
10
|
+
fetch(:all, opts)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.fetch_tickets_by_query(opts)
|
14
|
+
fetch(:by_query, opts)
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(opts = {})
|
18
|
+
super(opts)
|
19
|
+
@project = opts[:project] || raise(Errors::TicketArgumentError, 'Project is not given')
|
20
|
+
@status = @fields.delete('state')
|
21
|
+
end
|
22
|
+
|
23
|
+
def add_attachment(attachment)
|
24
|
+
@attachments << Attachment.new(attachment.merge!(ticket_id: @ticket_id, endpoint: @endpoint))
|
25
|
+
@changes[:new_attachments] += 1
|
26
|
+
self
|
27
|
+
end
|
28
|
+
|
29
|
+
def add_comment(comment)
|
30
|
+
@comments << Comment.new(comment.merge!(ticket_id: @ticket_id, endpoint: @endpoint))
|
31
|
+
@changes[:new_comments] += 1
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
def attachments
|
36
|
+
return @attachments if @attachments.present?
|
37
|
+
|
38
|
+
return [] if @ticket_id.blank? && @attachments.blank?
|
39
|
+
|
40
|
+
@attachments = Attachment.fetch(@ticket_id, @endpoint)
|
41
|
+
end
|
42
|
+
|
43
|
+
def comments
|
44
|
+
return @comments if @comments.present?
|
45
|
+
|
46
|
+
return [] if @ticket_id.blank? && @comments.blank?
|
47
|
+
|
48
|
+
@comments = Comment.fetch(@ticket_id, @endpoint)
|
49
|
+
end
|
50
|
+
|
51
|
+
def sync!
|
52
|
+
raise TicketArgumentError, 'No changes to apply' unless self.any_changes?
|
53
|
+
return create_ticket if @changes[:create]
|
54
|
+
update_ticket if @changes[:update]
|
55
|
+
update_status if @changes[:new_status]
|
56
|
+
sync_comments unless @changes[:new_comments].zero?
|
57
|
+
sync_attachments unless @changes[:new_attachments].zero?
|
58
|
+
reset_changes!
|
59
|
+
end
|
60
|
+
|
61
|
+
def updated_at
|
62
|
+
@fields['sys_updated_on']
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
# selektor -- all, by_id, by_query
|
68
|
+
# Ticket.fetch(:all, opts)
|
69
|
+
# Ticket.fetch(:by_id, opts)
|
70
|
+
# Ticket.fetch(:by_query, opts)
|
71
|
+
def self.fetch(selektor, opts)
|
72
|
+
opts = opts.with_indifferent_access
|
73
|
+
endpoint = opts.delete(:endpoint)
|
74
|
+
method_map = { all: :get_all_tickets, by_id: :get_ticket_by_id, by_query: :get_tickets_by_query }
|
75
|
+
client_response = Client.new(endpoint).public_send(method_map.fetch(selektor.to_sym), opts)
|
76
|
+
|
77
|
+
Array.wrap(client_response).map do |hash|
|
78
|
+
fields = filter_fields(hash)
|
79
|
+
ticket = new(ticket_id: opts[:ticket_id], fields: fields, endpoint: endpoint, project: opts[:table_name])
|
80
|
+
ticket.reset_changes!
|
81
|
+
ticket
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.filter_fields(fields)
|
86
|
+
filter_fields_klass = TicketAbstractorClient.configuration.snow_fields_filter_class
|
87
|
+
|
88
|
+
return fields if filter_fields_klass.blank?
|
89
|
+
|
90
|
+
filter_fields_klass.new(fields).filter_fields
|
91
|
+
end
|
92
|
+
|
93
|
+
def create_ticket
|
94
|
+
response = Client.new(@endpoint).create_ticket(self)
|
95
|
+
ticket = Ticket.fetch_by_id(ticket_id: response['number'], table_name: @project, endpoint: @endpoint)
|
96
|
+
@fields = ticket.fields
|
97
|
+
@status = ticket.status
|
98
|
+
reset_changes!
|
99
|
+
end
|
100
|
+
|
101
|
+
def update_status
|
102
|
+
@fields['state'] = @status
|
103
|
+
update_ticket
|
104
|
+
end
|
105
|
+
|
106
|
+
def update_ticket
|
107
|
+
response = Client.new(@endpoint).update_ticket(self)
|
108
|
+
@fields['sys_updated_on'] = response['sys_updated_on']
|
109
|
+
end
|
110
|
+
|
111
|
+
def sync_attachments
|
112
|
+
@attachments.last(@changes[:new_attachments]).map(&:sync!)
|
113
|
+
end
|
114
|
+
|
115
|
+
def sync_comments
|
116
|
+
@comments.last(@changes[:new_comments]).map(&:sync!)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ticket_abstractor_client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Roman Samoilov
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2017-02-
|
12
|
+
date: 2017-02-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -53,6 +53,34 @@ dependencies:
|
|
53
53
|
- - "~>"
|
54
54
|
- !ruby/object:Gem::Version
|
55
55
|
version: 2.0.0
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: activesupport
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - "~>"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 4.2.7
|
63
|
+
type: :runtime
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 4.2.7
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: mime-types
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - "~>"
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: 1.25.1
|
77
|
+
type: :runtime
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - "~>"
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: 1.25.1
|
56
84
|
description: Get access to Jira and Brouha ticketing systems through the single service
|
57
85
|
email:
|
58
86
|
- rsamoilov@productengine.com
|
@@ -63,13 +91,28 @@ extra_rdoc_files: []
|
|
63
91
|
files:
|
64
92
|
- README.md
|
65
93
|
- lib/ticket_abstractor_client.rb
|
66
|
-
- lib/ticket_abstractor_client/
|
67
|
-
- lib/ticket_abstractor_client/client.rb
|
68
|
-
- lib/ticket_abstractor_client/
|
69
|
-
- lib/ticket_abstractor_client/
|
70
|
-
- lib/ticket_abstractor_client/
|
71
|
-
- lib/ticket_abstractor_client/
|
72
|
-
- lib/ticket_abstractor_client/
|
94
|
+
- lib/ticket_abstractor_client/base/attachment.rb
|
95
|
+
- lib/ticket_abstractor_client/base/client.rb
|
96
|
+
- lib/ticket_abstractor_client/base/comment.rb
|
97
|
+
- lib/ticket_abstractor_client/base/errors.rb
|
98
|
+
- lib/ticket_abstractor_client/base/fields_filter.rb
|
99
|
+
- lib/ticket_abstractor_client/base/response_handler.rb
|
100
|
+
- lib/ticket_abstractor_client/base/ticket.rb
|
101
|
+
- lib/ticket_abstractor_client/client_helper.rb
|
102
|
+
- lib/ticket_abstractor_client/configuration.rb
|
103
|
+
- lib/ticket_abstractor_client/jira/attachment.rb
|
104
|
+
- lib/ticket_abstractor_client/jira/client.rb
|
105
|
+
- lib/ticket_abstractor_client/jira/comment.rb
|
106
|
+
- lib/ticket_abstractor_client/jira/errors.rb
|
107
|
+
- lib/ticket_abstractor_client/jira/fields_meta.rb
|
108
|
+
- lib/ticket_abstractor_client/jira/params_builder.rb
|
109
|
+
- lib/ticket_abstractor_client/jira/ticket.rb
|
110
|
+
- lib/ticket_abstractor_client/service_now/attachment.rb
|
111
|
+
- lib/ticket_abstractor_client/service_now/client.rb
|
112
|
+
- lib/ticket_abstractor_client/service_now/comment.rb
|
113
|
+
- lib/ticket_abstractor_client/service_now/errors.rb
|
114
|
+
- lib/ticket_abstractor_client/service_now/params_builder.rb
|
115
|
+
- lib/ticket_abstractor_client/service_now/ticket.rb
|
73
116
|
- lib/ticket_abstractor_client/version.rb
|
74
117
|
homepage: https://github.comcast.com/opsint/ticket-abstractor-client
|
75
118
|
licenses:
|