engineyard-local 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
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