synaptic4r 0.1.5 → 0.1.6
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.
- data/README.rdoc +4 -6
- data/Rakefile +8 -3
- data/VERSION +1 -1
- data/lib/synaptic4r/rest.rb +26 -12
- data/lib/synaptic4r/result.rb +40 -20
- data/lib/synaptic4r.rb +1 -0
- data/synaptic4r.gemspec +29 -4
- data/test/create_dir_messages.rb +34 -0
- data/test/create_dir_test.rb +28 -0
- data/test/create_file_messages.rb +68 -0
- data/test/create_file_test.rb +45 -0
- data/test/get_messages.rb +116 -0
- data/test/get_test.rb +78 -0
- data/test/helper.rb +31 -0
- data/test/matchers.rb +28 -0
- data/test/mock.rb +58 -0
- data/test/test.txt +16 -0
- metadata +23 -5
data/README.rdoc
CHANGED
@@ -1,12 +1,10 @@
|
|
1
1
|
= synaptic4r
|
2
2
|
|
3
|
-
Ruby
|
4
|
-
onto the REST API and can be used to inspect request headers and payloads, as well as,
|
5
|
-
a reference for the REST API.
|
3
|
+
Ruby CLI for ATT Synaptic Storage.
|
6
4
|
|
7
5
|
== Install
|
8
6
|
|
9
|
-
The synptic4r gem is in the gemcutter.org repository. If gemcutter.org is not in your gem sources
|
7
|
+
The synptic4r gem is in the http://gemcutter.org repository. If gemcutter.org is not in your gem sources
|
10
8
|
issue the following command only one time,
|
11
9
|
|
12
10
|
sudo gem source -a http://gemcutter.org
|
@@ -65,11 +63,11 @@ upload a file to directory foo
|
|
65
63
|
|
66
64
|
synrest create-file file.txt foo/
|
67
65
|
|
68
|
-
list contents remote directory foo
|
66
|
+
list contents for remote directory foo
|
69
67
|
|
70
68
|
synrest get foo
|
71
69
|
|
72
|
-
list contents remote file foo/file.txt
|
70
|
+
list contents for remote file foo/file.txt
|
73
71
|
|
74
72
|
synrest get foo/file.txt
|
75
73
|
|
data/Rakefile
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'rake'
|
3
3
|
|
4
|
+
#####-------------------------------------------------------------------------------------------------------
|
4
5
|
begin
|
5
6
|
require 'jeweler'
|
6
7
|
Jeweler::Tasks.new do |gem|
|
@@ -12,10 +13,15 @@ begin
|
|
12
13
|
gem.add_dependency('rest-client', '>= 1.0.2')
|
13
14
|
end
|
14
15
|
|
16
|
+
Jeweler::GemcutterTasks.new
|
17
|
+
|
15
18
|
rescue LoadError
|
16
19
|
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
17
20
|
end
|
18
21
|
|
22
|
+
task :default => :test
|
23
|
+
|
24
|
+
#####-------------------------------------------------------------------------------------------------------
|
19
25
|
require 'rake/testtask'
|
20
26
|
Rake::TestTask.new(:test) do |test|
|
21
27
|
test.libs << 'lib' << 'test'
|
@@ -23,6 +29,7 @@ Rake::TestTask.new(:test) do |test|
|
|
23
29
|
test.verbose = true
|
24
30
|
end
|
25
31
|
|
32
|
+
#####-------------------------------------------------------------------------------------------------------
|
26
33
|
begin
|
27
34
|
require 'rcov/rcovtask'
|
28
35
|
Rcov::RcovTask.new do |test|
|
@@ -36,9 +43,7 @@ rescue LoadError
|
|
36
43
|
end
|
37
44
|
end
|
38
45
|
|
39
|
-
|
40
|
-
task :default => :test
|
41
|
-
|
46
|
+
#####-------------------------------------------------------------------------------------------------------
|
42
47
|
require 'rake/rdoctask'
|
43
48
|
Rake::RDocTask.new do |rdoc|
|
44
49
|
if File.exist?('VERSION.yml')
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.6
|
data/lib/synaptic4r/rest.rb
CHANGED
@@ -25,7 +25,12 @@ module Synaptic4r
|
|
25
25
|
|
26
26
|
#.......................................................................................................
|
27
27
|
def read_file(file, offset, length)
|
28
|
-
|
28
|
+
case file
|
29
|
+
when String
|
30
|
+
IO.read(file, length, offset)
|
31
|
+
else
|
32
|
+
file.read
|
33
|
+
end
|
29
34
|
end
|
30
35
|
|
31
36
|
#### Utils
|
@@ -217,19 +222,23 @@ module Synaptic4r
|
|
217
222
|
build_service_url(args)
|
218
223
|
add_header_attr(args)
|
219
224
|
create_signature
|
220
|
-
|
221
|
-
self.send(meth, args)
|
222
|
-
else
|
223
|
-
if args[:dump].nil? and args[:payload].nil?
|
224
|
-
RestClient::Request.execute(:method => self.class.http_method(meth), :url => url,
|
225
|
-
:headers => headers, :payload => payload)
|
226
|
-
end
|
227
|
-
end
|
228
|
-
self.class.result_class(meth).new(:result => res, :headers => headers, :url => url, :sign => sign,
|
225
|
+
self.class.result_class(meth).new(:result => http_request(args), :headers => headers, :url => url, :sign => sign,
|
229
226
|
:http_request => self.class.http_method(meth),
|
230
227
|
:payload => args[:payload] ? payload : nil)
|
231
228
|
end
|
232
229
|
|
230
|
+
#.......................................................................................................
|
231
|
+
def http_request(args)
|
232
|
+
if self.respond_to?(meth)
|
233
|
+
self.send(meth, args)
|
234
|
+
else
|
235
|
+
if args[:dump].nil? and args[:payload].nil?
|
236
|
+
RestClient::Request.execute(:method => self.class.http_method(meth), :url => url,
|
237
|
+
:headers => headers, :payload => payload)
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
233
242
|
#.......................................................................................................
|
234
243
|
def exclusive_args_given?(exclusive_args, args)
|
235
244
|
exclusive_args.each do |alist|
|
@@ -276,7 +285,7 @@ module Synaptic4r
|
|
276
285
|
#.......................................................................................................
|
277
286
|
def create_signature
|
278
287
|
@sign = create_sign_string
|
279
|
-
digest = OpenSSL::HMAC.digest(OpenSSL::Digest.new
|
288
|
+
digest = OpenSSL::HMAC.digest(OpenSSL::Digest::SHA1.new, Base64.decode64(key), sign)
|
280
289
|
headers['x-emc-signature'] = Base64.encode64(digest.to_s()).chomp()
|
281
290
|
end
|
282
291
|
|
@@ -310,7 +319,12 @@ module Synaptic4r
|
|
310
319
|
#.......................................................................................................
|
311
320
|
def extent(file, begin_offset, end_offset)
|
312
321
|
if file
|
313
|
-
file_offset =
|
322
|
+
file_offset = case file
|
323
|
+
when String then File.size(file)
|
324
|
+
when File then file.stat.size
|
325
|
+
else
|
326
|
+
file.size
|
327
|
+
end - 1
|
314
328
|
offset = begin_offset.to_i
|
315
329
|
end_offset = end_offset.nil? ? file_offset : end_offset.to_i
|
316
330
|
end_offset = file_offset if end_offset > file_offset
|
data/lib/synaptic4r/result.rb
CHANGED
@@ -5,7 +5,7 @@ module Synaptic4r
|
|
5
5
|
class Result
|
6
6
|
|
7
7
|
#.......................................................................................................
|
8
|
-
attr_reader :headers, :url, :http_request, :sign, :payload
|
8
|
+
attr_reader :headers, :url, :http_request, :sign, :payload, :result
|
9
9
|
|
10
10
|
#.......................................................................................................
|
11
11
|
def initialize(args)
|
@@ -14,13 +14,21 @@ module Synaptic4r
|
|
14
14
|
@url = args[:url]
|
15
15
|
@sign = args[:sign]
|
16
16
|
@payload = args[:payload]
|
17
|
+
@result = {}
|
17
18
|
end
|
18
19
|
|
19
20
|
#.......................................................................................................
|
20
21
|
def print
|
21
22
|
end
|
22
23
|
|
23
|
-
|
24
|
+
#.........................................................................................................
|
25
|
+
def method_missing(meth, *args, &blk)
|
26
|
+
if result.kind_of?(Hash) and result.keys.include?(meth)
|
27
|
+
result[meth]
|
28
|
+
else
|
29
|
+
result.send(meth, *args, &blk)
|
30
|
+
end
|
31
|
+
end
|
24
32
|
|
25
33
|
#.......................................................................................................
|
26
34
|
def extract_header(args, header)
|
@@ -58,17 +66,18 @@ module Synaptic4r
|
|
58
66
|
def initialize(args)
|
59
67
|
super
|
60
68
|
if args[:result]
|
61
|
-
|
62
|
-
@
|
63
|
-
|
64
|
-
|
69
|
+
location = args[:result].headers[:location]
|
70
|
+
@result = {:oid => /\/rest\/objects\/(.*)/.match(location).captures.first,
|
71
|
+
:location => location,
|
72
|
+
:size => args[:result].headers[:x_emc_delta],
|
73
|
+
:date => args[:result].headers[:date]}
|
65
74
|
end
|
66
75
|
end
|
67
76
|
|
68
77
|
#.......................................................................................................
|
69
78
|
def print
|
70
|
-
(
|
71
|
-
(
|
79
|
+
(oid.nil? ? '' : "OID: #{oid}\n") +
|
80
|
+
(size.nil? ? '' : "size: #{size} bytes")
|
72
81
|
end
|
73
82
|
|
74
83
|
#Upload
|
@@ -77,6 +86,9 @@ module Synaptic4r
|
|
77
86
|
##########################################################################################################
|
78
87
|
class UserMetadata < Result
|
79
88
|
|
89
|
+
#.......................................................................................................
|
90
|
+
attr_reader :metadata, :listable_metadata
|
91
|
+
|
80
92
|
#.......................................................................................................
|
81
93
|
def initialize(args)
|
82
94
|
super
|
@@ -101,6 +113,9 @@ module Synaptic4r
|
|
101
113
|
##########################################################################################################
|
102
114
|
class SystemMetadata < Result
|
103
115
|
|
116
|
+
#.......................................................................................................
|
117
|
+
attr_reader :metadata
|
118
|
+
|
104
119
|
#.......................................................................................................
|
105
120
|
def initialize(args)
|
106
121
|
super
|
@@ -121,6 +136,9 @@ module Synaptic4r
|
|
121
136
|
##########################################################################################################
|
122
137
|
class Tags < Result
|
123
138
|
|
139
|
+
#.......................................................................................................
|
140
|
+
attr_reader :listable_tags
|
141
|
+
|
124
142
|
#.......................................................................................................
|
125
143
|
def initialize(args)
|
126
144
|
super
|
@@ -140,6 +158,9 @@ module Synaptic4r
|
|
140
158
|
##########################################################################################################
|
141
159
|
class Acl < Result
|
142
160
|
|
161
|
+
#.......................................................................................................
|
162
|
+
attr_reader :user_acl, :group_acl
|
163
|
+
|
143
164
|
#.......................................................................................................
|
144
165
|
def initialize(args)
|
145
166
|
super
|
@@ -174,8 +195,6 @@ module Synaptic4r
|
|
174
195
|
poids.inject("") {|r,o| r += " #{o}\n"} unless poids.empty?
|
175
196
|
end
|
176
197
|
|
177
|
-
private
|
178
|
-
|
179
198
|
#.......................................................................................................
|
180
199
|
def oids
|
181
200
|
@versions.elements.to_a('ObjectID').map{|o| o.text}
|
@@ -214,8 +233,6 @@ module Synaptic4r
|
|
214
233
|
end
|
215
234
|
end
|
216
235
|
|
217
|
-
private
|
218
|
-
|
219
236
|
#.......................................................................................................
|
220
237
|
def oids(ols)
|
221
238
|
ols.map{|o| o.elements.to_a('ObjectID').first.text}
|
@@ -253,26 +270,29 @@ module Synaptic4r
|
|
253
270
|
def initialize(args)
|
254
271
|
super
|
255
272
|
if args[:result]
|
256
|
-
@
|
257
|
-
@
|
273
|
+
@body = args[:result].net_http_res.body
|
274
|
+
@result[:content_type] = args[:result].headers[:content_type]
|
275
|
+
if content_type.eql?('text/xml')
|
276
|
+
@result[:directory] = directory_entries
|
277
|
+
else
|
278
|
+
@result[:file] = @body
|
279
|
+
end
|
258
280
|
end
|
259
281
|
end
|
260
282
|
|
261
283
|
#.......................................................................................................
|
262
284
|
def print
|
263
|
-
if
|
285
|
+
if content_type.eql?('text/xml')
|
264
286
|
print_directory_entries
|
265
287
|
else
|
266
288
|
@body
|
267
289
|
end
|
268
290
|
end
|
269
291
|
|
270
|
-
private
|
271
|
-
|
272
292
|
#.......................................................................................................
|
273
293
|
def directory_entries
|
274
294
|
REXML::Document.new(@body).root.elements.to_a.first.elements.to_a.map do |i|
|
275
|
-
i.elements.inject(nil, {}){|h,e| h.update(e.name => e.text)}
|
295
|
+
i.elements.inject(nil, {}){|h,e| h.update(e.name.downcase.to_sym => e.text)}
|
276
296
|
end
|
277
297
|
end
|
278
298
|
|
@@ -283,8 +303,8 @@ module Synaptic4r
|
|
283
303
|
fmt = "%-30s %-10s %-s\n"
|
284
304
|
fmt % ['Name', 'Type', 'OID'] +
|
285
305
|
dir_list.inject("") do |r,e|
|
286
|
-
t = e[
|
287
|
-
r += fmt % [e[
|
306
|
+
t = e[:filetype]
|
307
|
+
r += fmt % [e[:filename], (t.eql?('regular') ? 'file' : t), e[:objectid]]
|
288
308
|
end
|
289
309
|
end
|
290
310
|
end
|
data/lib/synaptic4r.rb
CHANGED
data/synaptic4r.gemspec
CHANGED
@@ -1,12 +1,15 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
1
4
|
# -*- encoding: utf-8 -*-
|
2
5
|
|
3
6
|
Gem::Specification.new do |s|
|
4
7
|
s.name = %q{synaptic4r}
|
5
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.6"
|
6
9
|
|
7
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
11
|
s.authors = ["troystribling-att"]
|
9
|
-
s.date = %q{2009-
|
12
|
+
s.date = %q{2009-12-02}
|
10
13
|
s.default_executable = %q{synrest}
|
11
14
|
s.email = %q{troy.stribling@usi.com}
|
12
15
|
s.executables = ["synrest"]
|
@@ -28,13 +31,34 @@ Gem::Specification.new do |s|
|
|
28
31
|
"lib/synaptic4r/request.rb",
|
29
32
|
"lib/synaptic4r/rest.rb",
|
30
33
|
"lib/synaptic4r/result.rb",
|
31
|
-
"synaptic4r.gemspec"
|
34
|
+
"synaptic4r.gemspec",
|
35
|
+
"test/create_dir_messages.rb",
|
36
|
+
"test/create_dir_test.rb",
|
37
|
+
"test/create_file_messages.rb",
|
38
|
+
"test/create_file_test.rb",
|
39
|
+
"test/get_messages.rb",
|
40
|
+
"test/get_test.rb",
|
41
|
+
"test/helper.rb",
|
42
|
+
"test/matchers.rb",
|
43
|
+
"test/mock.rb",
|
44
|
+
"test/test.txt"
|
32
45
|
]
|
33
46
|
s.homepage = %q{http://github.com/attsynaptic/synaptic4r}
|
34
47
|
s.rdoc_options = ["--charset=UTF-8"]
|
35
48
|
s.require_paths = ["lib"]
|
36
|
-
s.rubygems_version = %q{1.3.
|
49
|
+
s.rubygems_version = %q{1.3.5}
|
37
50
|
s.summary = %q{CLI and Ruby REST Client for ATT Synaptic Storage}
|
51
|
+
s.test_files = [
|
52
|
+
"test/get_messages.rb",
|
53
|
+
"test/create_file_messages.rb",
|
54
|
+
"test/get_test.rb",
|
55
|
+
"test/create_dir_messages.rb",
|
56
|
+
"test/helper.rb",
|
57
|
+
"test/create_dir_test.rb",
|
58
|
+
"test/create_file_test.rb",
|
59
|
+
"test/mock.rb",
|
60
|
+
"test/matchers.rb"
|
61
|
+
]
|
38
62
|
|
39
63
|
if s.respond_to? :specification_version then
|
40
64
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
@@ -49,3 +73,4 @@ Gem::Specification.new do |s|
|
|
49
73
|
s.add_dependency(%q<rest-client>, [">= 1.0.2"])
|
50
74
|
end
|
51
75
|
end
|
76
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
#########################################################################################################
|
2
|
+
module CreateDirMessages
|
3
|
+
|
4
|
+
#......................................................................................................
|
5
|
+
@oid, @date = 'DIROID', "Thu, 10 Sep 2009 17:34:30 GMT"
|
6
|
+
|
7
|
+
####---------------------------------------------------------------------------------------------------
|
8
|
+
class << self
|
9
|
+
|
10
|
+
#......................................................................................................
|
11
|
+
attr_reader :oid, :date
|
12
|
+
|
13
|
+
#......................................................................................................
|
14
|
+
def request(args)
|
15
|
+
{:url => "#{args[:site]}/namespace/#{args[:rpath]}",
|
16
|
+
:http_request => :post,
|
17
|
+
:headers => {'content-type' => 'application/octet-stream'},
|
18
|
+
:payload => nil}
|
19
|
+
end
|
20
|
+
|
21
|
+
#......................................................................................................
|
22
|
+
def response(args)
|
23
|
+
HttpMessages::Result.new(:headers=> {:x_emc_delta => 0,
|
24
|
+
:date => date,
|
25
|
+
:content_type => "text/plain; charset=UTF-8",
|
26
|
+
:location => "/rest/objects/#{oid}"},
|
27
|
+
:body => '')
|
28
|
+
end
|
29
|
+
|
30
|
+
#### self
|
31
|
+
end
|
32
|
+
|
33
|
+
### HttpMessages
|
34
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
##############################################################################################################
|
2
|
+
require 'helper'
|
3
|
+
|
4
|
+
##############################################################################################################
|
5
|
+
class CreateDirTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
#.........................................................................................................
|
8
|
+
def setup
|
9
|
+
@args, @client = client
|
10
|
+
end
|
11
|
+
|
12
|
+
#.........................................................................................................
|
13
|
+
should "build request to create directory with specified name" do
|
14
|
+
a = @args.merge({:rpath=>'newdir'})
|
15
|
+
@client.create_dir(a).should send_request(CreateDirMessages.request(a))
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
#.........................................................................................................
|
20
|
+
should "return OID, location and creation date for created directory" do
|
21
|
+
a = @args.merge({:rpath=>'newdir'})
|
22
|
+
res = @client.create_dir(a)
|
23
|
+
res[:oid].should be(CreateDirMessages.oid)
|
24
|
+
res[:location].should be("/rest/objects/#{CreateDirMessages.oid}")
|
25
|
+
res[:date].should be(CreateDirMessages.date)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
#########################################################################################################
|
2
|
+
module CreateFileMessages
|
3
|
+
|
4
|
+
#......................................................................................................
|
5
|
+
@oid, @date = 'FILEOID', "Thu, 10 Sep 2009 17:34:30 GMT"
|
6
|
+
|
7
|
+
####---------------------------------------------------------------------------------------------------
|
8
|
+
class << self
|
9
|
+
|
10
|
+
#......................................................................................................
|
11
|
+
attr_reader :oid, :date, :full_payload, :partial_payload, :full_size
|
12
|
+
attr_accessor :response_method
|
13
|
+
|
14
|
+
#......................................................................................................
|
15
|
+
def namespace_request(args)
|
16
|
+
full_payload = args[:file].kind_of?(String) ? IO.read(args[:file]) : (args[:file].rewind; args[:file].read)
|
17
|
+
@full_size = full_payload.length
|
18
|
+
full_content_md5 = Base64.encode64(Digest::MD5.digest(full_payload)).chomp()
|
19
|
+
{:url => "#{args[:site]}/namespace/#{args[:rpath]}",
|
20
|
+
:http_request => :post,
|
21
|
+
:headers => {'content-length' => full_size,
|
22
|
+
'content-md5' => full_content_md5,
|
23
|
+
'content-type' => 'application/octet-stream'},
|
24
|
+
:payload => full_payload}
|
25
|
+
end
|
26
|
+
|
27
|
+
#......................................................................................................
|
28
|
+
def listable_metadata_request(args)
|
29
|
+
full_payload = IO.read(args[:file])
|
30
|
+
@full_size = full_payload.length
|
31
|
+
full_content_md5 = Base64.encode64(Digest::MD5.digest(full_payload)).chomp()
|
32
|
+
{:url => "#{args[:site]}/objects",
|
33
|
+
:http_request => :post,
|
34
|
+
:headers => {'content-length' => full_size,
|
35
|
+
'content-md5' => full_content_md5,
|
36
|
+
'x-emc-listable-meta' => args[:listable_meta],
|
37
|
+
'content-type' => 'application/octet-stream'},
|
38
|
+
:payload => full_payload}
|
39
|
+
end
|
40
|
+
|
41
|
+
#......................................................................................................
|
42
|
+
def response(args)
|
43
|
+
send(response_method, args) if respond_to?(response_method)
|
44
|
+
end
|
45
|
+
|
46
|
+
#......................................................................................................
|
47
|
+
def file_response(args)
|
48
|
+
HttpMessages::Result.new(:headers=> {:x_emc_delta => full_size,
|
49
|
+
:date => date,
|
50
|
+
:content_type => "text/plain; charset=UTF-8",
|
51
|
+
:location => "/rest/objects/#{oid}"},
|
52
|
+
:body => '')
|
53
|
+
end
|
54
|
+
|
55
|
+
#......................................................................................................
|
56
|
+
def file_offset_response(args)
|
57
|
+
HttpMessages::Result.new(:headers=> {:x_emc_delta => args[:endoffset]-args[:beginoffset]+1,
|
58
|
+
:date => date,
|
59
|
+
:content_type => 'text/plain; charset=UTF-8',
|
60
|
+
:location => "/rest/objects/#{oid}"},
|
61
|
+
:body => '')
|
62
|
+
end
|
63
|
+
|
64
|
+
#### self
|
65
|
+
end
|
66
|
+
|
67
|
+
### HttpMessages
|
68
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
##############################################################################################################
|
2
|
+
require 'helper'
|
3
|
+
|
4
|
+
##############################################################################################################
|
5
|
+
class CreateFileTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
#.........................................................................................................
|
8
|
+
def setup
|
9
|
+
@args, @client = client
|
10
|
+
end
|
11
|
+
|
12
|
+
#.........................................................................................................
|
13
|
+
should "build request to create file with specified name and read entire file from disk when local file name is specified" do
|
14
|
+
CreateFileMessages.response_method = :file_response
|
15
|
+
a = @args.merge({:rpath=>'test.text', :file => 'test/test.txt', :payload => true})
|
16
|
+
@client.create_file(a).should send_request(CreateFileMessages.namespace_request(a))
|
17
|
+
end
|
18
|
+
|
19
|
+
#.........................................................................................................
|
20
|
+
should "build request to create file with specified listable metadata and read entire file from disk when local file name is specified" do
|
21
|
+
CreateFileMessages.response_method = :file_response
|
22
|
+
a = @args.merge({:listable_meta=>'test', :file => 'test/test.txt', :payload => true})
|
23
|
+
@client.create_file(a).should send_request(CreateFileMessages.listable_metadata_request(a))
|
24
|
+
end
|
25
|
+
|
26
|
+
#.........................................................................................................
|
27
|
+
should "build request to create file with specified name and read entire file from disk when file IO object specified" do
|
28
|
+
CreateFileMessages.response_method = :file_response
|
29
|
+
full_payload = File.new('test/test.txt')
|
30
|
+
a = @args.merge({:rpath=>'test.text', :file => full_payload, :payload => true})
|
31
|
+
@client.create_file(a).should send_request(CreateFileMessages.namespace_request(a))
|
32
|
+
end
|
33
|
+
|
34
|
+
#.........................................................................................................
|
35
|
+
should "return OID, location and creation date for created file when entire file is uploaded" do
|
36
|
+
CreateFileMessages.response_method = :file_response
|
37
|
+
a = @args.merge({:listable_meta=>'test', :file => 'test/test.txt', :payload => true})
|
38
|
+
res = @client.create_file(a)
|
39
|
+
res[:oid].should be(CreateFileMessages.oid)
|
40
|
+
res[:location].should be("/rest/objects/#{CreateFileMessages.oid}")
|
41
|
+
res[:date].should be(CreateFileMessages.date)
|
42
|
+
res[:size].should be(CreateFileMessages.full_size)
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
#########################################################################################################
|
2
|
+
module GetMessages
|
3
|
+
|
4
|
+
#......................................................................................................
|
5
|
+
@date = "Thu, 10 Sep 2009 17:34:30 GMT"
|
6
|
+
|
7
|
+
@get_dir_result =[{:objectid=>'OID1', :filetype=>'directory', :filename=>'lib'},
|
8
|
+
{:objectid=>'OID2', :filetype=>'regular', :filename=>'file1.rb'},
|
9
|
+
{:objectid=>'OID3', :filetype=>'regular', :filename=>'file2.rb'}]
|
10
|
+
|
11
|
+
@get_dir_body = <<-BODY
|
12
|
+
<?xml version='1.0' encoding='UTF-8'?>
|
13
|
+
<ListDirectoryResponse xmlns='http://www.emc.com/cos/'>
|
14
|
+
<DirectoryList>
|
15
|
+
<DirectoryEntry>
|
16
|
+
<ObjectID>#{@get_dir_result[0][:objectid]}</ObjectID>
|
17
|
+
<FileType>#{@get_dir_result[0][:filetype]}</FileType>
|
18
|
+
<Filename>#{@get_dir_result[0][:filename]}</Filename>
|
19
|
+
</DirectoryEntry>
|
20
|
+
<DirectoryEntry>
|
21
|
+
<ObjectID>#{@get_dir_result[1][:objectid]}</ObjectID>
|
22
|
+
<FileType>#{@get_dir_result[1][:filetype]}</FileType>
|
23
|
+
<Filename>#{@get_dir_result[1][:filename]}</Filename>
|
24
|
+
</DirectoryEntry>
|
25
|
+
<DirectoryEntry>
|
26
|
+
<ObjectID>#{@get_dir_result[2][:objectid]}</ObjectID>
|
27
|
+
<FileType>#{@get_dir_result[2][:filetype]}</FileType>
|
28
|
+
<Filename>#{@get_dir_result[2][:filename]}</Filename>
|
29
|
+
</DirectoryEntry>
|
30
|
+
</DirectoryList>
|
31
|
+
</ListDirectoryResponse>
|
32
|
+
BODY
|
33
|
+
|
34
|
+
####---------------------------------------------------------------------------------------------------
|
35
|
+
class << self
|
36
|
+
|
37
|
+
#......................................................................................................
|
38
|
+
attr_reader :date, :get_dir_body, :get_dir_result, :get_dir_oid
|
39
|
+
attr_accessor :response_method
|
40
|
+
|
41
|
+
#......................................................................................................
|
42
|
+
def response(args)
|
43
|
+
send(response_method, args) if respond_to?(response_method)
|
44
|
+
end
|
45
|
+
|
46
|
+
#......................................................................................................
|
47
|
+
# get directory messages
|
48
|
+
#......................................................................................................
|
49
|
+
def dir_namespace_request(args)
|
50
|
+
{:url => "#{args[:site]}/namespace/#{args[:rpath]}",
|
51
|
+
:http_request => :get,
|
52
|
+
:headers => {'content-type' => 'application/octet-stream'},
|
53
|
+
:payload => nil}
|
54
|
+
end
|
55
|
+
|
56
|
+
#......................................................................................................
|
57
|
+
def dir_objects_request(args)
|
58
|
+
{:url => "#{args[:site]}/objects/#{args[:oid]}",
|
59
|
+
:http_request => :get,
|
60
|
+
:headers => {'content-type' => 'application/octet-stream'},
|
61
|
+
:payload => nil}
|
62
|
+
end
|
63
|
+
|
64
|
+
#......................................................................................................
|
65
|
+
def dir_response(args)
|
66
|
+
HttpMessages::Result.new(:headers => {:content_type=> "text/xml"},
|
67
|
+
:body => get_dir_body)
|
68
|
+
end
|
69
|
+
|
70
|
+
#......................................................................................................
|
71
|
+
# get file messages
|
72
|
+
#......................................................................................................
|
73
|
+
def file_namespace_request(args)
|
74
|
+
{:url => "#{args[:site]}/namespace/#{args[:rpath]}",
|
75
|
+
:http_request => :get,
|
76
|
+
:headers => {'content-type' => 'application/octet-stream'},
|
77
|
+
:payload => nil}
|
78
|
+
end
|
79
|
+
|
80
|
+
#......................................................................................................
|
81
|
+
def file_namespace_with_offset_request(args)
|
82
|
+
{:url => "#{args[:site]}/namespace/#{args[:rpath]}",
|
83
|
+
:http_request => :get,
|
84
|
+
:headers => {'endoffset' => args[:endoffset],
|
85
|
+
'beginoffset' => args[:beginoffset],
|
86
|
+
'range' =>"bytes=#{args[:beginoffset]}-#{args[:endoffset]}",
|
87
|
+
'content-type' => 'application/octet-stream'},
|
88
|
+
:payload => nil}
|
89
|
+
end
|
90
|
+
|
91
|
+
#......................................................................................................
|
92
|
+
def file_objects_request(args)
|
93
|
+
{:url => "#{args[:site]}/objects/#{args[:oid]}",
|
94
|
+
:http_request => :get,
|
95
|
+
:headers => {'content-type' => 'application/octet-stream'},
|
96
|
+
:payload => nil}
|
97
|
+
end
|
98
|
+
|
99
|
+
#......................................................................................................
|
100
|
+
def file_response(args)
|
101
|
+
HttpMessages::Result.new(:headers => {:content_type=> "text/xml"},
|
102
|
+
:body => get_dir_body)
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
#......................................................................................................
|
107
|
+
def file_offset_response(args)
|
108
|
+
HttpMessages::Result.new(:headers => {:content_type=> "text/xml"},
|
109
|
+
:body => get_dir_body)
|
110
|
+
end
|
111
|
+
|
112
|
+
#### self
|
113
|
+
end
|
114
|
+
|
115
|
+
### GetDirMessages
|
116
|
+
end
|
data/test/get_test.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
##############################################################################################################
|
2
|
+
require 'helper'
|
3
|
+
|
4
|
+
##############################################################################################################
|
5
|
+
class GetTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
#.........................................................................................................
|
8
|
+
def setup
|
9
|
+
@args, @client = client
|
10
|
+
end
|
11
|
+
|
12
|
+
#.........................................................................................................
|
13
|
+
# get directory test cases
|
14
|
+
#.........................................................................................................
|
15
|
+
should "build request to get directory with specified name" do
|
16
|
+
GetMessages.response_method = :dir_response
|
17
|
+
a = @args.merge({:rpath=> 'getdir'})
|
18
|
+
@client.get(a).should send_request(GetMessages.dir_namespace_request(a))
|
19
|
+
end
|
20
|
+
|
21
|
+
#.........................................................................................................
|
22
|
+
should "build request to get directory with specified OID" do
|
23
|
+
GetMessages.response_method = :dir_response
|
24
|
+
a = @args.merge({:oid=> 'DIROID'})
|
25
|
+
@client.get(a).should send_request(GetMessages.dir_objects_request(a))
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
#.........................................................................................................
|
30
|
+
should "return a list of information containing OID, object type and name for each object in directory when directory name is specified" do
|
31
|
+
GetMessages.response_method = :dir_response
|
32
|
+
a = @args.merge({:rpath=> 'getdir'})
|
33
|
+
res = @client.get(a)
|
34
|
+
res[:directory].length.should be(3)
|
35
|
+
res[:directory][0].should be(GetMessages.get_dir_result[0])
|
36
|
+
res[:directory][1].should be(GetMessages.get_dir_result[1])
|
37
|
+
res[:directory][2].should be(GetMessages.get_dir_result[2])
|
38
|
+
end
|
39
|
+
|
40
|
+
#.........................................................................................................
|
41
|
+
# get file test cases
|
42
|
+
#.........................................................................................................
|
43
|
+
should "build request to get entire file with specified name" do
|
44
|
+
GetMessages.response_method = :file_response
|
45
|
+
a = @args.merge({:rpath=> 'getfile'})
|
46
|
+
@client.get(a).should send_request(GetMessages.file_namespace_request(a))
|
47
|
+
end
|
48
|
+
|
49
|
+
#.........................................................................................................
|
50
|
+
should "build request to get portion of file with specified name and byte offsets" do
|
51
|
+
GetMessages.response_method = :file_response
|
52
|
+
a = @args.merge({:rpath=> 'getdir/getfile', :beginoffset=>10, :endoffset=>110})
|
53
|
+
@client.get(a).should send_request(GetMessages.file_namespace_with_offset_request(a))
|
54
|
+
end
|
55
|
+
|
56
|
+
#.........................................................................................................
|
57
|
+
should "build request to get entire file with specified OID" do
|
58
|
+
GetMessages.response_method = :file_response
|
59
|
+
a = @args.merge({:oid=> 'FILEOID'})
|
60
|
+
@client.get(a).should send_request(GetMessages.file_objects_request(a))
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
#.........................................................................................................
|
65
|
+
should "return the entire file if only the file name is specified" do
|
66
|
+
GetMessages.response_method = :file_response
|
67
|
+
a = @args.merge({:rpath=> 'getfile'})
|
68
|
+
res = @client.get(a)
|
69
|
+
end
|
70
|
+
|
71
|
+
#.........................................................................................................
|
72
|
+
should "return the a portion of the file if the file name and file offsets are specified" do
|
73
|
+
GetMessages.response_method = :file_response
|
74
|
+
a = @args.merge({:rpath=> 'getfile', :beginoffset=>10, :endoffset=>110})
|
75
|
+
res = @client.get(a)
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
#####-------------------------------------------------------------------------------------------------------
|
2
|
+
require 'test/unit'
|
3
|
+
require 'rubygems'
|
4
|
+
begin
|
5
|
+
require 'shoulda'
|
6
|
+
rescue LoadError
|
7
|
+
abort "shoulda is not available: sudo gem install thoughtbot-shoulda --source=http://gems.github.com"
|
8
|
+
end
|
9
|
+
begin
|
10
|
+
require 'matchy'
|
11
|
+
rescue LoadError
|
12
|
+
abort "matchy is not available: sudo gem install mhennemeyer-matchy --source=http://gems.github.com"
|
13
|
+
end
|
14
|
+
|
15
|
+
#####-------------------------------------------------------------------------------------------------------
|
16
|
+
$:.unshift('lib')
|
17
|
+
require 'rubygems'
|
18
|
+
require 'synaptic4r'
|
19
|
+
|
20
|
+
#####-------------------------------------------------------------------------------------------------------
|
21
|
+
require 'mock'
|
22
|
+
require 'matchers'
|
23
|
+
Dir["test/*_messages.rb"].each{|f| require f}
|
24
|
+
|
25
|
+
|
26
|
+
#.........................................................................................................
|
27
|
+
def client
|
28
|
+
args = {:key=>'thesecret', :site=>'https://nowhere.com', :subtenant=>'abcdef1245', :uid=>'noone'}
|
29
|
+
client = Synaptic4r::Client.new(args)
|
30
|
+
[args, client]
|
31
|
+
end
|
data/test/matchers.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
####------------------------------------------------------------------------------------------------------
|
2
|
+
def_matcher :send_request do |receiver, matcher, args|
|
3
|
+
matched, exp = true, args.first
|
4
|
+
pos_msg, neg_msg = '', ''
|
5
|
+
receiver.headers.delete('x-emc-date')
|
6
|
+
receiver.headers.delete('date')
|
7
|
+
receiver.headers.delete('x-emc-signature')
|
8
|
+
receiver.headers.delete('accept')
|
9
|
+
receiver.headers.delete('x-emc-uid')
|
10
|
+
unless exp[:headers].eql?(receiver.headers)
|
11
|
+
pos_msg << "Expected 'headers' #{exp[:headers].inspect}, but found #{receiver.headers.inspect}\n"
|
12
|
+
matched = false
|
13
|
+
end
|
14
|
+
unless exp[:url].eql?(receiver.url)
|
15
|
+
pos_msg << "Expected 'url' of #{exp[:url]}, but found #{receiver.url}\n"
|
16
|
+
matched = false
|
17
|
+
end
|
18
|
+
unless exp[:payload].eql?(receiver.payload)
|
19
|
+
pos_msg << "Expected 'payload' of #{exp[:payload]}, but found #{receiver.payload}\n"
|
20
|
+
matched = false
|
21
|
+
end
|
22
|
+
unless exp[:http_request].eql?(receiver.http_request)
|
23
|
+
pos_msg << "Expected 'http_request' of #{exp[:http_request]}, but found #{receiver.http_request}\n"
|
24
|
+
matched = false
|
25
|
+
end
|
26
|
+
matcher.positive_msg = pos_msg
|
27
|
+
matched
|
28
|
+
end
|
data/test/mock.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
###########################################################################################################
|
2
|
+
module Synaptic4r
|
3
|
+
|
4
|
+
#########################################################################################################
|
5
|
+
class Request
|
6
|
+
|
7
|
+
#......................................................................................................
|
8
|
+
def http_request(args)
|
9
|
+
to_message_class(meth).send(:response, args)
|
10
|
+
end
|
11
|
+
|
12
|
+
#......................................................................................................
|
13
|
+
def to_message_class(meth)
|
14
|
+
eval("#{meth.to_s.split('_').collect{|s| s.capitalize}.join}Messages")
|
15
|
+
end
|
16
|
+
|
17
|
+
### Rest
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
### Rest
|
22
|
+
end
|
23
|
+
|
24
|
+
#########################################################################################################
|
25
|
+
module HttpMessages
|
26
|
+
|
27
|
+
|
28
|
+
####---------------------------------------------------------------------------------------------------
|
29
|
+
class Body
|
30
|
+
|
31
|
+
#......................................................................................................
|
32
|
+
attr_reader :body
|
33
|
+
|
34
|
+
#......................................................................................................
|
35
|
+
def initialize(args)
|
36
|
+
@body = args
|
37
|
+
end
|
38
|
+
|
39
|
+
#### Result
|
40
|
+
end
|
41
|
+
|
42
|
+
####---------------------------------------------------------------------------------------------------
|
43
|
+
class Result
|
44
|
+
|
45
|
+
#......................................................................................................
|
46
|
+
attr_reader :headers, :net_http_res
|
47
|
+
|
48
|
+
#......................................................................................................
|
49
|
+
def initialize(args)
|
50
|
+
@headers = args[:headers]
|
51
|
+
@net_http_res = Body.new(args[:body])
|
52
|
+
end
|
53
|
+
|
54
|
+
#### Result
|
55
|
+
end
|
56
|
+
|
57
|
+
### HttpMessages
|
58
|
+
end
|
data/test/test.txt
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
= synaptic4r
|
2
|
+
|
3
|
+
Ruby REST Client and CLI for ATT Synaptic Storage. The CLI directly maps
|
4
|
+
onto the REST API and can be used to inspect request headers and payloads, as well as,
|
5
|
+
a reference for the REST API.
|
6
|
+
|
7
|
+
== Install
|
8
|
+
|
9
|
+
The synptic4r gem is in the http://gemcutter.org repository. If gemcutter.org is not in your gem sources
|
10
|
+
issue the following command only one time,
|
11
|
+
|
12
|
+
sudo gem source -a http://gemcutter.org
|
13
|
+
|
14
|
+
and install synaptic4r
|
15
|
+
|
16
|
+
sudo gem install synaptic4r
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: synaptic4r
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- troystribling-att
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-12-02 00:00:00 -05:00
|
13
13
|
default_executable: synrest
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -46,6 +46,16 @@ files:
|
|
46
46
|
- lib/synaptic4r/rest.rb
|
47
47
|
- lib/synaptic4r/result.rb
|
48
48
|
- synaptic4r.gemspec
|
49
|
+
- test/create_dir_messages.rb
|
50
|
+
- test/create_dir_test.rb
|
51
|
+
- test/create_file_messages.rb
|
52
|
+
- test/create_file_test.rb
|
53
|
+
- test/get_messages.rb
|
54
|
+
- test/get_test.rb
|
55
|
+
- test/helper.rb
|
56
|
+
- test/matchers.rb
|
57
|
+
- test/mock.rb
|
58
|
+
- test/test.txt
|
49
59
|
has_rdoc: true
|
50
60
|
homepage: http://github.com/attsynaptic/synaptic4r
|
51
61
|
licenses: []
|
@@ -70,9 +80,17 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
70
80
|
requirements: []
|
71
81
|
|
72
82
|
rubyforge_project:
|
73
|
-
rubygems_version: 1.3.
|
83
|
+
rubygems_version: 1.3.5
|
74
84
|
signing_key:
|
75
85
|
specification_version: 3
|
76
86
|
summary: CLI and Ruby REST Client for ATT Synaptic Storage
|
77
|
-
test_files:
|
78
|
-
|
87
|
+
test_files:
|
88
|
+
- test/get_messages.rb
|
89
|
+
- test/create_file_messages.rb
|
90
|
+
- test/get_test.rb
|
91
|
+
- test/create_dir_messages.rb
|
92
|
+
- test/helper.rb
|
93
|
+
- test/create_dir_test.rb
|
94
|
+
- test/create_file_test.rb
|
95
|
+
- test/mock.rb
|
96
|
+
- test/matchers.rb
|