attsynaptic-synaptic4r 0.1.4

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.
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
@@ -0,0 +1,6 @@
1
+ *~
2
+ *.sw?
3
+ .DS_Store
4
+ coverage
5
+ rdoc
6
+ pkg
data/LICENSE ADDED
@@ -0,0 +1,11 @@
1
+ Copyright (c) 2009 AT&T Intellectual Property.
2
+
3
+ All rights reserved.
4
+
5
+ AT&T, AT&T logo and all other AT&T marks contained herein
6
+ are trademarks of AT&T Intellectual Property and/or AT&T affiliated companies.
7
+
8
+ All other trademarks are the property of their owners.
9
+
10
+ The above copyright notice shall be included in all copies or
11
+ substantial portions of the Software.
@@ -0,0 +1,79 @@
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
+ == Credentials
10
+
11
+ Save credentials to $HOME/.synaptic4r
12
+
13
+ single account
14
+
15
+ subtenant: SubtenantID
16
+ uid: UserID
17
+ key: SecretKey
18
+ site: https://storage.synaptic.att.com/rest
19
+
20
+ multiple accounts (the first is used by default, the dashes must
21
+ be included in the file)
22
+
23
+ -
24
+ account: myacct
25
+ subtenant: SubtenantID
26
+ uid: UserID
27
+ key: SecretKey
28
+ site: https://storage.synaptic.att.com/rest
29
+
30
+ -
31
+ account: myotheracct
32
+ subtenant: OtherSubtenantID
33
+ uid: OtherUserID
34
+ key: OtherSecretKey
35
+ site: https://storage.synaptic.att.com/rest
36
+
37
+ == Basic CLI Commands
38
+
39
+ list information here
40
+
41
+ synrest get-started
42
+
43
+ list all commands with descriptions
44
+
45
+ synrest
46
+
47
+ list contents of remote root directory
48
+
49
+ synrest get
50
+
51
+ create a remote directory named foo
52
+
53
+ synrest create-dir foo
54
+
55
+ upload a file to directory foo
56
+
57
+ synrest create-file file.txt foo/
58
+
59
+ list contents remote directory foo
60
+
61
+ synrest get foo
62
+
63
+ list contents remote file foo/file.txt
64
+
65
+ synrest get foo/file.txt
66
+
67
+ execute command for account other than default
68
+
69
+ synrest command args [options] -u myotheracct
70
+
71
+ show examples for a command
72
+
73
+ synrest command examples
74
+
75
+
76
+
77
+ == Copyright
78
+
79
+ Copyright (c) 2009 ATT. See LICENSE for details.
@@ -0,0 +1,57 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "synaptic4r"
8
+ gem.summary = "CLI and Ruby REST Client for ATT Synaptic Storage"
9
+ gem.email = "troy.stribling@usi.com"
10
+ gem.homepage = "http://github.com/troystribling-att/synaptic4r"
11
+ gem.authors = ["troystribling-att"]
12
+ gem.add_dependency('rake', '>= 0.8.3')
13
+ gem.add_dependency('rest-client', '>= 1.0.2')
14
+ end
15
+
16
+ rescue LoadError
17
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
18
+ end
19
+
20
+ require 'rake/testtask'
21
+ Rake::TestTask.new(:test) do |test|
22
+ test.libs << 'lib' << 'test'
23
+ test.pattern = 'test/**/*_test.rb'
24
+ test.verbose = true
25
+ end
26
+
27
+ begin
28
+ require 'rcov/rcovtask'
29
+ Rcov::RcovTask.new do |test|
30
+ test.libs << 'test'
31
+ test.pattern = 'test/**/*_test.rb'
32
+ test.verbose = true
33
+ end
34
+ rescue LoadError
35
+ task :rcov do
36
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
37
+ end
38
+ end
39
+
40
+
41
+ task :default => :test
42
+
43
+ require 'rake/rdoctask'
44
+ Rake::RDocTask.new do |rdoc|
45
+ if File.exist?('VERSION.yml')
46
+ config = YAML.load(File.read('VERSION.yml'))
47
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
48
+ else
49
+ version = ""
50
+ end
51
+
52
+ rdoc.rdoc_dir = 'rdoc'
53
+ rdoc.title = "synaptic4r #{version}"
54
+ rdoc.rdoc_files.include('README*')
55
+ rdoc.rdoc_files.include('lib/**/*.rb')
56
+ end
57
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.4
@@ -0,0 +1,316 @@
1
+ #!/usr/bin/ruby
2
+
3
+ ####---------------------------------------------------------------------------------------------------------
4
+ SYNLIB = "#{File.dirname($0)}/../lib"
5
+ $:.unshift(SYNLIB) unless $:.include?(SYNLIB)
6
+
7
+ ####---------------------------------------------------------------------------------------------------------
8
+ require 'yaml'
9
+ require 'optparse'
10
+ require 'synaptic4r'
11
+ require 'logger'
12
+
13
+ #############################################################################################################
14
+ ####---------------------------------------------------------------------------------------------------------
15
+ def credentials_configured?
16
+ config_keys = %w(key site subtenant uid)
17
+ status = if File.exists?(Synaptic4r::Client.config_file)
18
+ config = File.open(Synaptic4r::Client.config_file){|yf| YAML::load(yf)}
19
+ if config.kind_of?(Hash)
20
+ config.keys.sort.eql?(config_keys) or config.keys.sort.eql?(config_keys.unshift('account'))
21
+ elsif config.kind_of?(Array)
22
+ config_keys.unshift('account')
23
+ config.select{|c| c.keys.sort.eql?(config_keys)}.length.eql?(config.length)
24
+ else
25
+ puts "#{Synaptic4r::Client.config_file} not formatted properly"
26
+ exit
27
+ end
28
+ else
29
+ puts "#{Synaptic4r::Client.config_file} not found"
30
+ exit
31
+ end
32
+ unless status
33
+ puts "#{Synaptic4r::Client.config_file} missing one of 'key', 'site', 'subtenant' or 'uid'"
34
+ exit
35
+ end
36
+ end
37
+
38
+ ####---------------------------------------------------------------------------------------------------------
39
+ def dump(cmd, input, result)
40
+ output = if input[:dump]
41
+ <<-DUMP
42
+ COMMAND: #{cmd}
43
+ ARGS: #{input.inspect}
44
+ SIGNING STRING: #{result.sign.inspect}
45
+ HTTP METHOD: #{result.http_request}
46
+ URL: #{result.url}
47
+ HEADERS: #{result.headers.inspect}
48
+ DUMP
49
+ else; ''; end
50
+ if input[:payload] and result.payload
51
+ output + "PAYLOAD:\n" + result.payload
52
+ else
53
+ output
54
+ end
55
+ end
56
+
57
+ ####---------------------------------------------------------------------------------------------------------
58
+ def run(cmd, input)
59
+ begin
60
+ result = Synaptic4r::Client.new(input[:account].nil? ? nil : {:account => input[:account]}).send(cmd, input)
61
+ {:out => (input[:dump] or input[:payload]) ? dump(cmd, input, result) : result.print, :logger => :info}
62
+ rescue RestClient::RequestFailed, RestClient::ResourceNotFound, RestClient::Unauthorized,
63
+ RestClient::NotModified => err
64
+ {:out => "#{err.message}\n" + Synaptic4r::RequestError.new(err).print, :logger => :error}
65
+ rescue RestClient::Redirect, RestClient::ServerBrokeConnection, RestClient::RequestTimeout => err
66
+ {:out => err.message, :logger => :error}
67
+ rescue ArgumentError => err
68
+ {:out => err.to_s, :logger => :error}
69
+ rescue Errno::ENOENT, Errno::EISDIR => err
70
+ {:out => err.to_s, :logger => :error}
71
+ end
72
+ end
73
+
74
+ ####---------------------------------------------------------------------------------------------------------
75
+ def extract_cmd(meths)
76
+ if ARGV.first
77
+ if meths.include?(ARGV.first.gsub(/-/,'_').to_sym)
78
+ ARGV.shift.gsub(/-/,'_').to_sym
79
+ else
80
+ puts "Error: '#{ARGV.first}' is not a valid command"
81
+ exit
82
+ end
83
+ end
84
+ end
85
+
86
+ ####---------------------------------------------------------------------------------------------------------
87
+ def format_required_args(args)
88
+ args.inject("") do |f,a|
89
+ aname = lambda{|v,l| arg_name(Synaptic4r::Request.rest_arg(v),l)}
90
+ if a.kind_of?(Array)
91
+ f + [aname[a.first,false],a[1..-1].map{|v| aname[v,true]}].join('|') + ' '
92
+ else
93
+ "#{f}#{aname[a, false]} "
94
+ end
95
+ end.chomp(' ')
96
+ end
97
+
98
+ ####---------------------------------------------------------------------------------------------------------
99
+ def diagnostic_args(opts, input, cmd)
100
+ if Synaptic4r::Request.diagnostics(cmd)
101
+ opts.separator "\ndiagnostic options"
102
+ opts.on('-q', '--dump', 'do not send request but print headers and service url to STDOUT'){|d| input[:dump] = true}
103
+ opts.on('-p', '--payload', 'do not send request print payload to STDOUT if present'){|p| input[:payload] = true}
104
+ opts.on('-l', '--log [file]', 'log request to file (by default file is synaptic4r.log)') do |file|
105
+ input[:log] = true
106
+ input[:log_file] = file
107
+ end
108
+ end
109
+ opts.on_tail('-h', '--help', "this listing\n") {
110
+ puts
111
+ puts opts
112
+ puts "Examples: synrest #{cmd.to_s.gsub(/_/,'-')} examples\n\n"
113
+ exit
114
+ }
115
+ end
116
+
117
+ ####---------------------------------------------------------------------------------------------------------
118
+ def set_opts(opts, input, opt_args)
119
+ opt_args = [opt_args].flatten
120
+ unless opt_args.empty?
121
+ opts.separator "\noptions"
122
+ opt_args.sort_by{|m| m.to_s}.each do |a|
123
+ arg_info = Synaptic4r::Request.rest_arg(a)
124
+ sopt = arg_info[:cli][1]
125
+ lopt = "--#{arg_info[:cli][0]}" + (arg_info[:cli][2].eql?(:flag) ? '' : " #{arg_info[:cli][0]}")
126
+ opts.on(sopt, lopt, arg_info[:desc]) do |v|
127
+ input[a] = arg_info[:map].nil? ? v : arg_info[:map][v]
128
+ end
129
+ end
130
+ end
131
+ end
132
+
133
+ ####---------------------------------------------------------------------------------------------------------
134
+ def set_args(opts, meths, input, cmd)
135
+ extract_positional_args(meths, input, cmd)
136
+ all_args = Synaptic4r::Request.required_rest_args(cmd)
137
+ fmt = " %-32s %s"
138
+ unless all_args.empty?
139
+ opts.separator "\nargs"
140
+ arg_row = lambda{|a,l| arg_info = Synaptic4r::Request.rest_arg(a)
141
+ opts.separator fmt % [arg_name(arg_info,l), arg_info[:desc]]}
142
+ all_args.each do |a|
143
+ if a.kind_of?(Array)
144
+ opts.separator "one of"
145
+ arg_row[a.first,false]
146
+ a[1..-1].each{|e| arg_row[e,true]}
147
+ else
148
+ arg_row[a,false]
149
+ end
150
+ end
151
+ end
152
+ end
153
+
154
+ ####---------------------------------------------------------------------------------------------------------
155
+ def prep_argv
156
+ add = true
157
+ inargs = ARGV.inject([]) do |o,a|
158
+ if /^-/.match(a)
159
+ i = ARGV.index(a)
160
+ n = ARGV[i+1]
161
+ if n and not /^-/.match(n)
162
+ add = false; o << [a,n].join(' ')
163
+ else
164
+ o << a
165
+ end
166
+ elsif add
167
+ o << a
168
+ else
169
+ add = true; o
170
+ end
171
+ end
172
+ end
173
+
174
+ ####---------------------------------------------------------------------------------------------------------
175
+ def extract_positional_args(meths, input, cmd)
176
+ eargs = Synaptic4r::Request.required_rest_args(cmd)
177
+ elength = eargs.length
178
+ pvals= prep_argv.first(elength)
179
+ nvals = if Synaptic4r::Request.map_required_args(cmd)
180
+ Synaptic4r::Request.map_required_args(cmd)[pvals]
181
+ else
182
+ {:pvals => pvals, :dlen => 0}
183
+ end
184
+ if pvals.include?('-h')
185
+ elsif ARGV.first.eql?('examples')
186
+ begin
187
+ send("#{cmd}_examples".to_sym)
188
+ exit
189
+ rescue NoMethodError
190
+ puts "'#{cmd.to_s.gsub(/_/,'-')}' examples are not availble"
191
+ exit
192
+ end
193
+ elsif nvals[:pvals].length < elength
194
+ puts "Error: expecting args '#{format_required_args(eargs)}'"
195
+ exit
196
+ else
197
+ set_positional_args(input, nvals, eargs)
198
+ end
199
+ end
200
+
201
+ ####---------------------------------------------------------------------------------------------------------
202
+ def set_positional_args(input, nvals, eargs)
203
+ assign_input = lambda{|a,v| info = Synaptic4r::Request.rest_arg(a);
204
+ input[a] = info[:map].nil? ? v : info[:map][v]}
205
+ length = 0
206
+ nvals[:pvals].each_index do |i|
207
+ pv = nvals[:pvals][i]
208
+ ea = eargs[i]
209
+ if ea.kind_of?(Array)
210
+ if /^-/.match(pv)
211
+ matched = false
212
+ ea[1..-1].each do |a|
213
+ info = Synaptic4r::Request.rest_arg(a)
214
+ flag = info[:cli][1]
215
+ next unless flag
216
+ if /^#{flag}/.match(pv)
217
+ input[a] = pv.split(/\s/).last
218
+ matched = true
219
+ length += 2
220
+ break
221
+ end
222
+ end
223
+ unless matched
224
+ puts "Error: expecting args '#{format_required_args(eargs)}'"
225
+ exit
226
+ end
227
+ else
228
+ length += 1
229
+ assign_input[ea.first,pv]
230
+ end
231
+ else
232
+ length += 1
233
+ assign_input[ea,pv]
234
+ end
235
+ end
236
+ ARGV.slice!(0, length - nvals[:dlen])
237
+ end
238
+
239
+ ####---------------------------------------------------------------------------------------------------------
240
+ def arg_name(arg_info, long=true)
241
+ cli = arg_info[:cli]
242
+ if cli.kind_of?(Array) and long
243
+ cli.length > 1 ? "#{cli[1]} #{cli[0]}" : cli.first
244
+ else; [cli].flatten.first; end
245
+ end
246
+
247
+ ####---------------------------------------------------------------------------------------------------------
248
+ def build_banner(opts, cmd)
249
+ exp_args = Synaptic4r::Request.required_rest_args(cmd)
250
+ opts.banner = Synaptic4r::Request.banner(cmd) || \
251
+ "\nUsage: synrest #{cmd.to_s.gsub(/_/,'-')} #{format_required_args(exp_args)} [options]"
252
+
253
+ end
254
+
255
+ ####---------------------------------------------------------------------------------------------------------
256
+ def process_input(opts, meths, input, cmd)
257
+ build_banner(opts, cmd)
258
+ set_args(opts, meths, input, cmd)
259
+ set_opts(opts, input, Synaptic4r::Request.optional_rest_args(cmd))
260
+ diagnostic_args(opts, input, cmd)
261
+ end
262
+
263
+
264
+ ####---------------------------------------------------------------------------------------------------------
265
+ def cmd_help(meths)
266
+ puts "\nUsage: synrest command args [options]"
267
+ puts "\nCommands"
268
+ meths.sort_by{|m| m.to_s}.each do |m|
269
+ next if m.eql?(:get_started)
270
+ meth_str = " %-30s" % m.to_s.gsub(/_/,'-')
271
+ puts "#{meth_str} #{Synaptic4r::Request.desc(m)}"
272
+ end
273
+ puts "\nCommand args and options\n synrest command -h"
274
+ puts "\nGet Started\n synrest get-started"
275
+ puts "\nCommand examples\n synrest command examples\n\n"
276
+ end
277
+
278
+ ####---------------------------------------------------------------------------------------------------------
279
+ meths = Synaptic4r::Request.rest_methods << :get_started
280
+ input = {}
281
+ cmd = extract_cmd(meths)
282
+
283
+ ####---------------------------------------------------------------------------------------------------------
284
+ if cmd.eql?(:get_started)
285
+ get_started
286
+ exit
287
+ elsif cmd
288
+ OptionParser.new do |opts|
289
+ process_input(opts, meths, input, cmd)
290
+ begin
291
+ credentials_configured?
292
+ opts.parse!(ARGV)
293
+ rescue OptionParser::MissingArgument, OptionParser::InvalidOption => err
294
+ puts err.to_s
295
+ exit
296
+ end
297
+ end
298
+ else
299
+ puts "\nsynrest provides a command line interface that maps directly onto the"
300
+ puts "synaptic storage rest API"
301
+ cmd_help(meths)
302
+ exit
303
+ end
304
+
305
+ ####---------------------------------------------------------------------------------------------------------
306
+ if input[:log]
307
+ log = Logger.new(input[:log_file] || 'synaptic4r.log')
308
+ request = run(cmd, input.merge(:dump => true))
309
+ end
310
+
311
+ ####---------------------------------------------------------------------------------------------------------
312
+ result = run(cmd, input)
313
+ puts result[:out] if result[:out]
314
+
315
+ ####---------------------------------------------------------------------------------------------------------
316
+ log.send(result[:logger], "\n#{request[:out]}#{result[:out]}") if input[:log]