addax 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (6) hide show
  1. data/Rakefile +16 -0
  2. data/VERSION +1 -0
  3. data/bin/addax +7 -0
  4. data/lib/addax.rb +80 -0
  5. data/lib/addax/commands.rb +236 -0
  6. metadata +119 -0
@@ -0,0 +1,16 @@
1
+ begin
2
+ require 'jeweler'
3
+ Jeweler::Tasks.new do |gemspec|
4
+ gemspec.name = "addax"
5
+ gemspec.summary = "Command-line tool for accessing TIMA-SLS's ADDAX webservice."
6
+ gemspec.email = "guillaume.godetbar@gmail.com"
7
+ gemspec.homepage = "http://tima-sls.imag.fr/addax"
8
+ gemspec.authors = ["Guillaume Godet-Bar"]
9
+ gemspec.files = FileList["lib/**/*", "bin/*", "Rakefile", "VERSION"]
10
+ gemspec.executables = ['addax']
11
+ gemspec.add_dependency 'rest-client'
12
+ gemspec.add_dependency 'json'
13
+ end
14
+ rescue LoadError
15
+ puts "Jeweler not available. Install it with: gem install jeweler"
16
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.10.0
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '../lib')
4
+ require 'addax'
5
+
6
+ opts = Addax::Exec.new(ARGV)
7
+ opts.parse!
@@ -0,0 +1,80 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rest_client'
4
+ require 'json'
5
+ require 'readline'
6
+ require 'base64'
7
+ require 'tempfile'
8
+ require 'pp'
9
+
10
+ require File.join(File.dirname(__FILE__), 'addax/commands')
11
+
12
+ module Addax
13
+ USAGE = <<END
14
+ Addax, a command line tool for connecting with the Addax Webservice.
15
+
16
+ Usage
17
+
18
+ addax <Action>
19
+
20
+ Actions
21
+
22
+ [list | l] <object_type> - lists all available objects, which should be either 'oses|operating_systems', 'drivers', 'platforms'
23
+ <object_type> <id> - displays the data associated with the object instance, e.g. 'addax driver 1'
24
+ [fetch | f] <object_type> <id> <path> - returns the file associated with a driver or a platform
25
+ [generate | g] <id> <path> - downloads the generated sources for the driver associated with <id> into <path>
26
+ [create | c] <object_type> <param>=<value> [<param>=<value>]*
27
+ - creates a new instance of the object type, with the list of parameters provided.
28
+ [update | u] <object_type> <id> <param>=<value> [<param>=<value>]*
29
+ - modifies the object identified by <id> with the list of parameters provided.
30
+ [destroy | d] [-f] <object_type> <id> - destroys the object identified by <id>. -f to destroy without asking for confirmation.
31
+
32
+ END
33
+
34
+ SERVER_URL = 'http://tima-sls.imag.fr/addax'
35
+
36
+ class Exec
37
+
38
+ def initialize(args)
39
+ @args = args
40
+ end
41
+
42
+ def parse!
43
+ begin
44
+ parse
45
+ rescue ArgumentError
46
+ $stderr.puts USAGE
47
+ end
48
+ end
49
+
50
+ def parse
51
+ if ARGV.size == 2 && %w(l list).include?(ARGV[0]) && %w(operating_systems oses platforms drivers strategies).include?(ARGV[1])
52
+ Addax::Commands.list(ARGV[1])
53
+ elsif ARGV.size == 2 && %w(operating_system os driver platform).include?(ARGV[0])
54
+ Addax::Commands.show(ARGV[0], ARGV[1])
55
+ elsif ARGV.size == 3 && %w(g generate).include?(ARGV[0])
56
+ Addax::Commands.generate(ARGV[1], ARGV[2])
57
+ elsif ARGV.size > 2 && %w(c create).include?(ARGV[0]) && %w(operating_system os platform driver).include?(ARGV[1])
58
+ Addax::Commands.send("create_#{ARGV[1]}".to_sym, ARGV[2..-1])
59
+ elsif ARGV.size == 4 && %w(f fetch).include?(ARGV[0]) && %w(driver platform).include?(ARGV[1])
60
+ Addax::Commands.send("fetch_#{ARGV[1]}".to_sym, ARGV[2], ARGV[3])
61
+ elsif ARGV.size > 3 && %w(u update).include?(ARGV[0]) && %w(operating_system os platform driver).include?(ARGV[1])
62
+ Addax::Commands.update(ARGV[1], ARGV[2], ARGV[3..-1])
63
+ elsif ARGV.size >= 3 && %w(d destroy).include?(ARGV[0])
64
+ if ARGV[1] == '-f'
65
+ Addax::Commands.destroy(ARGV[2], ARGV[3])
66
+ else
67
+ begin
68
+ puts "Please confirm that you wish to destroy this resource (Y/n)"
69
+ line = Readline.readline()
70
+ end while !%w(Y n).include?(line)
71
+ if line == 'Y'
72
+ Addax::Commands.destroy(ARGV[1], ARGV[2])
73
+ end
74
+ end
75
+ else
76
+ raise ArgumentError
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,236 @@
1
+ module Addax
2
+ module Commands
3
+
4
+ OUTPUTS = {
5
+ :generic_error => "ERROR. Something went wrong with the server.",
6
+ :not_found => "ERROR. Resource not found.",
7
+ :platform_data_missing => "ERROR. Platform data file (format: zip) is missing.",
8
+ :created_resource => "Successfully created resource.",
9
+ :updated_resource => "Successfully updated resource.",
10
+ :destroyed_resource => "Successfully destroyed resource.",
11
+ :security_tokens_error => "ERROR. Could not fetch security tokens from the server."
12
+ }
13
+
14
+ def self.list(type)
15
+ type = type == 'oses' ? 'operating_systems' : type
16
+ begin
17
+ response = RestClient.get "#{SERVER_URL}/#{type}.json"
18
+ rescue => e
19
+ abort OUTPUTS[:generic_error]
20
+ else
21
+ format(response.body)
22
+ end
23
+ end
24
+
25
+ def self.show(model, id)
26
+ type = type == 'os' ? 'operating_system' : type
27
+ begin
28
+ response = RestClient.get "#{SERVER_URL}/#{model}s/#{id}.json"
29
+ rescue => e
30
+ case e.response.code
31
+ when 404 then
32
+ abort OUTPUTS[:not_found]
33
+ else
34
+ abort OUTPUTS[:generic_error]
35
+ end
36
+ else
37
+ format(response.body)
38
+ end
39
+ end
40
+
41
+ def self.generate(driver_id, file_path)
42
+ begin
43
+ response = RestClient.post "#{SERVER_URL}/drivers/#{driver_id}/generate_sources", {}
44
+ rescue => e
45
+ case e.response.code
46
+ when 404 then
47
+ abort OUTPUTS[:not_found]
48
+ else
49
+ abort OUTPUTS[:generic_error]
50
+ end
51
+ else
52
+ file_name = response.headers[:content_disposition].scan(/filename="(.+)"/)[0][0] + ".zip"
53
+ File.open File.join(file_path, file_name), "w" do |f|
54
+ f.write(response.body)
55
+ end
56
+ puts "File was written to #{File.join(file_path, file_name)}"
57
+ end
58
+ end
59
+
60
+ def self.fetch_driver(object_id, file_path)
61
+ begin
62
+ response = RestClient.get "#{SERVER_URL}/drivers/#{object_id}/show_attachment"
63
+ rescue => e
64
+ case e.response.code
65
+ when 404 then
66
+ abort OUTPUTS[:not_found]
67
+ else
68
+ abort OUTPUTS[:generic_error]
69
+ end
70
+ else
71
+ file_name = response.headers[:content_disposition].scan(/filename="(.+)"/)[0][0] + ".xml"
72
+ File.open File.join(file_path, file_name), "w" do |f|
73
+ f.write(response.body)
74
+ end
75
+ puts "File was written to #{File.join file_path, file_name}"
76
+ end
77
+ end
78
+
79
+ def self.fetch_platform(object_id, file_path)
80
+ abort "ERROR: Platform data fetch not implemented yet!"
81
+ end
82
+
83
+ def self.create_platform(params)
84
+ param_hash = normalize_params(params)
85
+
86
+ authenticity_token, cookie = security_tokens
87
+
88
+ # The params should at least have a platform_data param
89
+ platform_data = param_hash.delete(:platform_data)
90
+ unless platform_data
91
+ abort OUTPUTS[:platform_data_missing]
92
+ end
93
+
94
+ begin
95
+ load_platform_data_response = RestClient.post "#{SERVER_URL}/platforms/load_file.json",
96
+ {:platform_data => File.new(platform_data, 'rb'), :authenticity_token => authenticity_token},
97
+ {:cookies => cookie}
98
+ rescue => e
99
+ abort OUTPUTS[:generic_error] + '\n' + format_error(e.response.body)
100
+ end
101
+
102
+ encoded_cache_name = load_platform_data_response.body
103
+
104
+ if param_hash[:root_component]
105
+ begin
106
+ create_platform_response = RestClient.post "#{SERVER_URL}/platforms.json?cache=#{encoded_cache_name}",
107
+ {:platform => param_hash, :authenticity_token => authenticity_token},
108
+ {:cookies => cookie}
109
+ rescue => e
110
+ abort OUTPUTS[:generic_error] + '\n' + format_error(e.response.body)
111
+ else
112
+ puts OUTPUTS[:created_resource]
113
+ format(create_platform_response.body)
114
+ end
115
+ else
116
+ abort "ERROR: Root component choice not yet implemented!"
117
+ end
118
+ end
119
+
120
+ def self.create_driver(params)
121
+ param_hash = normalize_params(params)
122
+
123
+ authenticity_token, cookie = security_tokens
124
+
125
+ begin
126
+ response = RestClient.post "#{SERVER_URL}/drivers.json",
127
+ {:driver => param_hash, :authenticity_token => authenticity_token},
128
+ {:cookies => cookie}
129
+ rescue => e
130
+ abort OUTPUTS[:generic_error] + '\n' + format_error(e.response.body)
131
+ else
132
+ puts OUTPUTS[:updated_resource]
133
+ format(response.body)
134
+ end
135
+ end
136
+
137
+ def self.create_operating_system(params)
138
+ param_hash = normalize_params(params)
139
+
140
+ authenticity_token, cookie = security_tokens
141
+
142
+ begin
143
+ response = RestClient.post "#{SERVER_URL}/operating_systems.json",
144
+ {:operating_system => param_hash,:authenticity_token => authenticity_token},
145
+ {:cookies => cookie}
146
+ rescue => e
147
+ abort OUTPUTS[:generic_error] + '\n' + format_error(e.response.body)
148
+ else
149
+ puts OUTPUTS[:created_resource]
150
+ format(response.body)
151
+ end
152
+ end
153
+
154
+ def self.update(object_type, object_id, params)
155
+ object_type = object_type == "os" ? "operating_system" : object_type
156
+ param_hash = normalize_params(params)
157
+
158
+ begin
159
+ response = RestClient.put "#{SERVER_URL}/#{object_type}s/#{object_id}.json",
160
+ {object_type.to_sym => param_hash}
161
+ rescue => e
162
+ abort OUTPUTS[:generic_error] + '\n' + format_error(e.response.body)
163
+ else
164
+ puts OUTPUTS[:updated_resource]
165
+ format(response.body)
166
+ end
167
+ end
168
+
169
+ def self.destroy(object_type, object_id)
170
+ authenticity_token, cookie = security_tokens
171
+ begin
172
+ response = RestClient.delete "#{SERVER_URL}/#{object_type}s/#{object_id}.json", {:cookies => cookie}
173
+ rescue => e
174
+ case e.response.code
175
+ when 404 then
176
+ abort OUTPUTS[:not_found]
177
+ else
178
+ abort OUTPUTS[:generic_error]
179
+ end
180
+ else
181
+ puts OUTPUTS[:destroyed_resource]
182
+ end
183
+ end
184
+
185
+ class << self
186
+ alias :create_os :create_operating_system
187
+ end
188
+
189
+ private
190
+ def self.security_tokens
191
+ begin
192
+ new_response = RestClient.get "#{SERVER_URL}/drivers/new.html" # Any form would do
193
+ rescue => e
194
+ abort OUTPUTS[:security_tokens_error]
195
+ else
196
+ authenticity_token = new_response.body.scan(/<meta name="csrf-token" content="(.*)"\/>/)[0][0]
197
+ cookie = new_response.cookies
198
+ [authenticity_token, cookie]
199
+ end
200
+ end
201
+
202
+ def self.normalize_params(param_array)
203
+ param_hash = param_array.inject({}){|acc, p| pieces = p.split('='); acc[pieces[0].to_sym] = pieces[1]; acc}
204
+ param_hash.delete(:id)
205
+ param_hash.delete(:created_at)
206
+ param_hash.delete(:updated_at)
207
+
208
+ param_hash
209
+ end
210
+
211
+ def self.format(json)
212
+ content = json.is_a?(String) ? JSON::parse(json) : json
213
+ if content.is_a?(Array)
214
+ content.each do |el|
215
+ format(el)
216
+ end
217
+ else
218
+ puts content.values[0].delete('name') + ":"
219
+ data = content.values[0]
220
+ data.each do |k, v|
221
+ puts "\t" + k + ": " + v.to_s #.gsub('_', ' ').capitalize + ": " + v.to_s
222
+ end
223
+
224
+ end
225
+ end
226
+
227
+ def self.format_error(json)
228
+ content = json.is_a?(String) ? JSON::parse(json) : json
229
+ if content.is_a?(Hash)
230
+ content.collect do |k, v|
231
+ "\t" + k + ' ' + v
232
+ end.join('\n')
233
+ end
234
+ end
235
+ end
236
+ end
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: addax
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 10
8
+ - 0
9
+ version: 0.10.0
10
+ platform: ruby
11
+ authors:
12
+ - Guillaume Godet-Bar
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-02-15 00:00:00 +01:00
18
+ default_executable: addax
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: json
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ none: false
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ type: :runtime
31
+ prerelease: false
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: rest-client
35
+ requirement: &id002 !ruby/object:Gem::Requirement
36
+ none: false
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ segments:
41
+ - 0
42
+ version: "0"
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: *id002
46
+ - !ruby/object:Gem::Dependency
47
+ name: rest-client
48
+ requirement: &id003 !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ segments:
54
+ - 0
55
+ version: "0"
56
+ type: :runtime
57
+ prerelease: false
58
+ version_requirements: *id003
59
+ - !ruby/object:Gem::Dependency
60
+ name: json
61
+ requirement: &id004 !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ segments:
67
+ - 0
68
+ version: "0"
69
+ type: :runtime
70
+ prerelease: false
71
+ version_requirements: *id004
72
+ description:
73
+ email: guillaume.godetbar@gmail.com
74
+ executables:
75
+ - addax
76
+ extensions: []
77
+
78
+ extra_rdoc_files: []
79
+
80
+ files:
81
+ - Rakefile
82
+ - VERSION
83
+ - bin/addax
84
+ - lib/addax.rb
85
+ - lib/addax/commands.rb
86
+ has_rdoc: true
87
+ homepage: http://tima-sls.imag.fr/addax
88
+ licenses: []
89
+
90
+ post_install_message:
91
+ rdoc_options: []
92
+
93
+ require_paths:
94
+ - lib
95
+ required_ruby_version: !ruby/object:Gem::Requirement
96
+ none: false
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ segments:
101
+ - 0
102
+ version: "0"
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ none: false
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ segments:
109
+ - 0
110
+ version: "0"
111
+ requirements: []
112
+
113
+ rubyforge_project:
114
+ rubygems_version: 1.3.7
115
+ signing_key:
116
+ specification_version: 3
117
+ summary: Command-line tool for accessing TIMA-SLS's ADDAX webservice.
118
+ test_files: []
119
+