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
+ require "engineyard-local/middleware/rails/db"
2
+ require "engineyard-local/middleware/rails/command"
3
+ require "engineyard-local/middleware/rails/install"
@@ -0,0 +1,31 @@
1
+ module Engineyard
2
+ module Local
3
+ module Middleware
4
+ module Rails
5
+ class Command
6
+ include Middleware::Helpers::Rvm
7
+ include Middleware::Helpers::Executable
8
+
9
+ def initialize(app, env)
10
+ @app, @env = app, env
11
+ end
12
+
13
+ def call(env)
14
+ ssh_exec!(env, commands)
15
+ @app.call(env)
16
+ end
17
+
18
+ def commands
19
+ rvm_env +
20
+ [ "cd #{project_dir}",
21
+ "rails #{command_args}" ]
22
+ end
23
+
24
+ def command_args
25
+ @env["eylocal.rails.command_args"].join(" ")
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,36 @@
1
+ module Engineyard
2
+ module Local
3
+ module Middleware
4
+ module Rails
5
+ class DB
6
+ include Middleware::Helpers::Rvm
7
+ include Middleware::Helpers::Executable
8
+
9
+ def initialize(app, env)
10
+ @app = app
11
+ @env = env
12
+ end
13
+
14
+ def call(env)
15
+ @env[:ui].info I18n.t("eylocal.setup.rails.db")
16
+ ssh_exec!(env, commands)
17
+ @app.call(env)
18
+ end
19
+
20
+ def commands
21
+ rvm_env +
22
+ [ "cd #{project_dir}",
23
+ if_task_exists("db:create"),
24
+ if_task_exists("db:migrate") ]
25
+ end
26
+
27
+ # if there's a Rakefile, and rake -T contains the task we're looking for
28
+ # execute the task
29
+ def if_task_exists(task)
30
+ "if [[ `rake -T > /dev/null 2>&1 && rake -T | grep -e '#{task}'` ]]; then rake #{task}; fi"
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,36 @@
1
+ module Engineyard
2
+ module Local
3
+ module Middleware
4
+ module Rails
5
+ class Install
6
+ include Middleware::Helpers::Rvm
7
+ include Middleware::Helpers::Executable
8
+
9
+ def initialize(app, env)
10
+ @app, @env = app, env
11
+ end
12
+
13
+ def call(env)
14
+ ssh_exec!(env, commands)
15
+ @app.call(env)
16
+ end
17
+
18
+ def commands
19
+ rvm_env +
20
+ [ unless_rails("gem install rails #{install_opts}") ]
21
+ end
22
+
23
+ def install_opts
24
+ if @env["eylocal.rails.version"]
25
+ "--version=#{@env["eylocal.rails.version"]}"
26
+ end
27
+ end
28
+
29
+ def unless_rails(cmd)
30
+ "gem list rails | grep rails; if [[ $? -gt 0 ]]; then sudo #{cmd}; fi"
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,31 @@
1
+ module Engineyard
2
+ module Local
3
+ module Middleware
4
+ module Rails
5
+ class New
6
+ include Middleware::Helpers::Rvm
7
+ include Middleware::Helpers::Executable
8
+
9
+ def initialize(app, env, opts)
10
+ @app, @env, @opts = app, env, opts
11
+ end
12
+
13
+ def call(env)
14
+ ssh_exec!(env, commands)
15
+ @app.call(env)
16
+ end
17
+
18
+ def commands
19
+ rvm_env +
20
+ [ "cd #{project_dir}",
21
+ "rails #{command_args}" ]
22
+ end
23
+
24
+ def command_args
25
+ @opts["eylocal.rails.command_args"].join(" ")
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,33 @@
1
+ require 'digest/sha1'
2
+
3
+ module Engineyard
4
+ module Local
5
+ module Middleware
6
+ class Tag
7
+ include Helpers::Network
8
+
9
+ def initialize(app, env)
10
+ @app, @env = app, env
11
+ end
12
+
13
+ def call(env)
14
+ @env[:ui].info I18n.t("eylocal.tag")
15
+ tag_vm(env)
16
+ @app.call(env)
17
+ end
18
+
19
+ def tag_vm(env)
20
+ value = env[:root_path].to_s
21
+
22
+ # mark the vm as ey-local for listing
23
+ set_extra_data(env, Local.config[:managed_vm_key], value)
24
+ set_extra_data(env, Local.config[:network_ip_key], proposed_ip)
25
+ end
26
+
27
+ def set_extra_data(env, key, value)
28
+ env[:vm].driver.execute("setextradata", env[:vm].uuid, key, value)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,33 @@
1
+ module Engineyard
2
+ module Local
3
+ module UI
4
+ module Common
5
+ def ey_localize(message)
6
+ # TODO this is likely to be insufficient but it's a start
7
+ # toward making sure the ui is consistent for the user
8
+ message.gsub(/([Aa]) (`)?[Vv]agrant /, '\1n \2ey-local ').gsub(/[Vv]agrant /, 'ey-local ')
9
+ end
10
+
11
+ def say(type, message, opts=nil)
12
+ super(type, ey_localize(message), opts)
13
+ end
14
+ end
15
+
16
+ class Basic < Vagrant::UI::Basic
17
+ include Common
18
+
19
+ def initialize(resource)
20
+ super(Local.config[:commands][:prefix])
21
+ end
22
+ end
23
+
24
+ class Colored < Vagrant::UI::Colored
25
+ include Common
26
+
27
+ def initialize(resource)
28
+ super(Local.config[:commands][:prefix])
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,5 @@
1
+ module Engineyard
2
+ module Local
3
+ VERSION = "0.2.1"
4
+ end
5
+ end
@@ -0,0 +1,35 @@
1
+ module Engineyard
2
+ module Local
3
+ class Virtualbox
4
+ VALUE_PREFIX = "Value: "
5
+ # TODO this is exceptionally difficult to read
6
+ INFO_REGEX = /"(.*)".*\{(.*)\}/
7
+
8
+ def self.uuid_map
9
+ # TODO ~~~ is fragile
10
+ # extract the uuids from `VBoxMange list vms`, sample output:
11
+ # "Bar VM" {c21b5de6-5867-4471-ab53-7af23badc5eb}
12
+ # "Foo VM" {aaba8c3a-3521-46e2-bd2c-fe7e65b77524}
13
+ info_list = vbox.execute("list", "vms").gsub(INFO_REGEX, '\1~~~\2').split("\n")
14
+
15
+ info_list.inject({}) do |acc, info|
16
+ name, uuid = info.split("~~~")
17
+ acc[name] = uuid
18
+ acc
19
+ end
20
+ end
21
+
22
+ def self.extra_data(uuid, key = "enumerate" )
23
+ value = vbox.execute("getextradata", uuid, key).strip
24
+
25
+ if value.include?(VALUE_PREFIX)
26
+ value.gsub!(/#{VALUE_PREFIX}/, '')
27
+ end
28
+ end
29
+
30
+ def self.vbox
31
+ @@vbox ||= Vagrant::Driver::VirtualBox.new
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1 @@
1
+ require "engineyard-local"
@@ -0,0 +1,34 @@
1
+ require "test_helper"
2
+
3
+ class CommandGroupTest < Test::Unit::TestCase
4
+ include Vagrant::TestHelpers
5
+
6
+ context "log" do
7
+ setup do
8
+ @cmd = Engineyard::Local::Command::Group.new([], {}, {:env => @env})
9
+ @klass = Engineyard::Local::Command::Group
10
+ @app, @env = action_env
11
+ @klass.env = @env
12
+ @cmd.stubs(:options).returns({"lines" => 100, "environment" => "development"})
13
+ end
14
+
15
+ should "exec tail with flagged lines" do
16
+ Engineyard::Local::Command::Exec
17
+ .any_instance.expects(:run)
18
+ .with(Engineyard::Local::Middleware::Exec, { "eylocal.exec.command_args" => ["tail -10 log/development.log"]})
19
+
20
+
21
+ @cmd.expects(:options).twice.returns({"lines" => 10, "environment" => "development"})
22
+ @cmd.log()
23
+ end
24
+
25
+ should "exec tail with flagged environment" do
26
+ Engineyard::Local::Command::Exec
27
+ .any_instance.expects(:run)
28
+ .with(Engineyard::Local::Middleware::Exec, { "eylocal.exec.command_args" => ["tail -100 log/foo.log"]})
29
+
30
+ @cmd.expects(:options).twice.returns({"lines" => 100, "environment" => "foo"})
31
+ @cmd.log()
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,70 @@
1
+ require "test_helper"
2
+
3
+ class CommandUpTest < Test::Unit::TestCase
4
+ include Vagrant::TestHelpers
5
+
6
+ context "up" do
7
+ setup do
8
+ @klass = Engineyard::Local::Command::Up
9
+ @config = Engineyard::Local.config
10
+ @env = vagrant_env
11
+
12
+ # TODO this is clearly bad, using env.cli in the commands
13
+ # makes it hard to mock/expect
14
+ @cmd = Engineyard::Local::Command::Group.new([], {}, {:env => @env})
15
+
16
+ # prevent the bundle middleware from executing
17
+ @klass.any_instance.stubs(:with_target_vms).returns([])
18
+ @klass.any_instance.stubs(:env).returns(@env)
19
+
20
+ @env.stubs(:cli)
21
+ @env.stubs(:root_path).returns(nil)
22
+ end
23
+
24
+ should "add a box with config default params when invoked" do
25
+ default_name = @config[:box_defaults][:name]
26
+ default_uri = @config[:box_defaults][:uri]
27
+
28
+ @env.expects(:cli).with("box", "add", default_name, default_uri)
29
+ @env.expects(:cli).with("init", default_name)
30
+ @cmd.up
31
+ end
32
+
33
+ should "add a box with passed params when invoked" do
34
+ name = "foo"
35
+ uri = "http://foo.com"
36
+
37
+ @env.expects(:cli).with("box", "add", name, uri)
38
+ @env.expects(:cli).with("init", name)
39
+ @cmd.up(name, uri)
40
+ end
41
+
42
+ should "default to the installed box when its preset" do
43
+ default_name = @config[:box_defaults][:name]
44
+
45
+ Engineyard::Local.expects(:project_root).returns("/foo/")
46
+ File.expects(:exists?).with("/foo/default.box").returns(true)
47
+
48
+ @env.expects(:cli).with("box", "add", default_name, "/foo/default.box")
49
+ @env.expects(:cli).with("init", default_name)
50
+ @cmd.up
51
+ end
52
+
53
+ context "bundling" do
54
+ setup do
55
+ @env.stubs(:cli)
56
+ Vagrant::Action::Builder.any_instance.stubs(:use)
57
+ end
58
+
59
+ should "skip bundle when --no-bundle is included on the cli" do
60
+ Vagrant::Action::Builder.any_instance.expects(:use).with(Engineyard::Local::Middleware::Bundle).never
61
+ @cmd.up("--no-bundle")
62
+ end
63
+
64
+ should "run bundle by default" do
65
+ Vagrant::Action::Builder.any_instance.expects(:use).with(Engineyard::Local::Middleware::Bundle)
66
+ @cmd.up
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,40 @@
1
+ require "test_helper"
2
+
3
+ class CommandTest < Test::Unit::TestCase
4
+ include Vagrant::TestHelpers
5
+
6
+ context "Command" do
7
+ setup do
8
+ @klass = Engineyard::Local::Command
9
+ @cmdgrp = Engineyard::Local::Command::Group
10
+ @klass.stubs(:passthrough).returns(["foo"])
11
+ @klass.stubs(:all).returns(["foo", "bar"])
12
+
13
+ @app, @env = action_env
14
+ @klass.stubs(:vagrant_env).returns(@env)
15
+ end
16
+
17
+ should "not start Thor when command is member of passthrough set" do
18
+ # add description for the expected method below to prevent
19
+ # thor warning
20
+ @cmdgrp.desc("foo", "desc")
21
+
22
+ @cmdgrp.any_instance.expects(:foo).once
23
+ @cmdgrp.expects(:start).never
24
+
25
+ @klass.dispatch(["foo"])
26
+ end
27
+
28
+ should "start thor when the command is not passthrough" do
29
+ @cmdgrp.expects(:start).once
30
+
31
+ @klass.dispatch(["bar"])
32
+ end
33
+
34
+ should "return false when the command isn't included defined by ey-local" do
35
+ args = ["not-there-at-all"]
36
+ @env.expects(:cli).with(args)
37
+ assert !@klass.dispatch(args)
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,32 @@
1
+ require "test_helper"
2
+
3
+ class BundleTest < Test::Unit::TestCase
4
+ include Vagrant::TestHelpers
5
+ include Engineyard::Local::TestHelpers
6
+
7
+ context "bundle" do
8
+ setup do
9
+ @app, @env = action_env
10
+ @middleware = Engineyard::Local::Middleware::Bundle.new(@app, @env)
11
+ end
12
+
13
+ should "provide the project directory" do
14
+ # TODO reference default config
15
+ assert_equal(@middleware.project_dir, "/vagrant")
16
+ end
17
+
18
+ should "setup the users environment for the ssh session (rvm)" do
19
+ assert(joined_commands.include?("/etc/profile.d/"))
20
+ end
21
+
22
+ should "set the rvm environment and gemset" do
23
+ # rvm command
24
+ assert(joined_commands.include?("rvm use"))
25
+ end
26
+
27
+ should "execute the commands necessary to install bundle in the app gemset" do
28
+ mock_ssh_channel(@env).expects(:execute).with(joined_commands)
29
+ @middleware.call(@env)
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,35 @@
1
+ require "test_helper"
2
+
3
+ class DefaultProvisionerTest < Test::Unit::TestCase
4
+ include Vagrant::TestHelpers
5
+ include Engineyard::Local::TestHelpers
6
+
7
+ context "defaulting the provisioner" do
8
+ setup do
9
+ @app, @env = action_env
10
+ @middleware = Engineyard::Local::Middleware::DefaultProvisioner.new(@app, @env)
11
+ end
12
+
13
+ should "not alter the provisioners list when the recipe doesn't exist" do
14
+ @middleware.expects(:default_recipe_path).returns("/will-not-exist")
15
+ @env[:vm].config.vm.expects(:provision).never
16
+ @middleware.call(@env)
17
+ end
18
+
19
+ should "not alter the provisioners list when another is configured" do
20
+ # ensure file check passes
21
+ @middleware.expects(:default_recipe_path).returns(File.expand_path(__FILE__))
22
+ @middleware.expects(:provisioner_configured?).returns(true)
23
+ @env[:vm].config.vm.expects(:provision).never
24
+ @middleware.call(@env)
25
+ end
26
+
27
+ should "add a provisioner when the recipe exists and there are no other provisioners" do
28
+ # ensure file check passes, called twice for the ui output
29
+ @middleware.expects(:default_recipe_path).twice.returns(File.expand_path(__FILE__))
30
+ @middleware.expects(:provisioner_configured?).returns(false)
31
+ @env[:vm].config.vm.expects(:provision).once
32
+ @middleware.call(@env)
33
+ end
34
+ end
35
+ end