omnibus-ctl 0.3.3

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3f727fad81d619b5de76e830757918590df8b636
4
+ data.tar.gz: 2a606b930145058c04f31a36f14ff4f32f1d1449
5
+ SHA512:
6
+ metadata.gz: ed89feaa9a4cfedb22f06640efd44644f1908cc6c254ba19185e41e144d722006855cb57c451c86e293448a3269ecae36acf725948cab7f83539df0e01aec4f7
7
+ data.tar.gz: 4627bd21c3569788abdca489e4d94096d847861fbfee83f35eb9cbbaeb67e29c4859dd5e67507ad8e94fe9d4f849d4ccee3a805aac8ab9ff6830263b37c57a21
data/README.md ADDED
@@ -0,0 +1,85 @@
1
+ ## omnibus-ctl
2
+
3
+ omnibus-ctl provides service control and configuration for omnibus packages.
4
+
5
+ Not much to see here yet.
6
+
7
+ ### Run the Tests!
8
+
9
+ There are tests in this repo that should be run before merging to master in the `spec` directory.
10
+
11
+ To run them, first install rspec via bundler:
12
+
13
+ ```
14
+ bundle install --binstubs
15
+ ```
16
+
17
+ Then run the tests:
18
+
19
+ ```
20
+ ./bin/rspec spec/
21
+ ```
22
+
23
+ ### Framework API
24
+
25
+ There are two main functions you will use in your `*-ctl` project to add commands.
26
+
27
+ #### add_command_under_category(string, string, string, int, ruby_block)
28
+
29
+ This method will add a new command to your ctl under a category, useful for grouping similar commands together logically in help output.
30
+
31
+ Input arguments:
32
+
33
+ 1. Name of the command.
34
+ 2. Category of the command. It should be string consisting of only characters and "-". If the category does not exist, it will be added. Default categories are "general" and "service-management" (if the latter is enabled).
35
+ 3. Description. This will be outputted below the command name when the help command is run.
36
+ 4. Arity. TODO: Due to current bug, this must be 2, I believe. We should fix this.
37
+ 5. Ruby block. Ruby code to be executed when your command is run (arguments to that command will be passed into the block).
38
+
39
+ #### add_command(string, string, int, ruby_block)
40
+
41
+ This method will add a new command to your ctl without a category. It will be displayed above all categories when the help command is called.
42
+
43
+ Input arguments are the same as `add_command_under_category` except 2 doesn't exist.
44
+
45
+ #### Sample Output
46
+
47
+ ```
48
+ # sample-ctl help
49
+ /opt/opscode/embedded/bin/sample-ctl: command (subcommand)
50
+ command-without-category
51
+ Here is an insightful description for the above command, added via add_command.
52
+ another-command-without-category
53
+ Yet another description.
54
+ Some Category Of Commands:
55
+ command-with-category
56
+ Exciting description of command added via add_command_under_category.
57
+ better-command-with-category
58
+ You get the idea.
59
+ Another Category:
60
+ command-with-better-category
61
+ I'm not just going to copy-pasta above example descriptions.
62
+ better-command-with-better-category
63
+ I'm running out of ideas.
64
+ ```
65
+
66
+ If you only use `add_command_under_category` to add your custom commands, everything will be outputted under a category.
67
+
68
+ ### Licensing
69
+
70
+ See the LICENSE file for details.
71
+
72
+ Copyright: Copyright (c) 2012 Opscode, Inc.
73
+ License: Apache License, Version 2.0
74
+
75
+ Licensed under the Apache License, Version 2.0 (the "License");
76
+ you may not use this file except in compliance with the License.
77
+ You may obtain a copy of the License at
78
+
79
+ http://www.apache.org/licenses/LICENSE-2.0
80
+
81
+ Unless required by applicable law or agreed to in writing, software
82
+ distributed under the License is distributed on an "AS IS" BASIS,
83
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
84
+ See the License for the specific language governing permissions and
85
+ limitations under the License.
data/bin/omnibus-ctl ADDED
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/ruby
2
+ #
3
+ # Author:: Adam Jacob (<adam@opscode.com>)
4
+ # Copyright:: Copyright (c) 2011 Opscode, Inc.
5
+ # License:: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ require 'omnibus-ctl'
21
+
22
+ # service name: ARGV[0]
23
+ # additional modules: ARGV[1]
24
+ # command: ARGV[2]
25
+ # service: ARGV[3]
26
+ # options: ARGV[4..]
27
+
28
+ ctl = Omnibus::Ctl.new(ARGV[0])
29
+ ctl.load_files(ARGV[1])
30
+ arguments = ARGV[2..-1] # Get the rest of the command line arguments
31
+ ctl.run(arguments)
32
+ exit 0
33
+
@@ -0,0 +1,559 @@
1
+ #
2
+ # Copyright:: Copyright (c) 2012 Opscode, Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require "omnibus-ctl/version"
19
+ require 'json'
20
+ require 'fileutils'
21
+
22
+ module Omnibus
23
+ class Ctl
24
+
25
+ File::umask(022)
26
+
27
+ SV_COMMAND_NAMES = %w[status up down once pause cont hup alarm interrupt quit
28
+ term kill start stop restart shutdown force-stop
29
+ force-reload force-restart force-shutdown check]
30
+
31
+ attr_accessor :name, :display_name, :log_exclude, :base_path, :sv_path,
32
+ :service_path, :etc_path, :data_path, :log_path, :command_map, :category_command_map,
33
+ :fh_output, :kill_users, :verbose, :log_path_exclude
34
+
35
+ def initialize(name, service_commands=true)
36
+ @name = name
37
+ @service_commands = service_commands
38
+ @display_name = name
39
+ @base_path = "/opt/#{name}"
40
+ @sv_path = File.join(@base_path, "sv")
41
+ @service_path = File.join(@base_path, "service")
42
+ @log_path = "/var/log/#{name}"
43
+ @data_path = "/var/opt/#{name}"
44
+ @etc_path = "/etc/#{name}"
45
+ @log_exclude = '(config|lock|@|gzip|tgz|gz)'
46
+ @log_path_exclude = ['*/sasl/*']
47
+ @fh_output = STDOUT
48
+ @kill_users = []
49
+ @verbose = false
50
+ # backwards compat command map that does not have categories
51
+ @command_map = { }
52
+
53
+ # categoired commands that we want by default
54
+ @category_command_map = {
55
+ "general" => {
56
+ "show-config" => {
57
+ :desc => "Show the configuration that would be generated by reconfigure.",
58
+ :arity => 1
59
+ },
60
+ "reconfigure" => {
61
+ :desc => "Reconfigure the application.",
62
+ :arity => 1
63
+ },
64
+ "cleanse" => {
65
+ :desc => "Delete *all* #{display_name} data, and start from scratch.",
66
+ :arity => 2
67
+ },
68
+ "uninstall" => {
69
+ :arity => 1,
70
+ :desc => "Kill all processes and uninstall the process supervisor (data will be preserved)."
71
+ },
72
+ "help" => {
73
+ :arity => 1,
74
+ :desc => "Print this help message."
75
+ }
76
+ }
77
+ }
78
+ service_command_map = {
79
+ "service-management" => {
80
+ "service-list" => {
81
+ :arity => 1,
82
+ :desc => "List all the services (enabled services appear with a *.)"
83
+ },
84
+ "status" => {
85
+ :desc => "Show the status of all the services.",
86
+ :arity => 2
87
+ },
88
+ "tail" => {
89
+ :desc => "Watch the service logs of all enabled services.",
90
+ :arity => 2
91
+ },
92
+ "start" => {
93
+ :desc => "Start services if they are down, and restart them if they stop.",
94
+ :arity => 2
95
+ },
96
+ "stop" => {
97
+ :desc => "Stop the services, and do not restart them.",
98
+ :arity => 2
99
+ },
100
+ "restart" => {
101
+ :desc => "Stop the services if they are running, then start them again.",
102
+ :arity => 2
103
+ },
104
+ "once" => {
105
+ :desc => "Start the services if they are down. Do not restart them if they stop.",
106
+ :arity => 2
107
+ },
108
+ "hup" => {
109
+ :desc => "Send the services a HUP.",
110
+ :arity => 2
111
+ },
112
+ "term" => {
113
+ :desc => "Send the services a TERM.",
114
+ :arity => 2
115
+ },
116
+ "int" => {
117
+ :desc => "Send the services an INT.",
118
+ :arity => 2
119
+ },
120
+ "kill" => {
121
+ :desc => "Send the services a KILL.",
122
+ :arity => 2
123
+ },
124
+ "graceful-kill" => {
125
+ :desc => "Attempt a graceful stop, then SIGKILL the entire process group.",
126
+ :arity => 2
127
+ }
128
+ }
129
+ }
130
+ @category_command_map.merge!(service_command_map) if service_commands?
131
+ end
132
+
133
+ SV_COMMAND_NAMES.each do |sv_cmd|
134
+ method_name = sv_cmd.gsub(/-/, "_")
135
+ Omnibus::Ctl.class_eval <<-EOH
136
+ def #{method_name}(*args)
137
+ run_sv_command(*args)
138
+ end
139
+ EOH
140
+ end
141
+
142
+ # merges category_command_map and command_map,
143
+ # removing categories
144
+ def get_all_commands_hash
145
+ without_categories = {}
146
+ category_command_map.each do |category, commands|
147
+ without_categories.merge!(commands)
148
+ end
149
+ command_map.merge(without_categories)
150
+ end
151
+
152
+ def service_commands?
153
+ @service_commands
154
+ end
155
+
156
+ def load_files(path)
157
+ Dir["#{path}/*.rb"].each do |file|
158
+ eval(IO.read(file))
159
+ end
160
+ end
161
+
162
+ def add_command(name, description, arity=1, &block)
163
+ @command_map[name] = { :desc => description, :arity => arity }
164
+ metaclass = class << self; self; end
165
+ # Ruby does not like dashes in method names
166
+ method_name = name.gsub(/-/, "_")
167
+ metaclass.send(:define_method, method_name.to_sym) { |*args| block.call(*args) }
168
+ end
169
+
170
+ def add_command_under_category(name, category, description, arity=1, &block)
171
+ # add new category if it doesn't exist
172
+ @category_command_map[category] = {} unless @category_command_map.has_key?(category)
173
+ @category_command_map[category][name] = { :desc => description, :arity => arity }
174
+ metaclass = class << self; self; end
175
+ # Ruby does not like dashes in method names
176
+ method_name = name.gsub(/-/, "_")
177
+ metaclass.send(:define_method, method_name.to_sym) { |*args| block.call(*args) }
178
+ end
179
+
180
+ def exit!(error_code)
181
+ exit error_code
182
+ end
183
+
184
+ def log(msg)
185
+ fh_output.puts msg
186
+ end
187
+
188
+ def get_pgrp_from_pid(pid)
189
+ ps=`which ps`.chomp
190
+ `#{ps} -p #{pid} -o pgrp=`.chomp
191
+ end
192
+
193
+ def get_pids_from_pgrp(pgrp)
194
+ pgrep=`which pgrep`.chomp
195
+ `#{pgrep} -g #{pgrp}`.split(/\n/).join(" ")
196
+ end
197
+
198
+ def sigkill_pgrp(pgrp)
199
+ pkill=`which pkill`.chomp
200
+ run_command("#{pkill} -9 -g #{pgrp}")
201
+ end
202
+
203
+ def run_command(command)
204
+ system(command)
205
+ $?
206
+ end
207
+
208
+ def service_list(*args)
209
+ get_all_services.each do |service_name|
210
+ print "#{service_name}"
211
+ print "*" if service_enabled?(service_name)
212
+ print "\n"
213
+ end
214
+ exit! 0
215
+ end
216
+
217
+ def cleanup_procs_and_nuke(filestr)
218
+ begin
219
+ run_sv_command("stop")
220
+ rescue SystemExit
221
+ end
222
+
223
+ FileUtils.rm_f("/etc/init/#{name}-runsvdir.conf") if File.exists?("/etc/init/#{name}-runsvdir.conf")
224
+ run_command("egrep -v '#{base_path}/embedded/bin/runsvdir-start' /etc/inittab > /etc/inittab.new && mv /etc/inittab.new /etc/inittab") if File.exists?("/etc/inittab")
225
+ run_command("kill -1 1")
226
+
227
+ backup_dir = Time.now.strftime("/root/#{name}-cleanse-%FT%R")
228
+ FileUtils.mkdir_p("/root") unless File.exists?("/root")
229
+ FileUtils.rm_rf(backup_dir)
230
+ FileUtils.cp_r(etc_path, backup_dir) if File.exists?(etc_path)
231
+ run_command("rm -rf #{filestr}")
232
+
233
+ begin
234
+ graceful_kill
235
+ rescue SystemExit
236
+ end
237
+
238
+ run_command("pkill -HUP -u #{kill_users.join(',')}") if kill_users.length > 0
239
+ run_command("pkill -HUP -f 'runsvdir -P #{service_path}'")
240
+ sleep 3
241
+ run_command("pkill -TERM -u #{kill_users.join(',')}") if kill_users.length > 0
242
+ run_command("pkill -TERM -f 'runsvdir -P #{service_path}'")
243
+ sleep 3
244
+ run_command("pkill -KILL -u #{kill_users.join(',')}") if kill_users.length > 0
245
+ run_command("pkill -KILL -f 'runsvdir -P #{service_path}'")
246
+
247
+ get_all_services.each do |die_daemon_die|
248
+ run_command("pkill -KILL -f 'runsv #{die_daemon_die}'")
249
+ end
250
+
251
+ log "Your config files have been backed up to #{backup_dir}."
252
+ exit! 0
253
+ end
254
+
255
+ def uninstall(*args)
256
+ cleanup_procs_and_nuke("/tmp/opt")
257
+ end
258
+
259
+ def cleanse(*args)
260
+ log "This will delete *all* configuration, log, and variable data associated with this application.\n\n*** You have 60 seconds to hit CTRL-C ***\n\n"
261
+ unless args[1] == "yes"
262
+ sleep 60
263
+ end
264
+ cleanup_procs_and_nuke("#{service_path}/* /tmp/opt #{data_path} #{etc_path} #{log_path}")
265
+ end
266
+
267
+ def get_all_services_files
268
+ Dir[File.join(sv_path, '*')]
269
+ end
270
+
271
+ def get_all_services
272
+ get_all_services_files.map { |f| File.basename(f) }.sort
273
+ end
274
+
275
+ def service_enabled?(service_name)
276
+ File.symlink?("#{service_path}/#{service_name}")
277
+ end
278
+
279
+ def run_sv_command(sv_cmd, service=nil)
280
+ exit_status = 0
281
+ if service
282
+ exit_status += run_sv_command_for_service(sv_cmd, service)
283
+ else
284
+ get_all_services.each do |service_name|
285
+ exit_status += run_sv_command_for_service(sv_cmd, service_name) if global_service_command_permitted(sv_cmd, service_name)
286
+ end
287
+ end
288
+ exit! exit_status
289
+ end
290
+
291
+ # run an sv command for a specific service name
292
+ def run_sv_command_for_service(sv_cmd, service_name)
293
+ if service_enabled?(service_name)
294
+ status = run_command("#{base_path}/init/#{service_name} #{sv_cmd}")
295
+ return status.exitstatus
296
+ else
297
+ log "#{service_name} disabled" if sv_cmd == "status" && verbose
298
+ return 0
299
+ end
300
+ end
301
+
302
+ # if we're running a global service command (like p-c-c status)
303
+ # across all of the services, there are certain cases where we
304
+ # want to prevent services files that exist in the service
305
+ # directory from being activated. This method is the logic that
306
+ # blocks those services
307
+ def global_service_command_permitted(sv_cmd, service_name)
308
+ # For services that have been removed, we only want to
309
+ # them to respond to the stop command. They should not show
310
+ # up in status, and they should not be started.
311
+ if removed_services.include?(service_name)
312
+ return sv_cmd == "stop"
313
+ end
314
+
315
+ # For keepalived, we only want it to respond to the status
316
+ # command when running global service commands like p-c-c start
317
+ # and p-c-c stop
318
+ if service_name == "keepalived"
319
+ return sv_cmd == "status"
320
+ end
321
+
322
+ # If c-s-c status is called, check to see if the service
323
+ # is hidden supposed to be hidden from the status results
324
+ # (mover for example should be hidden).
325
+ if sv_cmd == "status"
326
+ return !(hidden_services.include?(service_name))
327
+ end
328
+
329
+ # All other services respond normally to p-c-c * commands
330
+ return true
331
+ end
332
+
333
+ # removed services are configured via the attributes file in
334
+ # the main omnibus cookbook
335
+ def removed_services
336
+ # in the case that there is no running_config (the config file does
337
+ # not exist), we know that this will be a new server, and we don't
338
+ # have to worry about pre-upgrade services hanging around. We can safely
339
+ # return an empty array when running_config is nil
340
+ if (cfg = running_config)
341
+ key = package_name.gsub(/-/, '_')
342
+ cfg[key]["removed_services"] || []
343
+ else
344
+ []
345
+ end
346
+ end
347
+
348
+ # hidden services are configured via the attributes file in
349
+ # the main omnibus cookbook
350
+ #
351
+ # hidden services are services that we do not want to show up in
352
+ # c-s-c status.
353
+ def hidden_services
354
+ # in the case that there is no running_config (the config file does
355
+ # not exist), we don't want to return nil, just return an empty array.
356
+ # worse result with doing that is services that we don't want to show up in
357
+ # c-s-c status will show up.
358
+ if (cfg = running_config)
359
+ key = package_name.gsub(/-/, '_')
360
+ cfg[key]["hidden_services"] || []
361
+ else
362
+ []
363
+ end
364
+ end
365
+
366
+ # translate the name from the config to the package name.
367
+ # this is a special case for the private-chef package because
368
+ # it is configured to use the name and directory structure of
369
+ # 'opscode', not 'private-chef'
370
+ def package_name
371
+ case @name
372
+ when "opscode"
373
+ "private-chef"
374
+ else
375
+ @name
376
+ end
377
+ end
378
+
379
+ # returns nil when chef-server-running.json does not exist
380
+ def running_config
381
+ @running_config ||= begin
382
+ if File.exists?("#{etc_path}/chef-server-running.json")
383
+ JSON.parse(File.read("#{etc_path}/chef-server-running.json"))
384
+ end
385
+ end
386
+ end
387
+
388
+ def show_config(*args)
389
+ status = run_command("#{base_path}/embedded/bin/chef-client -z -c #{base_path}/embedded/cookbooks/solo.rb -j #{base_path}/embedded/cookbooks/show-config.json -l fatal")
390
+ if status.success?
391
+ exit! 0
392
+ else
393
+ exit! 1
394
+ end
395
+ end
396
+
397
+ def reconfigure(exit_on_success=true)
398
+ status = run_command("#{base_path}/embedded/bin/chef-client -z -c #{base_path}/embedded/cookbooks/solo.rb -j #{base_path}/embedded/cookbooks/dna.json")
399
+ if status.success?
400
+ log "#{display_name} Reconfigured!"
401
+ exit! 0 if exit_on_success
402
+ else
403
+ exit! 1
404
+ end
405
+ end
406
+
407
+ def tail(*args)
408
+ # find /var/log -type f -not -path '*/sasl/*' | grep -E -v '(lock|@|tgz|gzip)' | xargs tail --follow=name --retry
409
+ command = "find #{log_path}"
410
+ command << "/#{args[1]}" if args[1]
411
+ command << ' -type f'
412
+ command << log_path_exclude.map { |path| " -not -path #{path}" }.join(' ')
413
+ command << " | grep -E -v '#{log_exclude}' | xargs tail --follow=name --retry"
414
+
415
+ system(command)
416
+ end
417
+
418
+ def is_integer?(string)
419
+ return true if Integer(string) rescue false
420
+ end
421
+
422
+ def graceful_kill(*args)
423
+ service = args[1]
424
+ exit_status = 0
425
+ get_all_services.each do |service_name|
426
+ next if !service.nil? && service_name != service
427
+ if service_enabled?(service_name)
428
+ pidfile="#{sv_path}/#{service_name}/supervise/pid"
429
+ pid=File.read(pidfile).chomp if File.exists?(pidfile)
430
+ if pid.nil? || !is_integer?(pid)
431
+ log "could not find #{service_name} runit pidfile (service already stopped?), cannot attempt SIGKILL..."
432
+ status = run_command("#{base_path}/init/#{service_name} stop")
433
+ exit_status = status.exitstatus if exit_status == 0 && !status.success?
434
+ next
435
+ end
436
+ pgrp=get_pgrp_from_pid(pid)
437
+ if pgrp.nil? || !is_integer?(pgrp)
438
+ log "could not find pgrp of pid #{pid} (not running?), cannot attempt SIGKILL..."
439
+ status = run_command("#{base_path}/init/#{service_name} stop")
440
+ exit_status = status.exitstatus if exit_status == 0 && !status.success?
441
+ next
442
+ end
443
+ run_command("#{base_path}/init/#{service_name} stop")
444
+ pids=get_pids_from_pgrp(pgrp)
445
+ if !pids.empty?
446
+ log "found stuck pids still running in process group: #{pids}, sending SIGKILL" unless pids.empty?
447
+ sigkill_pgrp(pgrp)
448
+ end
449
+ else
450
+ log "#{service_name} disabled, not stopping"
451
+ exit_status = 1
452
+ end
453
+ end
454
+ exit! exit_status
455
+ end
456
+
457
+ def help(*args)
458
+ log "#{$0}: command (subcommand)\n"
459
+ command_map.keys.sort.each do |command|
460
+ log command
461
+ log " #{command_map[command][:desc]}"
462
+ end
463
+ category_command_map.each do |category, commands|
464
+ # Remove "-" and replace with spaces in category and capalize for output
465
+ category_string = category.gsub("-", " ").split.map(&:capitalize).join(' ')
466
+ log "#{category_string} Commands:\n"
467
+
468
+ # Print each command in this category
469
+ commands.keys.sort.each do |command|
470
+ log " #{command}"
471
+ log " #{commands[command][:desc]}"
472
+ end
473
+ end
474
+ exit! 1
475
+ end
476
+
477
+ # Set options. Silently ignore bad options.
478
+ # This allows the test subcommand to pass on pedant options
479
+ def parse_options!(args)
480
+ args.each do |option|
481
+ case option
482
+ when "--verbose", "-v"
483
+ @verbose = true
484
+ end
485
+ end
486
+ end
487
+
488
+ # If it begins with a '-', it is an option.
489
+ def is_option?(arg)
490
+ arg && arg[0] == '-'
491
+ end
492
+
493
+ # retrieves the commmand from either the command_map
494
+ # or the category_command_map, if the command is not found
495
+ # return nil
496
+ def retrieve_command(command_to_run)
497
+ if command_map.has_key?(command_to_run)
498
+ command_map[command_to_run]
499
+ else
500
+ command = nil
501
+ category_command_map.each do |category, commands|
502
+ command = commands[command_to_run] if commands.has_key?(command_to_run)
503
+ end
504
+ # return the command, or nil if it wasn't found
505
+ command
506
+ end
507
+ end
508
+
509
+ def run(args)
510
+ # Ensure Omnibus related binaries are in the PATH
511
+ ENV["PATH"] = [File.join(base_path, "bin"),
512
+ File.join(base_path, "embedded","bin"),
513
+ ENV['PATH']].join(":")
514
+
515
+ command_to_run = args[0]
516
+
517
+ # This piece of code checks if the argument is an option. If it is,
518
+ # then it sets service to nil and adds the argument into the options
519
+ # argument. This is ugly. A better solution is having a proper parser.
520
+ # But if we are going to implement a proper parser, we might as well
521
+ # port this to Thor rather than reinventing Thor. For now, this preserves
522
+ # the behavior to complain and exit with an error if one attempts to invoke
523
+ # a pcc command that does not accept an argument. Like "help".
524
+ options = args[2..-1] || []
525
+ if is_option?(args[1])
526
+ options.unshift(args[1])
527
+ service = nil
528
+ else
529
+ service = args[1]
530
+ end
531
+
532
+ # returns either hash content of comamnd or nil
533
+ command = retrieve_command(command_to_run)
534
+
535
+ if command.nil?
536
+ log "I don't know that command."
537
+ if args.length == 2
538
+ log "Did you mean: #{$0} #{service} #{command_to_run}?"
539
+ end
540
+ help
541
+ end
542
+
543
+ if args.length > 1 && command[:arity] != 2
544
+ log "The command #{command_to_run} does not accept any arguments"
545
+ exit! 2
546
+ end
547
+
548
+ parse_options! options
549
+
550
+ method_to_call = command_to_run.gsub(/-/, '_')
551
+ # Filter args to just command and service. If you are loading
552
+ # custom commands and need access to the command line argument,
553
+ # use ARGV directly.
554
+ actual_args = [command_to_run, service].reject(&:nil?)
555
+ self.send(method_to_call.to_sym, *actual_args)
556
+ end
557
+
558
+ end
559
+ end
@@ -0,0 +1,5 @@
1
+ module Omnibus
2
+ class Ctl
3
+ VERSION = "0.3.3"
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: omnibus-ctl
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.3
5
+ platform: ruby
6
+ authors:
7
+ - Opscode, Inc.
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-03-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec_junit_formatter
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Provides command line control for omnibus pakcages, rarely used as a
42
+ gem
43
+ email:
44
+ - legal@opscode.com
45
+ executables:
46
+ - omnibus-ctl
47
+ extensions: []
48
+ extra_rdoc_files: []
49
+ files:
50
+ - README.md
51
+ - bin/omnibus-ctl
52
+ - lib/omnibus-ctl.rb
53
+ - lib/omnibus-ctl/version.rb
54
+ homepage: http://github.com/opscode/omnibus-ctl
55
+ licenses: []
56
+ metadata: {}
57
+ post_install_message:
58
+ rdoc_options: []
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ requirements: []
72
+ rubyforge_project:
73
+ rubygems_version: 2.2.2
74
+ signing_key:
75
+ specification_version: 4
76
+ summary: Provides command line control for omnibus packages
77
+ test_files: []
78
+ has_rdoc: