roust 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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