synaptic4r 0.1.5

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/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,7 @@
1
+ *.gem
2
+ *~
3
+ *.sw?
4
+ .DS_Store
5
+ coverage
6
+ rdoc
7
+ 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.
data/README.rdoc ADDED
@@ -0,0 +1,88 @@
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 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
17
+
18
+ == Credentials
19
+
20
+ Save credentials to $HOME/.synaptic4r
21
+
22
+ single account
23
+
24
+ subtenant: SubtenantID
25
+ uid: UserID
26
+ key: SecretKey
27
+ site: https://storage.synaptic.att.com/rest
28
+
29
+ multiple accounts (the first is used by default, the dashes must
30
+ be included in the file)
31
+
32
+ -
33
+ account: myacct
34
+ subtenant: SubtenantID
35
+ uid: UserID
36
+ key: SecretKey
37
+ site: https://storage.synaptic.att.com/rest
38
+
39
+ -
40
+ account: myotheracct
41
+ subtenant: OtherSubtenantID
42
+ uid: OtherUserID
43
+ key: OtherSecretKey
44
+ site: https://storage.synaptic.att.com/rest
45
+
46
+ == Basic CLI Commands
47
+
48
+ list information here
49
+
50
+ synrest get-started
51
+
52
+ list all commands with descriptions
53
+
54
+ synrest
55
+
56
+ list contents of remote root directory
57
+
58
+ synrest get
59
+
60
+ create a remote directory named foo
61
+
62
+ synrest create-dir foo
63
+
64
+ upload a file to directory foo
65
+
66
+ synrest create-file file.txt foo/
67
+
68
+ list contents remote directory foo
69
+
70
+ synrest get foo
71
+
72
+ list contents remote file foo/file.txt
73
+
74
+ synrest get foo/file.txt
75
+
76
+ execute command for account other than default
77
+
78
+ synrest command args [options] -u myotheracct
79
+
80
+ show examples for a command
81
+
82
+ synrest command examples
83
+
84
+
85
+
86
+ == Copyright
87
+
88
+ Copyright (c) 2009 ATT. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,56 @@
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/attsynaptic/synaptic4r"
11
+ gem.authors = ["troystribling-att"]
12
+ gem.add_dependency('rest-client', '>= 1.0.2')
13
+ end
14
+
15
+ rescue LoadError
16
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
17
+ end
18
+
19
+ require 'rake/testtask'
20
+ Rake::TestTask.new(:test) do |test|
21
+ test.libs << 'lib' << 'test'
22
+ test.pattern = 'test/**/*_test.rb'
23
+ test.verbose = true
24
+ end
25
+
26
+ begin
27
+ require 'rcov/rcovtask'
28
+ Rcov::RcovTask.new do |test|
29
+ test.libs << 'test'
30
+ test.pattern = 'test/**/*_test.rb'
31
+ test.verbose = true
32
+ end
33
+ rescue LoadError
34
+ task :rcov do
35
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
36
+ end
37
+ end
38
+
39
+
40
+ task :default => :test
41
+
42
+ require 'rake/rdoctask'
43
+ Rake::RDocTask.new do |rdoc|
44
+ if File.exist?('VERSION.yml')
45
+ config = YAML.load(File.read('VERSION.yml'))
46
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
47
+ else
48
+ version = ""
49
+ end
50
+
51
+ rdoc.rdoc_dir = 'rdoc'
52
+ rdoc.title = "synaptic4r #{version}"
53
+ rdoc.rdoc_files.include('README*')
54
+ rdoc.rdoc_files.include('lib/**/*.rb')
55
+ end
56
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.5
data/bin/synrest ADDED
@@ -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]
@@ -0,0 +1,77 @@
1
+ ####-----------------------------------------------------------------------------------------------------
2
+ module Synaptic4r
3
+
4
+ ####------------------------------------------------------------------------------------------------------
5
+ class Client
6
+
7
+
8
+ ####------------------------------------------------------------------------------------------------------
9
+ include Utils
10
+
11
+ #.........................................................................................................
12
+ @config_file = ENV['HOME'] + '/.synaptic4r'
13
+
14
+ ####------------------------------------------------------------------------------------------------------
15
+ class << self
16
+ attr_reader :config_file
17
+ end
18
+
19
+ #.........................................................................................................
20
+ attr_reader :uid, :key, :site, :resource, :subtenant
21
+
22
+ #.........................................................................................................
23
+ def initialize(args = nil)
24
+ config_params = %w(key site subtenant uid)
25
+ if args
26
+ account = args[:account]
27
+ if account
28
+ aconfig = config_by_account(account)
29
+ raise ArgumentError, "Account '#{account}' not found in #{ENV['HOME']}/.synaptic4r" unless aconfig
30
+ args.update(symbolize(aconfig))
31
+ end
32
+ else
33
+ if config.kind_of?(Hash)
34
+ args = symbolize(config)
35
+ elsif config.kind_of?(Array)
36
+ cfg = config.first
37
+ args = symbolize(cfg)
38
+ else
39
+ raise ArgumentError, "#{ENV['HOME']}/.synaptic4r not formatted properly"
40
+ end
41
+ end
42
+ unary_args_given?(symbolize(config_params), args.keys)
43
+ @subtenant = args[:subtenant]
44
+ @uid = args[:uid]
45
+ @key = args[:key]
46
+ @site = args[:site]
47
+ end
48
+
49
+ #.........................................................................................................
50
+ def method_missing(meth, *args, &blk)
51
+ if Request.has_rest_method?(meth)
52
+ Request.new(:uid => uid, :subtenant => subtenant, :key => key, :site => site).execute(meth, *args, &blk)
53
+ else
54
+ super
55
+ end
56
+ end
57
+
58
+ private
59
+
60
+ #.........................................................................................................
61
+ def config
62
+ @config ||= File.open(Client.config_file){|yf| YAML::load(yf)}
63
+ end
64
+
65
+ #.........................................................................................................
66
+ def config_by_account(account)
67
+ if config.kind_of?(Array)
68
+ a = config.select{|c| c['account'].eql?(account)}.first
69
+ a.delete('account') unless a.nil?; a
70
+ else; config; end
71
+ end
72
+
73
+ #### Client
74
+ end
75
+
76
+ #### Synaptic4r
77
+ end