com.proofpoint.galaxy.cli 0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/bin/galaxy +3 -0
  2. data/lib/galaxy.rb +323 -0
  3. data/lib/galaxy/version.rb +3 -0
  4. metadata +91 -0
data/bin/galaxy ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "galaxy"
data/lib/galaxy.rb ADDED
@@ -0,0 +1,323 @@
1
+ require 'optparse'
2
+ require 'httpclient'
3
+ require 'json'
4
+
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
+
52
+
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
82
+ }
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
+
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}'"
170
+ 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
+
197
+ #
198
+ # Parse Command Line
199
+ #
200
+ commands = [:show, :assign, :clear, :start, :stop, :restart, :ssh]
201
+ options = {
202
+ :coordinator_url => ENV['GALAXY_COORDINATOR']
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]
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("-n", "--name SLOT_NAME", "Select slots with given slot name") do |arg|
250
+ filter[:name] = 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
+ 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
301
+
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
305
+
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
+ end
317
+ if options[:debug]
318
+ puts ''
319
+ puts "exit: #{e.code}"
320
+ end
321
+ exit exit_codes[e.code]
322
+ end
323
+
@@ -0,0 +1,3 @@
1
+ module Galaxy
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: com.proofpoint.galaxy.cli
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 2
8
+ version: "0.2"
9
+ platform: ruby
10
+ authors:
11
+ - Dain Sundstrom
12
+ autorequire:
13
+ bindir: bin
14
+ cert_chain: []
15
+
16
+ date: 2011-05-02 00:00:00 -07:00
17
+ default_executable:
18
+ dependencies:
19
+ - !ruby/object:Gem::Dependency
20
+ name: httpclient
21
+ prerelease: false
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ segments:
27
+ - 2
28
+ - 2
29
+ - 0
30
+ version: 2.2.0
31
+ type: :runtime
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: json_pure
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ segments:
41
+ - 1
42
+ - 5
43
+ - 1
44
+ version: 1.5.1
45
+ type: :runtime
46
+ version_requirements: *id002
47
+ description: Galaxy command line interface
48
+ email:
49
+ - dain@iq80.com
50
+ executables:
51
+ - galaxy
52
+ extensions: []
53
+
54
+ extra_rdoc_files: []
55
+
56
+ files:
57
+ - bin/galaxy
58
+ - lib/galaxy.rb
59
+ - lib/galaxy/version.rb
60
+ has_rdoc: true
61
+ homepage: https://github.com/dain/galaxy-server
62
+ licenses: []
63
+
64
+ post_install_message:
65
+ rdoc_options: []
66
+
67
+ require_paths:
68
+ - lib
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ segments:
74
+ - 0
75
+ version: "0"
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ segments:
81
+ - 0
82
+ version: "0"
83
+ requirements: []
84
+
85
+ rubyforge_project: galaxy
86
+ rubygems_version: 1.3.6
87
+ signing_key:
88
+ specification_version: 3
89
+ summary: galaxy
90
+ test_files: []
91
+