hobo-inviqa 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +15 -0
  2. data/.editorconfig +10 -0
  3. data/Gemfile.lock +19 -4
  4. data/Guardfile +2 -2
  5. data/Hobofile +5 -1
  6. data/README.md +8 -32
  7. data/bin/hobo +12 -18
  8. data/hobo.gemspec +3 -0
  9. data/lib/hobo.rb +8 -1
  10. data/lib/hobo/cli.rb +14 -3
  11. data/lib/hobo/error_handlers/debug.rb +5 -2
  12. data/lib/hobo/error_handlers/exit_code_map.rb +16 -0
  13. data/lib/hobo/error_handlers/friendly.rb +8 -8
  14. data/lib/hobo/errors.rb +11 -1
  15. data/lib/hobo/helper/http_download.rb +41 -0
  16. data/lib/hobo/helper/shell.rb +3 -2
  17. data/lib/hobo/helper/vm_command.rb +235 -14
  18. data/lib/hobo/lib/host_check.rb +20 -6
  19. data/lib/hobo/lib/host_check/deps.rb +22 -4
  20. data/lib/hobo/lib/host_check/git.rb +41 -17
  21. data/lib/hobo/lib/host_check/ruby.rb +30 -20
  22. data/lib/hobo/lib/host_check/vagrant.rb +37 -6
  23. data/lib/hobo/lib/s3sync.rb +22 -44
  24. data/lib/hobo/lib/seed/project.rb +10 -6
  25. data/lib/hobo/patches/slop.rb +21 -2
  26. data/lib/hobo/tasks/assets.rb +12 -15
  27. data/lib/hobo/tasks/config.rb +15 -0
  28. data/lib/hobo/tasks/deps.rb +37 -6
  29. data/lib/hobo/tasks/system.rb +15 -0
  30. data/lib/hobo/tasks/system/completions.rb +76 -0
  31. data/lib/hobo/tasks/tools.rb +10 -6
  32. data/lib/hobo/tasks/vm.rb +64 -11
  33. data/lib/hobo/ui.rb +27 -10
  34. data/lib/hobo/util.rb +36 -2
  35. data/lib/hobo/version.rb +2 -2
  36. data/spec/hobo/asset_applicator_spec.rb +2 -2
  37. data/spec/hobo/cli_spec.rb +40 -24
  38. data/spec/hobo/config/file_spec.rb +1 -3
  39. data/spec/hobo/error_handlers/debug_spec.rb +39 -5
  40. data/spec/hobo/error_handlers/friendly_spec.rb +38 -21
  41. data/spec/hobo/help_formatter_spec.rb +3 -3
  42. data/spec/hobo/helpers/file_locator_spec.rb +2 -2
  43. data/spec/hobo/helpers/shell_spec.rb +2 -2
  44. data/spec/hobo/helpers/vm_command_spec.rb +54 -21
  45. data/spec/hobo/lib/s3sync_spec.rb +6 -3
  46. data/spec/hobo/lib/seed/project_spec.rb +2 -3
  47. data/spec/hobo/lib/seed/replacer_spec.rb +1 -2
  48. data/spec/hobo/lib/seed/seed_spec.rb +2 -3
  49. data/spec/hobo/logging_spec.rb +2 -2
  50. data/spec/hobo/metadata_spec.rb +2 -2
  51. data/spec/hobo/null_spec.rb +2 -2
  52. data/spec/hobo/paths_spec.rb +1 -2
  53. data/spec/hobo/ui_spec.rb +104 -20
  54. data/spec/hobo/util_spec.rb +75 -0
  55. data/spec/spec_helper.rb +1 -0
  56. metadata +55 -46
  57. data/lib/hobo/tasks/host.rb +0 -19
@@ -0,0 +1,15 @@
1
+ desc "Configure hobo"
2
+ task :config do
3
+ config = Hobo.user_config
4
+
5
+ # Not required at present
6
+ # config.full_name = Hobo.ui.ask("Full name", :default => config.full_name).to_s
7
+ # config.email = Hobo.ui.ask("Email", :default => config.email).to_s
8
+
9
+ config[:aws] ||= {}
10
+ config.aws.access_key_id = Hobo.ui.ask("AWS access key ID", :default => config.aws.access_key_id).to_s
11
+ config.aws.secret_access_key = Hobo.ui.ask("AWS secret access key", :default => config.aws.secret_access_key).to_s
12
+
13
+ Hobo::Config::File.save(Hobo.user_config_file, config)
14
+ File.chmod(0600, Hobo.user_config_file)
15
+ end
@@ -21,10 +21,30 @@ namespace :deps do
21
21
  Rake::Task["tools:composer"].invoke
22
22
  Hobo.ui.title "Installing composer dependencies"
23
23
  Dir.chdir Hobo.project_path do
24
- shell "php", File.join(Hobo.project_bin_path, 'composer.phar'), "install", "--ansi", realtime: true, indent: 2
24
+ ansi = Hobo.ui.supports_color? ? '--ansi' : ''
25
+ args = [ "php bin/composer.phar install #{ansi} --prefer-dist", { realtime: true, indent: 2 } ]
26
+ complete = false
27
+
28
+ check = Hobo::Lib::HostCheck.check(:filter => /php_present/)
29
+
30
+ if check["Php present"] == :ok
31
+ begin
32
+ shell *args
33
+ complete = true
34
+ rescue Hobo::ExternalCommandError
35
+ Hobo.ui.warning "Installing composer dependencies locally failed!"
36
+ end
37
+ end
38
+
39
+ if !complete
40
+ vm_shell *args
41
+ end
42
+
43
+ Hobo.ui.success "Composer dependencies installed"
25
44
  end
45
+
46
+ Hobo.ui.separator
26
47
  end
27
- Hobo.ui.separator
28
48
  end
29
49
 
30
50
  desc "Install vagrant plugins"
@@ -32,9 +52,11 @@ namespace :deps do
32
52
  plugins = shell "vagrant plugin list", :capture => true
33
53
  locate "*Vagrantfile" do
34
54
  File.read("Vagrantfile").split("\n").each do |line|
55
+ next if line.match /^\s*#/
35
56
  next unless line.match /Vagrant\.require_plugin (.*)/
36
57
  plugin = $1.gsub(/['"]*/, '')
37
58
  next if plugins.include? "#{plugin} "
59
+
38
60
  Hobo.ui.title "Installing vagrant plugin: #{plugin}"
39
61
  bundle_shell "vagrant", "plugin", "install", plugin, :realtime => true, :indent => 2
40
62
  Hobo.ui.separator
@@ -45,13 +67,22 @@ namespace :deps do
45
67
  desc "Install chef dependencies"
46
68
  task :chef => [ "deps:gems" ] do
47
69
  locate "*Cheffile" do
48
- Hobo.ui.title "Installing chef dependencies"
70
+ Hobo.ui.title "Installing chef dependencies via librarian"
49
71
  Bundler.with_clean_env do
50
- bundle_shell "librarian-chef", "install", "--verbose", realtime: true, indent: 2 do |line|
51
- line =~ /Installing.*</ ? line : nil
72
+ bundle_shell "librarian-chef", "install", "--verbose", :realtime => true, :indent => 2 do |line|
73
+ line =~ /Installing.*</ ? line.strip + "\n" : nil
52
74
  end
53
75
  end
54
76
  Hobo.ui.separator
55
77
  end
78
+
79
+ locate "*Berksfile" do
80
+ Hobo.ui.title "Installing chef dependencies via berkshelf"
81
+ Bundler.with_clean_env do
82
+ bundle_shell "berks", "install", :realtime => true, :indent => 2
83
+ bundle_shell "berks", "install", "--path", "cookbooks"
84
+ end
85
+ Hobo.ui.separator
86
+ end
56
87
  end
57
- end
88
+ end
@@ -0,0 +1,15 @@
1
+ desc "System configuration related commands"
2
+ namespace :system do
3
+
4
+ desc "Check system configuration for potential problems"
5
+ task :check do
6
+ Hobo::Lib::HostCheck.check.each do |k,v|
7
+ if v == :ok
8
+ Hobo.ui.success "#{k}: OK"
9
+ else
10
+ Hobo.ui.error "#{k}: FAILED\n"
11
+ Hobo.ui.warning v.advice.gsub(/^/, ' ')
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,76 @@
1
+ desc "System configuration related commands"
2
+ namespace :system do
3
+
4
+ desc "Shell completion related commands"
5
+ namespace :completions do
6
+
7
+ desc "Install shell completion helpers"
8
+ option '-f', '--fish', 'Install completions for FISH'
9
+ option '-b', '--bash', 'Install completions for Bash'
10
+ option '-z', '--zsh', 'Install completions for ZSH'
11
+ task "install" do |task|
12
+ if task.opts[:fish]
13
+ script = <<-EOF
14
+ function __hobo_completion -d "Create hobo completions"
15
+ set -l cache_dir "/tmp/fish_hobo_completion_cache"
16
+ mkdir -p $cache_dir
17
+ set -l hashed_pwd (ruby -r 'digest' -e 'puts Digest::MD5.hexdigest(`pwd`)')
18
+ set -l hobo_cache_file "$cache_dir/$hashed_pwd"
19
+
20
+ if not test -f "$hobo_cache_file"
21
+ hobo system completions fish > "$hobo_cache_file"
22
+ end
23
+
24
+ cat "$hobo_cache_file"
25
+ end
26
+
27
+ function __hobo_scope_test -d "Hobo scoped completion test"
28
+ set cmd (commandline -opc)
29
+ if [ "$cmd" = "$argv" ]
30
+ return 0
31
+ end
32
+ return 1
33
+ end
34
+
35
+ eval (__hobo_completion)
36
+ EOF
37
+ target = File.join(ENV['HOME'], '.config/fish/completions/hobo.fish')
38
+ FileUtils.mkdir_p(File.dirname(target))
39
+ File.write(target, script)
40
+ end
41
+
42
+ if task.opts[:bash]
43
+ raise "Bash completions not yet implemented"
44
+ end
45
+
46
+ if task.opts[:zsh]
47
+ raise "ZSH completions not yet implemented"
48
+ end
49
+ end
50
+
51
+ desc "Display FISH shell completion commands"
52
+ task :fish do
53
+ Hobo.cli.slop.options.each do |option|
54
+ short = option.short.nil? ? '' : "-s #{option.short}"
55
+ long = option.long.nil? ? '' : "-l #{option.long}"
56
+ arg = option.config[:argument] ? '' : '-x'
57
+ puts "complete #{arg} -c hobo #{short} #{long} --description '#{option.description}';"
58
+ end
59
+
60
+ map = Hobo.cli.help_formatter.command_map
61
+ map.each do |k, v|
62
+ next if v.description.nil? || v.description.empty?
63
+ k = k.split(':')
64
+ k.unshift 'hobo'
65
+ c = k.pop
66
+ puts "complete -x -c hobo -n '__hobo_scope_test #{k.join(' ')}' -a #{c} --description '#{v.description}';"
67
+ v.options.each do |option|
68
+ short = option.short.nil? ? '' : "-s #{option.short}"
69
+ long = option.long.nil? ? '' : "-l #{option.long}"
70
+ arg = option.config[:argument] ? '' : '-x'
71
+ puts "complete #{arg} -c hobo -n '__hobo_scope_test #{k.concat([c]).join(' ')}' #{short} #{long} --description '#{option.description}';"
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -1,13 +1,17 @@
1
+ desc "Tasks to retrieve common tools"
2
+ hidden
1
3
  namespace :tools do
4
+
5
+ desc "Fetch composer"
2
6
  task :composer do
3
7
  bin_file = File.join(Hobo.project_bin_path, "composer.phar")
4
8
  unless File.exists?(bin_file)
5
- Hobo.ui.success "Getting composer.phar"
9
+ Hobo.ui.success "Getting composer"
6
10
  FileUtils.mkdir_p File.dirname(bin_file)
7
- Dir.chdir File.dirname(bin_file) do
8
- shell "php", "-r", "eval('?>'.file_get_contents('https://getcomposer.org/installer'));", realtime: true, indent: 2
9
- end
10
- Hobo.ui.separator
11
+ vm_shell "cd bin && php -r \"readfile('https://getcomposer.org/installer');\" | php", :realtime => true, :indent => 2
12
+ else
13
+ Hobo.ui.success "Composer already available in bin/composer.phar"
11
14
  end
15
+ Hobo.ui.separator
12
16
  end
13
- end
17
+ end
data/lib/hobo/tasks/vm.rb CHANGED
@@ -7,14 +7,43 @@ namespace :vm do
7
7
  end
8
8
  end
9
9
 
10
+ def vagrant_exec *args
11
+ opts = { :realtime => true, :indent => 2 }
12
+ color = Hobo.ui.supports_color? ? '--color' : '--no-color'
13
+
14
+ if OS.windows?
15
+ opts[:env] = { 'VAGRANT_HOME' => windows_short(dir) } if ENV['HOME'].match(/\s+/) && !ENV['VAGRANT_HOME']
16
+ end
17
+
18
+ args.unshift 'vagrant'
19
+ args.push color
20
+ args.push opts
21
+
22
+ bundle_shell *args
23
+ end
24
+
25
+ def windows_short dir
26
+ segments = dir.gsub(/\\/, '/').split('/')
27
+ segments.map do |segment|
28
+ if segment.match /\s+/
29
+ # This may fail in some edge cases but better than naught
30
+ # See the following link for the correct solution
31
+ # http://stackoverflow.com/questions/10224572/convert-long-filename-to-short-filename-8-3
32
+ segment.upcase.gsub(/\s+/, '')[0...6] + '~1'
33
+ else
34
+ segment
35
+ end
36
+ end.join('/')
37
+ end
38
+
10
39
  desc "Start & provision VM"
11
- task :up => [ 'deps:chef', 'deps:composer', 'assets:download', 'vm:start', 'vm:provision', 'assets:apply' ]
40
+ task :up => [ 'deps:chef', 'assets:download', 'vm:start', 'vm:provision', 'deps:composer', 'assets:apply' ]
12
41
 
13
42
  desc "Stop VM"
14
43
  task :stop => [ "deps:gems" ] do
15
44
  vagrantfile do
16
45
  Hobo.ui.title "Stopping VM"
17
- bundle_shell "vagrant", "suspend", "--color", realtime: true, indent: 2
46
+ vagrant_exec 'suspend'
18
47
  Hobo.ui.separator
19
48
  end
20
49
  end
@@ -26,7 +55,7 @@ namespace :vm do
26
55
  task :destroy => [ "deps:gems" ] do
27
56
  vagrantfile do
28
57
  Hobo.ui.title "Destroying VM"
29
- bundle_shell "vagrant", "destroy", "--force", "--color", realtime: true, indent: 2
58
+ vagrant_exec 'destroy', '--force'
30
59
  Hobo.ui.separator
31
60
  end
32
61
  end
@@ -35,7 +64,7 @@ namespace :vm do
35
64
  task :start => [ "deps:gems", "deps:vagrant_plugins" ] do
36
65
  vagrantfile do
37
66
  Hobo.ui.title "Starting vagrant VM"
38
- bundle_shell "vagrant", "up", "--no-provision", "--color", realtime: true, indent: 2
67
+ vagrant_exec 'up', '--no-provision'
39
68
  Hobo.ui.separator
40
69
  end
41
70
  end
@@ -44,23 +73,47 @@ namespace :vm do
44
73
  task :provision => [ "deps:gems" ] do
45
74
  vagrantfile do
46
75
  Hobo.ui.title "Provisioning VM"
47
- bundle_shell "vagrant", "provision", "--color", realtime: true, indent: 2
76
+ vagrant_exec 'provision'
48
77
  Hobo.ui.separator
49
78
  end
50
79
  end
51
80
 
52
81
  desc "Open an SSH connection"
53
- task :ssh do
54
- exec vm_command
82
+ task :ssh do |task|
83
+ execute = task.opts[:_unparsed]
84
+ opts = { :psuedo_tty => STDIN.tty? }
85
+
86
+ Hobo.ui.success "Determining VM connection details..." if STDOUT.tty?
87
+ command = execute.empty? ? vm_command(nil, opts) : vm_command(execute, opts)
88
+ Hobo.logger.debug "vm:ssh: #{command}"
89
+
90
+ Hobo.ui.success "Connecting..." if STDOUT.tty?
91
+ exec command
55
92
  end
56
93
 
57
94
  desc "Open a MySQL cli connection"
58
- task :mysql do
59
- exec vm_mysql
95
+ option '-D=', '--db=', 'Database'
96
+ task :mysql do |task|
97
+ opts = { :psuedo_tty => STDIN.tty? }
98
+ opts[:db] = task.opts[:db] if task.opts[:db]
99
+
100
+ Hobo.ui.success "Determining VM connection details..." if STDOUT.tty?
101
+ command = vm_mysql(opts)
102
+ Hobo.logger.debug "vm:mysql: #{command}"
103
+
104
+ Hobo.ui.success "Connecting..." if STDOUT.tty?
105
+ exec command
60
106
  end
61
107
 
62
108
  desc "Open a Redis cli connection"
63
109
  task :redis do
64
- exec vm_command "redis-cli"
110
+ opts = { :psuedo_tty => STDIN.tty? }
111
+
112
+ Hobo.ui.success "Determining VM connection details..." if STDOUT.tty?
113
+ command = vm_command("redis-cli", opts)
114
+ Hobo.logger.debug "vm:redis: #{command}"
115
+
116
+ Hobo.ui.success "Connecting..." if STDOUT.tty?
117
+ exec command
65
118
  end
66
- end
119
+ end
data/lib/hobo/ui.rb CHANGED
@@ -6,6 +6,8 @@ module Hobo
6
6
  end
7
7
 
8
8
  class Ui
9
+ include Hobo::Logging
10
+
9
11
  attr_accessor :interactive
10
12
 
11
13
  COLORS = {
@@ -22,10 +24,12 @@ module Hobo
22
24
  :description => [:bold]
23
25
  }
24
26
 
25
- def initialize out = $stdout, error = $stderr
27
+ def initialize input = $stdin, output = $stdout, error = $stderr
26
28
  HighLine.color_scheme = HighLine::ColorScheme.new COLORS
27
- @out = ::HighLine.new $stdin, out
28
- @error = ::HighLine.new $stdin, error
29
+ @output_io = output
30
+ @out = ::HighLine.new input, output
31
+ @error = ::HighLine.new input, error
32
+ use_color supports_color?
29
33
  end
30
34
 
31
35
  def color_scheme scheme = nil
@@ -33,15 +37,25 @@ module Hobo
33
37
  HighLine.color_scheme
34
38
  end
35
39
 
40
+ def supports_color?
41
+ return @output_io.tty? unless OS.windows?
42
+ return (ENV['ANSICON'] || ENV['TERM'] == 'xterm') && @output_io.tty? # ANSICON or MinTTY && output is TTY
43
+ end
44
+
36
45
  def use_color opt = nil
37
46
  HighLine.use_color = opt unless opt.nil?
38
47
  HighLine.use_color?
39
48
  end
40
49
 
41
50
  def ask question, opts = {}
42
- unless Hobo.ui.interactive
43
- raise Hobo::NonInteractive.new(question) if opts[:default].nil?
44
- return opts[:default]
51
+ opts = {
52
+ :validate => nil,
53
+ :default => nil
54
+ }.merge(opts)
55
+
56
+ unless @interactive
57
+ raise Hobo::NonInteractiveError.new(question) if opts[:default].nil?
58
+ return opts[:default].to_s
45
59
  end
46
60
 
47
61
  question = "#{question} [#{opts[:default]}]" if opts[:default]
@@ -51,7 +65,8 @@ module Hobo
51
65
  q.validate = opts[:validate] if opts[:validate]
52
66
  q.readline
53
67
  end
54
- answer.strip.empty? ? opts[:default] : answer.strip
68
+ answer = answer.to_s
69
+ answer.strip.empty? ? opts[:default].to_s : answer.strip
55
70
  rescue EOFError
56
71
  Hobo.ui.info ""
57
72
  ""
@@ -65,7 +80,7 @@ module Hobo
65
80
  end
66
81
 
67
82
  def separator
68
- info ""
83
+ info(supports_color? ? "" : "\n")
69
84
  end
70
85
 
71
86
  def color *args
@@ -100,7 +115,9 @@ module Hobo
100
115
 
101
116
  def say channel, message, color
102
117
  return if message.nil?
103
- channel.say(color ? channel.color(message, color) : message)
118
+ message = color ? channel.color(message, color) : message
119
+ channel.say(message) unless logger.level <= Logger::DEBUG
120
+ logger.debug(message)
104
121
  end
105
122
  end
106
- end
123
+ end
data/lib/hobo/util.rb CHANGED
@@ -1,7 +1,41 @@
1
+ require 'ruby-progressbar'
2
+
1
3
  module Hobo
2
4
  class << self
5
+
6
+ attr_accessor :project_bar_cache
7
+
3
8
  def in_project?
4
- !Hobo.project_path.nil?
9
+ !!Hobo.project_path
10
+ end
11
+
12
+ def progress file, increment, total, type, opts = {}
13
+ opts = {
14
+ :title => File.basename(file),
15
+ :total => total,
16
+ :format => "%t [%B] %p%% %e"
17
+ }.merge(opts)
18
+
19
+ # Hack to stop newline spam on windows
20
+ opts[:length] = 79 if Gem::win_platform?
21
+
22
+ @progress_bar_cache ||= {}
23
+
24
+ if type == :reset
25
+ type = :update
26
+ @progress_bar_cache.delete file
27
+ end
28
+
29
+ @progress_bar_cache[file] ||= ProgressBar.create(opts)
30
+
31
+ case type
32
+ when :update
33
+ @progress_bar_cache[file].progress += increment
34
+ when :finished
35
+ @progress_bar_cache[file].finish
36
+ end
37
+
38
+ return @progress_bar_cache[file]
5
39
  end
6
40
  end
7
- end
41
+ end