com.proofpoint.galaxy.cli 0.5 → 0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/bin/galaxy +4 -1
  2. data/lib/galaxy.rb +300 -295
  3. metadata +2 -2
data/bin/galaxy CHANGED
@@ -1,3 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "galaxy"
3
+ $:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
4
+ require 'galaxy'
5
+
6
+ Galaxy::CLI.execute(ARGV)
data/lib/galaxy.rb CHANGED
@@ -1,323 +1,328 @@
1
+ #!/usr/bin/env ruby
1
2
  require 'optparse'
2
3
  require 'httpclient'
3
4
  require 'json'
5
+ require 'galaxy/version'
4
6
 
5
- GALAXY_VERSION = "0.1"
6
-
7
- exit_codes = {
8
- :success => 0,
9
- :no_slots => 1,
10
- :unsupported => 3,
11
- :invalid_usage => 64
12
- }
13
-
14
- #
15
- # Slot Information
16
- #
17
- class Slot
18
- attr_reader :id, :name, :host, :ip, :url, :binary, :config, :status
19
-
20
- def initialize(id, name, url, binary, config, status)
21
- @id = id
22
- @name = name
23
- @url = url
24
- @binary = binary
25
- @config = config
26
- @status = status
27
- uri = URI.parse(url)
28
- @host = uri.host
29
- @ip = IPSocket::getaddress(host)
30
- end
31
-
32
- def print_col
33
- puts "#{id}\t#{host}\t#{name}\t#{status}\t#{binary}\t#{config}"
34
- end
35
- end
36
-
37
- def strip(string)
38
- space = /(\s+)/.match(string)[1]
39
- string.gsub(/^#{space}/, '')
40
- end
41
-
42
- class CommandError < RuntimeError
43
- attr_reader :code
44
- attr_reader :message
45
-
46
- def initialize(code, message)
47
- @code = code
48
- @message = message
49
- end
50
- end
51
-
7
+ module Galaxy
8
+ GALAXY_VERSION = "0.1"
52
9
 
53
- #
54
- # Commands
55
- #
56
-
57
- def show(filter, options, args)
58
- if !args.empty? then
59
- raise CommandError.new(:invalid_usage, "You can not pass arguments to show.")
60
- end
61
- coordinator_request(filter, options, :get)
62
- end
63
-
64
- def assign(filter, options, args)
65
- if args.size != 2 then
66
- raise CommandError.new(:invalid_usage, "You must specify a binary and config to assign.")
67
- end
68
- if filter.empty? then
69
- raise CommandError.new(:invalid_usage, "You must specify a filter when for assign.")
70
- end
71
- if args[0].start_with? '@'
72
- config = args[0]
73
- binary = args[1]
74
- else
75
- binary = args[0]
76
- config = args[1]
77
-
78
- end
79
- assignment = {
80
- :binary => binary,
81
- :config => config
10
+ EXIT_CODES = {
11
+ :success => 0,
12
+ :no_slots => 1,
13
+ :unsupported => 3,
14
+ :invalid_usage => 64
82
15
  }
83
- coordinator_request(filter, options, :put, 'assignment', assignment, true)
84
- end
85
-
86
- def clear(filter, options, args)
87
- if !args.empty? then
88
- raise CommandError.new(:invalid_usage, "You can not pass arguments to clear.")
89
- end
90
- if filter.empty? then
91
- raise CommandError.new(:invalid_usage, "You must specify a filter when for clear.")
92
- end
93
- coordinator_request(filter, options, :delete, 'assignment')
94
- end
95
-
96
- def start(filter, options, args)
97
- if !args.empty? then
98
- raise CommandError.new(:invalid_usage, "You can not pass arguments to start.")
99
- end
100
- if filter.empty? then
101
- raise CommandError.new(:invalid_usage, "You must specify a filter when for start.")
102
- end
103
- coordinator_request(filter, options, :put, 'lifecycle', 'running')
104
- end
105
-
106
- def stop(filter, options, args)
107
- if !args.empty? then
108
- raise CommandError.new(:invalid_usage, "You can not pass arguments to stop.")
109
- end
110
- if filter.empty? then
111
- raise CommandError.new(:invalid_usage, "You must specify a filter when for stop.")
112
- end
113
- coordinator_request(filter, options, :put, 'lifecycle', 'stopped')
114
- end
115
-
116
- def restart(filter, options, args)
117
- if !args.empty? then
118
- raise CommandError.new(:invalid_usage, "You can not pass arguments to restart.")
119
- end
120
- if filter.empty? then
121
- raise CommandError.new(:invalid_usage, "You must specify a filter when for restart.")
122
- end
123
- coordinator_request(filter, options, :put, 'lifecycle', 'restarting')
124
- end
125
-
126
- def ssh(filter, options, args)
127
- if !args.empty? then
128
- raise CommandError.new(:invalid_usage, "You can not pass arguments to ssh.")
129
- end
130
- if filter.empty? then
131
- raise CommandError.new(:invalid_usage, "You must specify a filter when for ssh.")
132
- end
133
- slots = show(filter, options, args)
134
- if slots.empty?
135
- return []
136
- end
137
-
138
- slot = slots.first
139
- command = ENV['GALAXY_SSH_COMMAND'] || "ssh"
140
- Kernel.system "#{command} #{slot.host}"
141
- []
142
- end
143
-
144
- def coordinator_request(filter, options, method, sub_path = nil, value = nil, is_json = false)
145
- # build the uri
146
- uri = options[:coordinator_url]
147
- uri += '/' unless uri.end_with? '/'
148
- uri += 'v1/slot/'
149
- uri += sub_path unless sub_path.nil?
150
-
151
- # create filter query
152
- query = filter.map { |k, v| "#{URI.escape(k.to_s)}=#{URI.escape(v)}" }.join('&')
153
-
154
- # encode body as json if necessary
155
- body = value
156
- headers = {}
157
- if is_json
158
- body = value.to_json
159
- headers['Content-Type'] = 'application/json'
160
- end
161
16
 
162
- # log request in as a valid curl command if in debug mode
163
- if options[:debug]
164
- if value then
165
- puts "curl -H 'Content-Type: application/json' -X#{method.to_s.upcase} '#{uri}?#{query}' -d '"
166
- puts body
167
- puts "'"
168
- else
169
- puts "curl -X#{method.to_s.upcase} '#{uri}?#{query}'"
17
+ #
18
+ # Slot Information
19
+ #
20
+ class Slot
21
+ attr_reader :uuid, :host, :ip, :url, :binary, :config, :status
22
+
23
+ def initialize(uuid, url, binary, config, status)
24
+ @uuid = uuid
25
+ @url = url
26
+ @binary = binary
27
+ @config = config
28
+ @status = status
29
+ uri = URI.parse(url)
30
+ @host = uri.host
31
+ @ip = IPSocket::getaddress(host)
170
32
  end
171
- end
172
-
173
- # execute request
174
- response = HTTPClient.new.request(method, uri, query, body, headers).body
175
-
176
- # parse response as json
177
- slots_json = JSON.parse(response)
178
-
179
- # log response if in debug mode
180
- if options[:debug]
181
- puts slots_json
182
- end
183
-
184
- # convert parsed json into slot objects
185
- slots = slots_json.map do |slot_json|
186
- Slot.new(slot_json['id'], slot_json['name'], slot_json['self'], slot_json['binary'], slot_json['config'], slot_json['status'])
187
- end
188
-
189
- # verify response
190
- if slots.empty? then
191
- raise CommandError.new(:no_slots, "No slots match the provided filters.")
192
- end
193
-
194
- slots
195
- end
196
33
 
197
- #
198
- # Parse Command Line
199
- #
200
- commands = [:show, :assign, :clear, :start, :stop, :restart, :ssh]
201
- options = {
202
- :coordinator_url => ENV['GALAXY_COORDINATOR'] || 'http://localhost:64000'
203
- }
204
- filter = {}
205
-
206
- option_parser = OptionParser.new do |opts|
207
- opts.banner = "Usage: #{File.basename($0)} [options] <command>"
208
-
209
- opts.separator ''
210
- opts.separator 'Options:'
211
-
212
- opts.on('-h', '--help', 'Display this screen') do
213
- puts opts
214
- exit exit_codes[:success]
34
+ def print_col
35
+ puts "#{uuid}\t#{host}\t#{status}\t#{binary}\t#{config}"
36
+ end
215
37
  end
216
38
 
217
- opts.on("-v", "--version", "Display the Galaxy version number and exit") do
218
- puts "Galaxy version #{GALAXY_VERSION}"
219
- exit exit_codes[:success]
220
- end
39
+ class CommandError < RuntimeError
40
+ attr_reader :code
41
+ attr_reader :message
221
42
 
222
- opts.on("--coordinator COORDINATOR", "Galaxy coordinator host (overrides GALAXY_COORDINATOR)") do |v|
223
- options[:coordinator_url] = v
43
+ def initialize(code, message)
44
+ @code = code
45
+ @message = message
46
+ end
224
47
  end
225
48
 
226
- opts.on('--debug', 'Enable debug messages') do
227
- options[:debug] = true
228
- end
49
+ class Commands
50
+ def self.show(filter, options, args)
51
+ if !args.empty? then
52
+ raise CommandError.new(:invalid_usage, "You can not pass arguments to show.")
53
+ end
54
+ coordinator_request(filter, options, :get)
55
+ end
229
56
 
230
- opts.separator ''
231
- opts.separator 'Filters:'
57
+ def self.assign(filter, options, args)
58
+ if args.size != 2 then
59
+ raise CommandError.new(:invalid_usage, "You must specify a binary and config to assign.")
60
+ end
61
+ if filter.empty? then
62
+ raise CommandError.new(:invalid_usage, "You must specify a filter when for assign.")
63
+
64
+ end
65
+ if args[0].start_with? '@'
66
+ config = args[0]
67
+ binary = args[1]
68
+ else
69
+ binary = args[0]
70
+ config = args[1]
71
+
72
+ end
73
+ assignment = {
74
+ :binary => binary,
75
+ :config => config
76
+ }
77
+ coordinator_request(filter, options, :put, 'assignment', assignment, true)
78
+ end
232
79
 
233
- opts.on("-b", "--binary BINARY", "Select slots with a given binary") do |arg|
234
- filter[:binary] = arg
235
- end
80
+ def self.clear(filter, options, args)
81
+ if !args.empty? then
82
+ raise CommandError.new(:invalid_usage, "You can not pass arguments to clear.")
83
+ end
84
+ if filter.empty? then
85
+ raise CommandError.new(:invalid_usage, "You must specify a filter when for clear.")
86
+ end
87
+ coordinator_request(filter, options, :delete, 'assignment')
88
+ end
236
89
 
237
- opts.on("-c", "--config CONFIG", "Select slots with given configuration") do |arg|
238
- filter[:config] = arg
239
- end
90
+ def self.start(filter, options, args)
91
+ if !args.empty? then
92
+ raise CommandError.new(:invalid_usage, "You can not pass arguments to start.")
93
+ end
94
+ if filter.empty? then
95
+ raise CommandError.new(:invalid_usage, "You must specify a filter when for start.")
96
+ end
97
+ coordinator_request(filter, options, :put, 'lifecycle', 'running')
98
+ end
240
99
 
241
- opts.on("-i", "--host HOST", "Select slots on the given hostname") do |arg|
242
- filter[:host] = arg
243
- end
100
+ def self.stop(filter, options, args)
101
+ if !args.empty? then
102
+ raise CommandError.new(:invalid_usage, "You can not pass arguments to stop.")
103
+ end
104
+ if filter.empty? then
105
+ raise CommandError.new(:invalid_usage, "You must specify a filter when for stop.")
106
+ end
107
+ coordinator_request(filter, options, :put, 'lifecycle', 'stopped')
108
+ end
244
109
 
245
- opts.on("-I", "--ip IP", "Select slots at the given IP address") do |arg|
246
- filter[:ip] = arg
247
- end
110
+ def self.restart(filter, options, args)
111
+ if !args.empty? then
112
+ raise CommandError.new(:invalid_usage, "You can not pass arguments to restart.")
113
+ end
114
+ if filter.empty? then
115
+ raise CommandError.new(:invalid_usage, "You must specify a filter when for restart.")
116
+ end
117
+ coordinator_request(filter, options, :put, 'lifecycle', 'restarting')
118
+ end
248
119
 
249
- opts.on("-n", "--name SLOT_NAME", "Select slots with given slot name") do |arg|
250
- filter[:name] = arg
251
- end
120
+ def self.ssh(filter, options, args)
121
+ if !args.empty? then
122
+ raise CommandError.new(:invalid_usage, "You can not pass arguments to ssh.")
123
+ end
124
+ if filter.empty? then
125
+ raise CommandError.new(:invalid_usage, "You must specify a filter when for ssh.")
126
+ end
127
+ slots = show(filter, options, args)
128
+ if slots.empty?
129
+ return []
130
+ end
131
+
132
+ slot = slots.first
133
+ command = ENV['GALAXY_SSH_COMMAND'] || "ssh"
134
+ Kernel.system "#{command} #{slot.host}"
135
+ []
136
+ end
252
137
 
253
- opts.on("-s", "--state STATE", "Select 'r{unning}', 's{topped}', 'u{assigned}' or 'unknown' slots", [:running, :r, :stopped, :s, :unassigned, :u, :unknown]) do |arg|
254
- case arg
255
- when :running, :r then
256
- filter[:state] = 'running'
257
- when :stopped, :s then
258
- filter[:state] = 'stopped'
259
- when :unassigned, :u then
260
- filter[:state] = 'unassigned'
261
- when :unknown then
262
- filter[:state] = 'unknown'
138
+ private
139
+
140
+ def self.coordinator_request(filter, options, method, sub_path = nil, value = nil, is_json = false)
141
+ # build the uri
142
+ uri = options[:coordinator_url]
143
+ uri += '/' unless uri.end_with? '/'
144
+ uri += 'v1/slot/'
145
+ uri += sub_path unless sub_path.nil?
146
+
147
+ # create filter query
148
+ query = filter.map { |k, v| "#{URI.escape(k.to_s)}=#{URI.escape(v)}" }.join('&')
149
+
150
+ # encode body as json if necessary
151
+ body = value
152
+ headers = {}
153
+ if is_json
154
+ body = value.to_json
155
+ headers['Content-Type'] = 'application/json'
156
+ end
157
+
158
+ # log request in as a valid curl command if in debug mode
159
+ if options[:debug]
160
+ if value then
161
+ puts "curl -H 'Content-Type: application/json' -X#{method.to_s.upcase} '#{uri}?#{query}' -d '"
162
+ puts body
163
+ puts "'"
164
+ else
165
+ puts "curl -X#{method.to_s.upcase} '#{uri}?#{query}'"
166
+ end
167
+ end
168
+
169
+ # execute request
170
+ response = HTTPClient.new.request(method, uri, query, body, headers).body
171
+
172
+ # parse response as json
173
+ slots_json = JSON.parse(response)
174
+
175
+ # log response if in debug mode
176
+ if options[:debug]
177
+ puts slots_json
178
+ end
179
+
180
+ # convert parsed json into slot objects
181
+ slots = slots_json.map do |slot_json|
182
+ Slot.new(slot_json['id'], slot_json['self'], slot_json['binary'], slot_json['config'], slot_json['status'])
183
+ end
184
+
185
+ # verify response
186
+ if slots.empty? then
187
+ raise CommandError.new(:no_slots, "No slots match the provided filters.")
188
+ end
189
+
190
+ slots
263
191
  end
264
192
  end
265
193
 
266
- notes = <<-NOTES
267
- Notes:
268
- - A filter is required for all commands except for show
269
- - Filters are evaluated as: set | host | ip | state | (binary & config)
270
- - The HOST, BINARY, and CONFIG arguments are globs
271
- - BINARY format is groupId:artifactId[:packaging[:classifier]]:version
272
- - CONFIG format is @env:component[:pools]:version
273
- - The default filter selects all hosts
274
- NOTES
275
- opts.separator ''
276
- opts.separator strip(notes)
277
- opts.separator ''
278
- opts.separator 'Commands:'
279
- opts.separator " #{commands.join("\n ")}"
280
- end
281
-
282
- option_parser.parse!(ARGV)
283
-
284
- puts options.map { |k, v| "#{k}=#{v}" }.join("\n") if options[:debug]
285
- puts filter.map { |k, v| "#{k}=#{v}" }.join("\n") if options[:debug]
286
-
287
- if ARGV.length == 0
288
- puts option_parser
289
- exit exit_codes[:success]
290
- end
291
-
292
- command = ARGV[0].to_sym
293
-
294
- #
295
- # Execute Command
296
- #
297
- begin
298
- if !commands.include?(command)
299
- raise CommandError.new(:invalid_usage, "Unsupported command: #{command}")
300
- end
194
+ class CLI
195
+
196
+ COMMANDS = [:show, :assign, :clear, :start, :stop, :restart, :ssh]
197
+ INITIAL_OPTIONS = {
198
+ :coordinator_url => ENV['GALAXY_COORDINATOR'] || 'http://localhost:64000'
199
+ }
200
+
201
+ def self.parse_command_line(args)
202
+ options = INITIAL_OPTIONS
203
+
204
+ filter = Hash.new
205
+
206
+ option_parser = OptionParser.new do |opts|
207
+ opts.banner = "Usage: #{File.basename($0)} [options] <command>"
208
+
209
+ opts.separator ''
210
+ opts.separator 'Options:'
211
+
212
+ opts.on('-h', '--help', 'Display this screen') do
213
+ puts opts
214
+ exit EXIT_CODES[:success]
215
+ end
216
+
217
+ opts.on("-v", "--version", "Display the Galaxy version number and exit") do
218
+ puts "Galaxy version #{GALAXY_VERSION}"
219
+ exit EXIT_CODES[:success]
220
+ end
221
+
222
+ opts.on("--coordinator COORDINATOR", "Galaxy coordinator host (overrides GALAXY_COORDINATOR)") do |v|
223
+ options[:coordinator_url] = v
224
+ end
225
+
226
+ opts.on('--debug', 'Enable debug messages') do
227
+ options[:debug] = true
228
+ end
229
+
230
+ opts.separator ''
231
+ opts.separator 'Filters:'
232
+
233
+ opts.on("-b", "--binary BINARY", "Select slots with a given binary") do |arg|
234
+ filter[:binary] = arg
235
+ end
236
+
237
+ opts.on("-c", "--config CONFIG", "Select slots with given configuration") do |arg|
238
+ filter[:config] = arg
239
+ end
240
+
241
+ opts.on("-i", "--host HOST", "Select slots on the given hostname") do |arg|
242
+ filter[:host] = arg
243
+ end
244
+
245
+ opts.on("-I", "--ip IP", "Select slots at the given IP address") do |arg|
246
+ filter[:ip] = arg
247
+ end
248
+
249
+ opts.on("-u", "--uuid SLOT_UUID", "Select slots with given slot uuid") do |arg|
250
+ filter[:uuid] = arg
251
+ end
252
+
253
+ opts.on("-s", "--state STATE", "Select 'r{unning}', 's{topped}', 'u{assigned}' or 'unknown' slots", [:running, :r, :stopped, :s, :unassigned, :u, :unknown]) do |arg|
254
+ case arg
255
+ when :running, :r then
256
+ filter[:state] = 'running'
257
+ when :stopped, :s then
258
+ filter[:state] = 'stopped'
259
+ when :unassigned, :u then
260
+ filter[:state] = 'unassigned'
261
+ when :unknown then
262
+ filter[:state] = 'unknown'
263
+ end
264
+ end
265
+
266
+ opts.separator ''
267
+ opts.separator <<-NOTES
268
+ Notes:
269
+ - A filter is required for all commands except for show
270
+ - Filters are evaluated as: set | host | ip | state | (binary & config)
271
+ - The HOST, BINARY, and CONFIG arguments are globs
272
+ - BINARY format is groupId:artifactId[:packaging[:classifier]]:version
273
+ - CONFIG format is @env:component[:pools]:version
274
+ - The default filter selects all hosts
275
+ NOTES
276
+ opts.separator ''
277
+ opts.separator 'Commands:'
278
+ opts.separator " #{COMMANDS.join("\n ")}"
279
+ end
280
+
281
+ option_parser.parse!(args)
282
+
283
+ puts options.map { |k, v| "#{k}=#{v}" }.join("\n") if options[:debug]
284
+ puts filter.map { |k, v| "#{k}=#{v}" }.join("\n") if options[:debug]
285
+
286
+ if args.length == 0
287
+ puts option_parser
288
+ exit EXIT_CODES[:success]
289
+ end
290
+
291
+ command = args[0].to_sym
292
+
293
+ unless COMMANDS.include?(command)
294
+ raise CommandError.new(:invalid_usage, "Unsupported command: #{command}")
295
+ end
296
+
297
+ if options[:coordinator_url].nil? || options[:coordinator_url].empty?
298
+ raise CommandError.new(:invalid_usage, "You must set Galaxy coordinator host by passing --coordinator COORDINATOR or by setting the GALAXY_COORDINATOR environment variable.")
299
+ end
300
+
301
+ return [command, filter, options, args.drop(1)]
302
+ end
301
303
 
302
- if options[:coordinator_url].nil? || options[:coordinator_url].empty?
303
- raise CommandError.new(:invalid_usage, "You must set Galaxy coordinator host by passing --coordinator COORDINATOR or by setting the GALAXY_COORDINATOR environment variable.")
304
- end
304
+ def self.execute(args)
305
+ begin
306
+ (command, filter, options, command_args) = parse_command_line(args)
307
+ slots = Commands.send(command, filter, options, command_args)
308
+ slots = slots.sort_by { |slot| "#{slot.ip}|#{slot.binary}|#{slot.config}|#{slot.uuid}" }
309
+ puts '' if options[:debug]
310
+ puts "uuid\tip\tstatus\tbinary\tconfig"
311
+ slots.each { |slot| slot.print_col } unless slots.nil?
312
+ exit EXIT_CODES[:success]
313
+ rescue CommandError => e
314
+ puts e.message
315
+ if e.code == :invalid_usage
316
+ puts ''
317
+ parse_command_line([])
318
+ end
319
+ if options[:debug]
320
+ puts ''
321
+ puts "exit: #{e.code}"
322
+ end
323
+ exit EXIT_CODES[e.code]
324
+ end
325
+ end
305
326
 
306
- slots = send(command, filter, options, ARGV.drop(1))
307
- slots = slots.sort_by { |slot| slot.name + slot.id }
308
- puts '' if options[:debug]
309
- slots.each { |slot| slot.print_col } unless slots.nil?
310
- exit exit_codes[:success]
311
- rescue CommandError => e
312
- puts e.message
313
- if e.code == :invalid_usage
314
- puts ''
315
- puts option_parser
316
327
  end
317
- if options[:debug]
318
- puts ''
319
- puts "exit: #{e.code}"
320
- end
321
- exit exit_codes[e.code]
322
328
  end
323
-
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: com.proofpoint.galaxy.cli
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: "0.5"
5
+ version: "0.6"
6
6
  platform: ruby
7
7
  authors:
8
8
  - Dain Sundstrom
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-05-18 00:00:00 -07:00
13
+ date: 2011-06-22 00:00:00 -07:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency