roust 1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 513086117718e9f68a4940b63d82d3546b1c999e
4
+ data.tar.gz: efa3079add7548468976c137b1b1cfb40525df21
5
+ SHA512:
6
+ metadata.gz: 4ccafda8340e695d70354798db29f7338828a2fa5d932ccb9bf8803a8aba0035ee109dbace9175d2dc78b177ddf10f9557238e503b09cd26d237a20a558e3b0c
7
+ data.tar.gz: c1719e2fb75e59ffba44f05e5b5c24a98faa42fb625137a169a3b74063b46c45f27ac24d9847391e87999954fdf56b557c92ec9736da2fe49b6bc1592ceaef32
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+ .rtclientrc
15
+ *.cookie
16
+
17
+ # YARD artifacts
18
+ .yardoc
19
+ _yardoc
20
+ doc/
21
+
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.0.0-p247
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec
6
+
7
+ group :development do
8
+ gem 'rspec'
9
+ gem 'colorize'
10
+ gem 'rake'
11
+ gem 'webmock'
12
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,55 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ roust (1.0.0)
5
+ archive-tar-minitar (>= 0.5)
6
+ mail (>= 2.5.4)
7
+ mime-types (>= 1.16)
8
+ nokogiri (>= 1.2)
9
+ rest-client (>= 0.9)
10
+
11
+ GEM
12
+ remote: https://rubygems.org/
13
+ specs:
14
+ addressable (2.3.5)
15
+ archive-tar-minitar (0.5.2)
16
+ colorize (0.5.8)
17
+ crack (0.4.1)
18
+ safe_yaml (~> 0.9.0)
19
+ diff-lcs (1.1.3)
20
+ mail (2.5.4)
21
+ mime-types (~> 1.16)
22
+ treetop (~> 1.4.8)
23
+ mime-types (1.25)
24
+ mini_portile (0.5.1)
25
+ nokogiri (1.6.0)
26
+ mini_portile (~> 0.5.0)
27
+ polyglot (0.3.3)
28
+ rake (10.1.0)
29
+ rest-client (1.6.7)
30
+ mime-types (>= 1.16)
31
+ rspec (2.9.0)
32
+ rspec-core (~> 2.9.0)
33
+ rspec-expectations (~> 2.9.0)
34
+ rspec-mocks (~> 2.9.0)
35
+ rspec-core (2.9.0)
36
+ rspec-expectations (2.9.1)
37
+ diff-lcs (~> 1.1.3)
38
+ rspec-mocks (2.9.0)
39
+ safe_yaml (0.9.7)
40
+ treetop (1.4.15)
41
+ polyglot
42
+ polyglot (>= 0.3.1)
43
+ webmock (1.17.1)
44
+ addressable (>= 2.2.7)
45
+ crack (>= 0.3.2)
46
+
47
+ PLATFORMS
48
+ ruby
49
+
50
+ DEPENDENCIES
51
+ colorize
52
+ rake
53
+ roust!
54
+ rspec
55
+ webmock
data/LICENSE ADDED
@@ -0,0 +1,14 @@
1
+ Copyright 2009-2013 Tom Lahti
2
+ Copyright 2014 Bulletproof Networks
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,103 @@
1
+ Roust
2
+ =====
3
+
4
+ Roust is a Ruby client for [Request Tracker](http://www.bestpractical.com/rt/)'s REST API.
5
+
6
+ It is a fork of [rt-client](http://rubygems.org/gems/rt-client) by Tom Lahti.
7
+
8
+ Features
9
+ --------
10
+
11
+ - Ticket querying using the full RT query language
12
+ - Fetching ticket metadata (id, subject, queue, etc)
13
+ - Fetching transactions on individual tickets (in long and short form)
14
+ - Fetching user details
15
+
16
+ Installing
17
+ ----------
18
+
19
+ Ensure you have Ruby > 1.9 installed, then run:
20
+
21
+ ```
22
+ gem install roust
23
+ ```
24
+
25
+ Or add to your Gemfile:
26
+
27
+ ``` ruby
28
+ gem 'roust', :git => 'git@github.com:bulletproofnetworks/roust.git'
29
+ ```
30
+
31
+ Using
32
+ -----
33
+
34
+ ``` ruby
35
+ require 'roust'
36
+
37
+ credentials = {
38
+ :server => 'http://rt.example.org',
39
+ :username => 'admin'
40
+ :password => 's3cr3t'
41
+ }
42
+
43
+ rt = Roust.new(credentials)
44
+ rt.authenticated? # => true
45
+
46
+ # Query RT
47
+ rt.list(:query => "id = 1 or id = 2") # => [["1", "A subject"], ["2", "Another subject"]]
48
+
49
+ # Fetch ticket metadata
50
+ rt.show("1") # => { {"cc"=>["dan@us.example", "dave@them.example"], "owner"=>"bob", "creator"=>"alice", "status"=>"open", … }
51
+
52
+ # Fetch ticket transactions
53
+ rt.history("1", :format => "short") # => [["1", "Ticket created by alice"], ["2", "Status changed from 'open' to 'resolved' by bob"]]
54
+ rt.history("1", :format => "long") # => [{"id"=>"1", "ticket"=>"1", "timetaken"=>"0", "type"=>"Create", "field"=>"", "oldvalue"=>"", "newvalue"=>"", "data"=>"", "description"=>"Ticket created by alice" }, … ]
55
+
56
+ # Fetch user details
57
+ rt.user("dan@us.example") # => {"id"=>"user/160000", "name"=>"dan", "password"=>"********", "emailaddress"=>"dan@us.example", "realname"=>"Dan Smith", "nickname"=>"dan", … }
58
+ ```
59
+
60
+
61
+ Developing
62
+ ----------
63
+
64
+ To get started, clone the Roust repository locally by running:
65
+
66
+ ```
67
+ git clone git@github.com:bulletproofnetworks/roust.git
68
+ ```
69
+
70
+ Then pull in the dependencies:
71
+
72
+ ```
73
+ bundle
74
+ ```
75
+
76
+ You're now ready to run the tests:
77
+
78
+ ```
79
+ bundle exec rake
80
+ ```
81
+
82
+ Roust has reasonable test coverage of the core features mentioned above. It has some other features that have been ported from the original rt-client implementation that are not tested (and are probably broken). See the TODO section for more details.
83
+
84
+
85
+ Releasing
86
+ ---------
87
+
88
+ 1. Bump the version in `lib/roust/version.rb`
89
+ 2. Add an entry to `CHANGELOG.md`
90
+ 3. Run a `bundle` to update any RubyGems dependencies.
91
+ 4. `git commit` everything.
92
+ 5. git tag the version git tag X.Y.Z
93
+ 6. Build the gem with `rake build`
94
+
95
+
96
+
97
+ TODO
98
+ ----
99
+
100
+ - Links CRUD (linking tickets to one another)
101
+ - User CRUD (creating + updating + deleting users)
102
+ - Ticket comment + correspondence
103
+ - Attachment fetching
data/Rakefile ADDED
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'rspec/core/rake_task'
5
+ require 'colorize'
6
+
7
+ RSpec::Core::RakeTask.new('spec')
8
+
9
+ desc "build gem"
10
+ task :build do
11
+ build_output = `gem build roust.gemspec`
12
+ puts build_output
13
+
14
+ gem_filename = build_output[/File: (.*)/,1]
15
+ pkg_path = "pkg"
16
+ FileUtils.mkdir_p(pkg_path)
17
+ FileUtils.mv(gem_filename, pkg_path)
18
+
19
+ puts "Gem built in #{pkg_path}/#{gem_filename}".green
20
+ end
21
+
22
+ desc "push gem"
23
+ task :push do
24
+ filenames = Dir.glob("pkg/*.gem")
25
+ filenames_with_times = filenames.map do |filename|
26
+ [filename, File.mtime(filename)]
27
+ end
28
+
29
+ newest = filenames_with_times.sort_by { |tuple| tuple.last }.last
30
+ newest_filename = newest.first
31
+
32
+ command = "gem push #{newest_filename}"
33
+ system(command)
34
+ end
35
+
36
+ task :default => [:spec]
37
+
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'rt/client' # requires ruby 1.8
5
+ require 'pp'
6
+
7
+
8
+ ticket_id = '1318622'
9
+ parent_id = '1258480'
10
+
11
+ rt = RT_Client.new
12
+
13
+ rt.add_link(:id => ticket_id, :MemberOf => parent_id)
14
+ links = rt.links(:id => ticket_id)
15
+ pp links
@@ -0,0 +1,271 @@
1
+ #!/opt/ruby-enterprise-1.8.7-2010.02/bin/ruby
2
+
3
+ ## XML RPC service to provide a cross-platform API for
4
+ ## RT ticket creation/maintenance. Essentially just a wrapper
5
+ ## around the rt/client library.
6
+
7
+ require "rubygems" # so we can load gems
8
+ require "rt/client" # rt-client REST library
9
+ require "xmlrpc/server" # that's what we're doing
10
+ require "date" # for parsing arbitrary date formats
11
+ require "pp"
12
+
13
+ PORT=8080
14
+ MAX_CONN=50
15
+
16
+ # extend the Hash class to
17
+ # translate string keys into symbol keys
18
+ class Hash # :nodoc:
19
+ def remapkeys!
20
+ n = Hash.new
21
+ self.each_key do |key|
22
+ n[key.to_sym] = self[key]
23
+ end
24
+ self.replace(n)
25
+ n = nil
26
+ $stderr.puts self.map { |k,v| "#{k} => #{v}" }
27
+ self
28
+ end
29
+ end
30
+
31
+ class TicketSrv
32
+
33
+ def initialize
34
+ end
35
+
36
+ INTERFACE = XMLRPC::interface("rt") {
37
+ meth 'string add_watcher(struct)','Calls RT_Client::add_watcher'
38
+ meth 'array attachments(struct)','Calls RT_Client::attachments'
39
+ meth 'string comment(struct)','Calls RT_Client::comment'
40
+ meth 'string correspond(struct)','Calls RT_Client::correspond'
41
+ meth 'string create(struct)','Calls RT_Client::create'
42
+ meth 'string create_user(struct)','Calls RT_Client::create_user'
43
+ meth 'string edit(struct)','Calls RT_Client::edit'
44
+ meth 'string edit_or_create_user(struct)','Calls RT_Client::edit_or_create_user'
45
+ meth 'struct get_attachment(struct)','Calls RT_Client::get_attachment'
46
+ meth 'struct history(struct)','Calls RT_Client::history (long form)'
47
+ meth 'struct history_item(struct)','Calls RT_Client::history_item'
48
+ meth 'array list(struct)','Calls RT_Client::list'
49
+ meth 'array query(struct)','Calls RT_Client::query (long form)'
50
+ meth 'struct show(struct)','Calls RT_Client::show'
51
+ }
52
+
53
+ # Allows watchers to be added via RT_Client::add_watcher
54
+ # You need to pass :id, :addr, and optionally :type
55
+ def add_watcher(struct)
56
+ struct.remapkeys!
57
+ if struct.has_key? :user and struct.has_key? :pass
58
+ rt = RT_Client.new(:user => struct[:user], :pass => struct[:pass])
59
+ else
60
+ rt = RT_Client.new
61
+ end
62
+ val = rt.add_watcher(struct)
63
+ rt = nil
64
+ val
65
+ end
66
+
67
+ # Gets a list of attachments via RT_Client::attachments
68
+ # You need to pass :id, and optionally :unnamed
69
+ def attachments(struct)
70
+ struct.remapkeys!
71
+ if struct.has_key? :user and struct.has_key? :pass
72
+ rt = RT_Client.new(:user => struct[:user], :pass => struct[:pass])
73
+ else
74
+ rt = RT_Client.new
75
+ end
76
+ rt = RT_Client.new
77
+ val = rt.attachments(struct)
78
+ rt = nil
79
+ val
80
+ end
81
+
82
+ # Adds comments to tickets via RT_Client::comment
83
+ def comment(struct)
84
+ struct.remapkeys!
85
+ if struct.has_key? :user and struct.has_key? :pass
86
+ rt = RT_Client.new(:user => struct[:user], :pass => struct[:pass])
87
+ else
88
+ rt = RT_Client.new
89
+ end
90
+ val = rt.comment(struct)
91
+ rt = nil
92
+ val
93
+ end
94
+
95
+ # Allows new tickets to be created via RT_Client::correspond
96
+ def correspond(struct)
97
+ struct.remapkeys!
98
+ if struct.has_key? :user and struct.has_key? :pass
99
+ rt = RT_Client.new(:user => struct[:user], :pass => struct[:pass])
100
+ else
101
+ rt = RT_Client.new
102
+ end
103
+ val = rt.correspond(struct)
104
+ rt = nil
105
+ val
106
+ end
107
+
108
+ # Allows new tickets to be created via RT_Client::create
109
+ def create(struct)
110
+ struct.remapkeys!
111
+ if struct.has_key? :user and struct.has_key? :pass
112
+ rt = RT_Client.new(:user => struct[:user], :pass => struct[:pass])
113
+ else
114
+ rt = RT_Client.new
115
+ end
116
+ val = rt.create(struct)
117
+ rt = nil
118
+ val
119
+ end
120
+
121
+ # Allows new users to be created via RT_Client::create_user
122
+ def create_user(struct)
123
+ struct.remapkeys!
124
+ if struct.has_key? :user and struct.has_key? :pass
125
+ rt = RT_Client.new(:user => struct[:user], :pass => struct[:pass])
126
+ else
127
+ rt = RT_Client.new
128
+ end
129
+ val = rt.create_user(struct)
130
+ rt = nil
131
+ val
132
+ end
133
+
134
+ # Find RT user details from email address via RT_Cleint::usersearch
135
+ def usersearch(struct)
136
+ struct.remapkeys!
137
+ if struct.has_key? :user and struct.has_key? :pass
138
+ rt = RT_Client.new(:user => struct[:user], :pass => struct[:pass])
139
+ else
140
+ rt = RT_Client.new
141
+ end
142
+ val = rt.usersearch(struct)
143
+ rt = nil
144
+ val
145
+ end
146
+
147
+ # Allows new users to be edited or created if they don't exist
148
+ def edit_or_create_user(struct)
149
+ struct.remapkeys!
150
+ if struct.has_key? :user and struct.has_key? :pass
151
+ rt = RT_Client.new(:user => struct[:user], :pass => struct[:pass])
152
+ else
153
+ rt = RT_Client.new
154
+ end
155
+ val = rt.edit_or_create_user(struct)
156
+ rt = nil
157
+ val
158
+ end
159
+
160
+ # Allows existing ticket to be modified via RT_Client::edit
161
+ def edit(struct)
162
+ struct.remapkeys!
163
+ if struct.has_key? :user and struct.has_key? :pass
164
+ rt = RT_Client.new(:user => struct[:user], :pass => struct[:pass])
165
+ else
166
+ rt = RT_Client.new
167
+ end
168
+ val = rt.edit(struct)
169
+ rt = nil
170
+ val
171
+ end
172
+
173
+ # Retrieves attachments via RT_Client::get_attachment
174
+ def get_attachment(struct)
175
+ struct.remapkeys!
176
+ if struct.has_key? :user and struct.has_key? :pass
177
+ rt = RT_Client.new(:user => struct[:user], :pass => struct[:pass])
178
+ else
179
+ rt = RT_Client.new
180
+ end
181
+ val = rt.get_attachment(struct)
182
+ rt = nil
183
+ val
184
+ end
185
+
186
+ # Gets the history of a ticket via RT_Client::history
187
+ def history(struct)
188
+ struct.remapkeys!
189
+ if struct.has_key? :user and struct.has_key? :pass
190
+ rt = RT_Client.new(:user => struct[:user], :pass => struct[:pass])
191
+ else
192
+ rt = RT_Client.new
193
+ end
194
+ val = rt.history(struct)
195
+ rt = nil
196
+ val
197
+ end
198
+
199
+ # Gets a single history item via RT_Client::history_item
200
+ def history_item(struct)
201
+ struct.remapkeys!
202
+ if struct.has_key? :user and struct.has_key? :pass
203
+ rt = RT_Client.new(:user => struct[:user], :pass => struct[:pass])
204
+ else
205
+ rt = RT_Client.new
206
+ end
207
+ val = rt.history_item(struct)
208
+ rt = nil
209
+ val
210
+ end
211
+
212
+ # Gets a list of tickets via RT_Client::list
213
+ def list(struct)
214
+ struct.remapkeys!
215
+ if struct.has_key? :user and struct.has_key? :pass
216
+ rt = RT_Client.new(:user => struct[:user], :pass => struct[:pass])
217
+ else
218
+ rt = RT_Client.new
219
+ end
220
+ val = rt.list(struct)
221
+ rt = nil
222
+ val
223
+ end
224
+
225
+ # Gets a list of tickets via RT_Client::query
226
+ def query(struct)
227
+ struct.remapkeys!
228
+ if struct.has_key? :user and struct.has_key? :pass
229
+ rt = RT_Client.new(:user => struct[:user], :pass => struct[:pass])
230
+ else
231
+ rt = RT_Client.new
232
+ end
233
+ val = rt.query(struct)
234
+ rt = nil
235
+ val
236
+ end
237
+
238
+ # Gets detail (minus history/attachments) via RT_Client::show
239
+ def show(struct)
240
+ struct.remapkeys!
241
+ if struct.has_key? :user and struct.has_key? :pass
242
+ rt = RT_Client.new(:user => struct[:user], :pass => struct[:pass])
243
+ else
244
+ rt = RT_Client.new
245
+ end
246
+ val = rt.show(struct)
247
+ rt = nil
248
+ val
249
+ end
250
+
251
+ end # class TicketSrv
252
+
253
+ pid = fork do
254
+ Signal.trap('HUP','IGNORE')
255
+ # set up a log file
256
+ logfile = File.dirname(__FILE__) + "/ticketsrv.log"
257
+ accfile = File.dirname(__FILE__) + "/access.log"
258
+ acc = File.open(accfile,"a+")
259
+ $stderr.reopen acc # redirect $stderr to the log as well
260
+ # determine the IP address to listen on and create the server
261
+ sock = Socket.getaddrinfo(Socket.gethostname,PORT,Socket::AF_INET,Socket::SOCK_STREAM)
262
+ $s = XMLRPC::Server.new(sock[0][1], sock[0][3], MAX_CONN, logfile)
263
+ $s.set_parser(XMLRPC::XMLParser::XMLStreamParser.new)
264
+ $s.add_handler(TicketSrv::INTERFACE, TicketSrv.new)
265
+ $s.add_introspection
266
+ $s.serve # start serving
267
+ $stderr.reopen STDERR
268
+ acc.close
269
+ end
270
+ Process.detach(pid)
271
+
@@ -0,0 +1,3 @@
1
+ class Roust
2
+ VERSION = '1.0.0'
3
+ end