engineyard-local 0.2.1

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 (70) hide show
  1. data/.gitignore +23 -0
  2. data/Gemfile +15 -0
  3. data/Gemfile.lock +62 -0
  4. data/README.md +115 -0
  5. data/Rakefile +15 -0
  6. data/bin/ey-local +4 -0
  7. data/config/dna.json +206 -0
  8. data/config/locales/en.yml +57 -0
  9. data/config/settings.yml +18 -0
  10. data/config/solo.rb +7 -0
  11. data/engineyard-local.gemspec +24 -0
  12. data/install/deb/README.md +72 -0
  13. data/install/deb/Rakefile +157 -0
  14. data/install/deb/Vagrantfile +10 -0
  15. data/install/deb/install.sh +32 -0
  16. data/install/osx/README.md +23 -0
  17. data/install/osx/Rakefile +39 -0
  18. data/install/osx/engineyard-local/engineyard-local.pkgproj +812 -0
  19. data/install/osx/images/eylocal_installer.png +0 -0
  20. data/install/osx/scripts/log.sh +3 -0
  21. data/install/osx/scripts/postinstall +57 -0
  22. data/install/osx/scripts/rvm_install.sh +34 -0
  23. data/lib/engineyard-local.rb +42 -0
  24. data/lib/engineyard-local/command.rb +65 -0
  25. data/lib/engineyard-local/command/base.rb +15 -0
  26. data/lib/engineyard-local/command/exec.rb +11 -0
  27. data/lib/engineyard-local/command/group.rb +86 -0
  28. data/lib/engineyard-local/command/helpers.rb +23 -0
  29. data/lib/engineyard-local/command/list.rb +29 -0
  30. data/lib/engineyard-local/command/rails.rb +19 -0
  31. data/lib/engineyard-local/command/up.rb +87 -0
  32. data/lib/engineyard-local/command/vagrant_action.rb +11 -0
  33. data/lib/engineyard-local/errors.rb +10 -0
  34. data/lib/engineyard-local/middleware.rb +28 -0
  35. data/lib/engineyard-local/middleware/bundle.rb +40 -0
  36. data/lib/engineyard-local/middleware/chef.rb +44 -0
  37. data/lib/engineyard-local/middleware/default_provisioner.rb +34 -0
  38. data/lib/engineyard-local/middleware/dna.rb +80 -0
  39. data/lib/engineyard-local/middleware/exec.rb +27 -0
  40. data/lib/engineyard-local/middleware/helpers.rb +4 -0
  41. data/lib/engineyard-local/middleware/helpers/executable.rb +27 -0
  42. data/lib/engineyard-local/middleware/helpers/network.rb +20 -0
  43. data/lib/engineyard-local/middleware/helpers/rvm.rb +37 -0
  44. data/lib/engineyard-local/middleware/helpers/uploadable.rb +14 -0
  45. data/lib/engineyard-local/middleware/network.rb +64 -0
  46. data/lib/engineyard-local/middleware/rails.rb +3 -0
  47. data/lib/engineyard-local/middleware/rails/command.rb +31 -0
  48. data/lib/engineyard-local/middleware/rails/db.rb +36 -0
  49. data/lib/engineyard-local/middleware/rails/install.rb +36 -0
  50. data/lib/engineyard-local/middleware/rails/new.rb +31 -0
  51. data/lib/engineyard-local/middleware/tag.rb +33 -0
  52. data/lib/engineyard-local/ui.rb +33 -0
  53. data/lib/engineyard-local/version.rb +5 -0
  54. data/lib/engineyard-local/virtualbox.rb +35 -0
  55. data/lib/vagrant_init.rb +1 -0
  56. data/test/engineyard-local/command/group_test.rb +34 -0
  57. data/test/engineyard-local/command/up_test.rb +70 -0
  58. data/test/engineyard-local/command_test.rb +40 -0
  59. data/test/engineyard-local/middelware/bundle_test.rb +32 -0
  60. data/test/engineyard-local/middelware/default_provisioner_test.rb +35 -0
  61. data/test/engineyard-local/middelware/exec_test.rb +19 -0
  62. data/test/engineyard-local/middelware/network_test.rb +94 -0
  63. data/test/engineyard-local/middelware/rails/command_test.rb +24 -0
  64. data/test/engineyard-local/middelware/rails/db_test.rb +23 -0
  65. data/test/engineyard-local/middelware/rails/install_test.rb +24 -0
  66. data/test/engineyard-local/ui_test.rb +22 -0
  67. data/test/engineyard-local/virtualbox_test.rb +34 -0
  68. data/test/integration/up_test.rb +28 -0
  69. data/test/test_helper.rb +78 -0
  70. metadata +178 -0
@@ -0,0 +1,3 @@
1
+ function log {
2
+ syslog -s -l notice "ey-local: $1"
3
+ }
@@ -0,0 +1,57 @@
1
+ #!/bin/bash
2
+
3
+ # pull in our logging
4
+ source log.sh
5
+
6
+ # the assumed install directory for the package. This should be provided
7
+ # as a setting from the ruby project by including a settings text file
8
+ # in the installation package
9
+ install_dir="/tmp/engineyard-local-installer"
10
+
11
+ # TODO take the set and loop over it to run the install for each
12
+ # logged in user
13
+ current_user=`users | tail -1`
14
+
15
+ # it would be nice to tie the directory to some variable
16
+ # determined by the installer
17
+ gems=`ls $install_dir/*.gem | xargs`
18
+
19
+ # the name of the base box to be created, again would be nice
20
+ # to include an installer file with these settings
21
+ box_name="ey-gentoo-rack"
22
+
23
+ # run the current command with a login shell as the current logged in user
24
+ function as_current_user {
25
+ su $current_user -l -c "$1"
26
+ }
27
+
28
+ # run the post install scripts as the logged in user
29
+ # --login is required to make sure that rvm is available when
30
+ # installed and added to .bash_profile
31
+ #
32
+ # If they aren't though RVM starts into an infinite
33
+ # loop because while the binary is present the scripts
34
+ # directory isn't available in $HOME which may be /var/root
35
+ # if run as `sudo -u $current_user`. That is, it thinks
36
+ # there's no user install and then attempts to find the
37
+ # root install despite the fact that its running the user install
38
+ # script. After not finding one it proceeds to
39
+ # execute the same command again and again.
40
+ as_current_user "./rvm_install.sh $gems"
41
+
42
+ # if rvm_install fails install to the system gems
43
+ if [[ $? -gt 0 ]]; then
44
+ log "Installing gems to system ruby ..."
45
+ sudo gem install $gems
46
+ fi
47
+
48
+ log "Gem install complete"
49
+ as_current_user "ey-local box list | grep $box_name"
50
+
51
+ # install the packaged box for use with ey-local up
52
+ if [[ $? -gt 0 ]]; then
53
+ log "Installing default box $box_name ..."
54
+ as_current_user "ey-local box add $box_name $install_dir/package.box"
55
+ else
56
+ log "$box_name already installed ..."
57
+ fi
@@ -0,0 +1,34 @@
1
+ # if rvm is not installed exit with an error to signal
2
+ # parent script that it needs to take action accordingly
3
+ if [[ ! `which rvm` ]]; then
4
+ exit 1;
5
+ fi
6
+
7
+ # pull in our syslog loggerGH
8
+ source log.sh
9
+
10
+ # rvm has a habit of making its output nigh unparsable.
11
+ # Here we have to strip the possible default ruby notation
12
+ # of `=>` incase it's used so that our results are consistent
13
+ # and can be run through awk to pull out the ruby
14
+ #
15
+ # possible `rvm list` output handled here:
16
+ # => ruby-version-patch
17
+ # ruby-version-patch
18
+ default_ruby=`rvm list default | sed 's/=>/ /' | grep '^ ' | awk '{print \$1}'`
19
+ current_ruby=`rvm current`
20
+
21
+ # if the user has a default or current ruby install to one or the other
22
+ # otherwise we can't know where it should be installed for rvm
23
+ if [[ $default_ruby ]]; then
24
+ log "Installing gems to the default ruby: $default_ruby@global ..."
25
+ rvm use $default_ruby@global
26
+ gem install $@ --no-ri --no-rdoc
27
+ elif [[ $current_ruby ]]; then
28
+ log "Installing gems to the current ruby: $current_ruby@global ..."
29
+ rvm use $current_ruby@global
30
+ gem install $@ --no-ri --no-rdoc
31
+ else
32
+ log "No rvm default or current ruby detected ..."
33
+ exit 1
34
+ fi
@@ -0,0 +1,42 @@
1
+ require "vagrant"
2
+ require "pathname"
3
+ require "yaml"
4
+
5
+ # TODO settings object/management will be needed shortly
6
+ module Engineyard
7
+ module Local
8
+ def self.project_root
9
+ @project_root ||= Pathname.new(File.expand_path('../../', __FILE__))
10
+ end
11
+
12
+ def self.project_file(path)
13
+ self.project_root + path
14
+ end
15
+
16
+ def self.config
17
+ @config ||= load_config_yaml("settings.yml")
18
+ end
19
+
20
+ # default to en until something more inteligent is required
21
+ # NOTE all locale information is contained in a single yaml
22
+ # file in anticipation of relatively minimal use
23
+ def self.locales
24
+ @locales ||= load_config_yaml("locales/en.yml")
25
+ end
26
+
27
+ def self.load_config_yaml(config_rel_path)
28
+ yaml_file = File.expand_path("config/#{config_rel_path}", self.project_root)
29
+ YAML.load_file(yaml_file)
30
+ end
31
+ end
32
+ end
33
+
34
+ require "engineyard-local/virtualbox"
35
+ require "engineyard-local/middleware/helpers"
36
+ require "engineyard-local/middleware"
37
+ require "engineyard-local/ui"
38
+ require "engineyard-local/version"
39
+ require "engineyard-local/command"
40
+ require "engineyard-local/errors"
41
+
42
+ I18n.load_path << Engineyard::Local.project_file("config/locales/en.yml")
@@ -0,0 +1,65 @@
1
+ module Engineyard
2
+ module Local
3
+ module Command
4
+ def self.all
5
+ Engineyard::Local.locales[:commands].keys.map { |cmd| cmd.to_s }
6
+ end
7
+
8
+ def self.passthrough
9
+ Engineyard::Local.config[:commands][:passthrough]
10
+ end
11
+
12
+ def self.dispatch(args)
13
+ Group.env = env = vagrant_env(args)
14
+
15
+ # if the flags need to be sent through on the command, avoid Thor
16
+ # otherwise start up Thor command line handling. Otherwise notify wrapper
17
+ # that nothing was dispatched.
18
+ if args.include?("-v") || args.include?("--version")
19
+ env.ui.info Engineyard::Local::VERSION, :prefix => false
20
+ elsif passthrough.include?(args.first)
21
+ cmd = Group.new(args, [], {})
22
+ cmd.send(args.first.to_sym, *args[1, args.length])
23
+ elsif all.include?(args.first) || args.length == 0
24
+ Group.start(args)
25
+ else
26
+ vagrant_env(args).cli(args)
27
+ end
28
+ rescue Vagrant::Errors::VagrantError => e
29
+ # TODO move to Vagrant Environment ui error
30
+ env.ui.error e.message if e.message
31
+ exit e.status_code if e.respond_to?(:status_code)
32
+ exit 999
33
+ end
34
+
35
+ def self.vagrant_env(args)
36
+ opts = {}
37
+
38
+ # setup the vagrant env properly for the commands to run
39
+ if args.include?("--no-color") || !$stdout.tty? || !Vagrant::Util::Platform.terminal_supports_colors?
40
+ # Delete the argument from the list so that it doesn't cause any
41
+ # invalid arguments down the road.
42
+ args.delete("--no-color")
43
+ opts[:ui_class] = UI::Basic
44
+ else
45
+ opts[:ui_class] = UI::Colored
46
+ end
47
+
48
+ new_env = Vagrant::Environment.new(opts)
49
+ new_env.load!
50
+ new_env
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ require "thor"
57
+ # TODO autoload
58
+ require "engineyard-local/command/helpers"
59
+ require "engineyard-local/command/base"
60
+ require "engineyard-local/command/group"
61
+ require "engineyard-local/command/vagrant_action"
62
+ require "engineyard-local/command/exec"
63
+ require "engineyard-local/command/list"
64
+ require "engineyard-local/command/rails"
65
+ require "engineyard-local/command/up"
@@ -0,0 +1,15 @@
1
+ module Engineyard
2
+ module Local
3
+ module Command
4
+ class Base < Vagrant::Command::Base
5
+ include Command::Helpers
6
+
7
+ attr_reader :env, :options
8
+
9
+ def initialize(env, options)
10
+ @env, @options = env, options
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,11 @@
1
+ module Engineyard
2
+ module Local
3
+ module Command
4
+ class Exec < Base
5
+ def exec(command_args)
6
+ run(Middleware::Exec, "eylocal.exec.command_args" => command_args)
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,86 @@
1
+ module Engineyard
2
+ module Local
3
+ module Command
4
+ # TODO move to purely vagrant command based setup
5
+ class Group < Thor
6
+ # TODO this class level env crap will go away once
7
+ # these commands are moved out of thor to Vagrant commands
8
+ def self.env=(env)
9
+ @@env = env
10
+ end
11
+
12
+ no_tasks do
13
+ def env
14
+ @@env
15
+ end
16
+ end
17
+
18
+ # NOTE this is generally a bad idea as it might break between Vagrant versions
19
+ # the alternate is to monkey with the output (we're attempting to own the ux)
20
+ # from Thor where ey-local remains a Vagrant plugin. Either way the library
21
+ # is reaching into deps and using their internals, Vagrant is preferred here
22
+ # because the author has more experience with said internals
23
+ # TODO clean up the vagrant command environment init
24
+ def initialize(*args)
25
+ super
26
+ end
27
+
28
+ def self.command_info
29
+ Local.locales[:commands]
30
+ end
31
+
32
+ # register the command group eylocal
33
+ # register(*command_info[:eylocal])
34
+
35
+ # make sure rails is installed, run rails commands in the guest project share
36
+ method_option "version", :type => :string, :default => nil
37
+ desc(*command_info[:rails])
38
+ def rails(*args)
39
+ Command::Rails.new(env, options).exec(*args)
40
+ end
41
+
42
+ desc(*command_info[:exec])
43
+ def exec(*args)
44
+ Command::Exec.new(env, options).exec(args)
45
+ end
46
+
47
+ # streamlining of Vagrant up
48
+ method_option "no-bundle", :type => :boolean, :default => nil
49
+ method_option "no-db-setup", :type => :boolean, :default => nil
50
+ method_option "silent", :type => :boolean, :default => nil
51
+ desc(*command_info[:up])
52
+ def up(*args)
53
+ Command::Up.new(env, options).exec(*args)
54
+ end
55
+
56
+ method_option "environment", :type => :string, :default => "development"
57
+ method_option "lines", :type => :numeric, :default => 100
58
+ desc(*command_info[:log])
59
+ def log(*args)
60
+ cmd_args = ["tail -#{options["lines"]} log/#{options["environment"]}.log"]
61
+ Command::Exec.new(env, options).exec(cmd_args)
62
+ end
63
+
64
+ method_option "format", :type => :string, :default => "short"
65
+ desc(*command_info[:list])
66
+ def list
67
+ if options["format"] && !["short", "full"].include?(options["format"])
68
+ help("list")
69
+ else
70
+ Command::List.new(env, options).exec(options)
71
+ end
72
+ end
73
+
74
+ desc(*command_info[:start])
75
+ def start
76
+ Command::VagrantAction.new(env, options).exec(:resume)
77
+ end
78
+
79
+ desc(*command_info[:stop])
80
+ def stop
81
+ Command::VagrantAction.new(env, options).exec(:suspend)
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,23 @@
1
+ module Engineyard
2
+ module Local
3
+ module Command
4
+ module Helpers
5
+ def run(middleware, opts={}, &block)
6
+ with_target_vms do |vm|
7
+ opts = merge_run_options(vm, opts)
8
+ vm.env.action_runner.run(middleware, opts)
9
+ end
10
+ end
11
+
12
+ # TODO borrowed entirely from vagrant, running outside it's command
13
+ # structure is causing issues that need remedy
14
+ def merge_run_options(vm, opts={})
15
+ {
16
+ :vm => vm,
17
+ :ui => vm.env.ui.dup
18
+ }.merge(opts || {})
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,29 @@
1
+ module Engineyard
2
+ module Local
3
+ module Command
4
+ class List < Base
5
+ def exec(options)
6
+ Virtualbox.uuid_map.each do |name, uuid|
7
+ project_root = Virtualbox.extra_data(uuid, Local.config[:managed_vm_key])
8
+
9
+ if project_root
10
+ # move the uuid and project root to the front of the output
11
+ # for easier cutting since it's less likely to have spaces
12
+ env.ui.info format(uuid, project_root, name), :prefix => false
13
+ end
14
+ end
15
+ end
16
+
17
+ def format(uuid, project_root, name)
18
+ result = "#{uuid} #{project_root}"
19
+
20
+ if @options[:format] == "full"
21
+ "#{result} #{name}"
22
+ else
23
+ result
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,19 @@
1
+ module Engineyard
2
+ module Local
3
+ module Command
4
+ class Rails < Base
5
+ def exec(*command_args)
6
+ scoped_options = options
7
+
8
+ stack = Vagrant::Action::Builder.new do
9
+ use Middleware::Rails::Install, "eylocal.rails.version" => scoped_options["version"]
10
+ use Middleware::Rails::Command, "eylocal.rails.command_args" => command_args
11
+ end
12
+
13
+ run stack
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+
@@ -0,0 +1,87 @@
1
+ module Engineyard
2
+ module Local
3
+ module Command
4
+ class Up < Base
5
+ def box_defaults
6
+ Local.config[:box_defaults]
7
+ end
8
+
9
+ def box_exists?(name)
10
+ env.boxes.map { |box| box.name }.include?(name)
11
+ end
12
+
13
+ # convention based streamlining of Vagrant's up
14
+ def exec(name=box_defaults[:name], uri=box_uri)
15
+ if box_exists?(name)
16
+ env.ui.warn(I18n.t("eylocal.up.box_exists", :name => name))
17
+ else
18
+ env.cli("box", "add", name, uri)
19
+ end
20
+
21
+ # if a Vagrant file does NOT exist create one
22
+ if env.root_path.nil?
23
+ env.cli("init", name)
24
+ end
25
+
26
+ # resets vagrant root path so that it can detect the
27
+ # newly initialized Vagrantfile, and the newly added box
28
+ # TODO submit alternate reset of root path to Vagrant
29
+ env.send(:remove_instance_variable, :@root_path)
30
+ env.load_config!
31
+ env.boxes.reload!
32
+
33
+ env.ui.info(I18n.t("eylocal.up.root_path", :root_path => env.root_path))
34
+ if File.expand_path(env.root_path) != File.expand_path(Dir.pwd)
35
+ env.ui.info(I18n.t("eylocal.up.root_path_instructions", :root_path => env.root_path, :pwd => Dir.pwd))
36
+ end
37
+
38
+ # don't build a box if its already built
39
+ with_target_vms do |vm|
40
+ if vm.created?
41
+ env.ui.info I18n.t("vagrant.commands.up.vm_created")
42
+ else
43
+ up = Vagrant.actions.get(:up)
44
+
45
+ # insert the tag before the box is in a state where it can't be saved eg running
46
+ up.insert_before(Vagrant::Action::VM::CheckGuestAdditions, Middleware::Tag)
47
+ up.insert_before(Vagrant::Action::VM::CheckGuestAdditions, Middleware::Network, @options)
48
+
49
+ opts = merge_run_options(vm)
50
+ vm.env.action_runner.run(up, opts)
51
+ end
52
+ end
53
+
54
+ # finish the box setup
55
+ run setup_stack(options)
56
+ end
57
+
58
+ private
59
+
60
+ # prefer the the base box included with the installer if it exists
61
+ # otherwise use the default downloadable box
62
+ def box_uri
63
+ default_path = Engineyard::Local.project_root + "default.box"
64
+
65
+ if File.exists?(default_path)
66
+ # to_s required here as the path will be scanned for http
67
+ # by Vagrant
68
+ default_path.to_s
69
+ else
70
+ box_defaults[:uri]
71
+ end
72
+ end
73
+
74
+ # install the application bundle and create/migrate the database
75
+ # TODO check for the database.yml and fail gracefully
76
+ def setup_stack(options)
77
+ Vagrant::Action::Builder.new do
78
+ use Middleware::DNA unless options["no-dna"]
79
+ use Middleware::Chef unless options["no-chef"]
80
+ use Middleware::Bundle unless options["no-bundle"]
81
+ use Middleware::Rails::DB unless options["no-db-setup"]
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end