com.proofpoint.galaxy.cli 0.2

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 (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
+