engineyard-local 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +23 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +62 -0
- data/README.md +115 -0
- data/Rakefile +15 -0
- data/bin/ey-local +4 -0
- data/config/dna.json +206 -0
- data/config/locales/en.yml +57 -0
- data/config/settings.yml +18 -0
- data/config/solo.rb +7 -0
- data/engineyard-local.gemspec +24 -0
- data/install/deb/README.md +72 -0
- data/install/deb/Rakefile +157 -0
- data/install/deb/Vagrantfile +10 -0
- data/install/deb/install.sh +32 -0
- data/install/osx/README.md +23 -0
- data/install/osx/Rakefile +39 -0
- data/install/osx/engineyard-local/engineyard-local.pkgproj +812 -0
- data/install/osx/images/eylocal_installer.png +0 -0
- data/install/osx/scripts/log.sh +3 -0
- data/install/osx/scripts/postinstall +57 -0
- data/install/osx/scripts/rvm_install.sh +34 -0
- data/lib/engineyard-local.rb +42 -0
- data/lib/engineyard-local/command.rb +65 -0
- data/lib/engineyard-local/command/base.rb +15 -0
- data/lib/engineyard-local/command/exec.rb +11 -0
- data/lib/engineyard-local/command/group.rb +86 -0
- data/lib/engineyard-local/command/helpers.rb +23 -0
- data/lib/engineyard-local/command/list.rb +29 -0
- data/lib/engineyard-local/command/rails.rb +19 -0
- data/lib/engineyard-local/command/up.rb +87 -0
- data/lib/engineyard-local/command/vagrant_action.rb +11 -0
- data/lib/engineyard-local/errors.rb +10 -0
- data/lib/engineyard-local/middleware.rb +28 -0
- data/lib/engineyard-local/middleware/bundle.rb +40 -0
- data/lib/engineyard-local/middleware/chef.rb +44 -0
- data/lib/engineyard-local/middleware/default_provisioner.rb +34 -0
- data/lib/engineyard-local/middleware/dna.rb +80 -0
- data/lib/engineyard-local/middleware/exec.rb +27 -0
- data/lib/engineyard-local/middleware/helpers.rb +4 -0
- data/lib/engineyard-local/middleware/helpers/executable.rb +27 -0
- data/lib/engineyard-local/middleware/helpers/network.rb +20 -0
- data/lib/engineyard-local/middleware/helpers/rvm.rb +37 -0
- data/lib/engineyard-local/middleware/helpers/uploadable.rb +14 -0
- data/lib/engineyard-local/middleware/network.rb +64 -0
- data/lib/engineyard-local/middleware/rails.rb +3 -0
- data/lib/engineyard-local/middleware/rails/command.rb +31 -0
- data/lib/engineyard-local/middleware/rails/db.rb +36 -0
- data/lib/engineyard-local/middleware/rails/install.rb +36 -0
- data/lib/engineyard-local/middleware/rails/new.rb +31 -0
- data/lib/engineyard-local/middleware/tag.rb +33 -0
- data/lib/engineyard-local/ui.rb +33 -0
- data/lib/engineyard-local/version.rb +5 -0
- data/lib/engineyard-local/virtualbox.rb +35 -0
- data/lib/vagrant_init.rb +1 -0
- data/test/engineyard-local/command/group_test.rb +34 -0
- data/test/engineyard-local/command/up_test.rb +70 -0
- data/test/engineyard-local/command_test.rb +40 -0
- data/test/engineyard-local/middelware/bundle_test.rb +32 -0
- data/test/engineyard-local/middelware/default_provisioner_test.rb +35 -0
- data/test/engineyard-local/middelware/exec_test.rb +19 -0
- data/test/engineyard-local/middelware/network_test.rb +94 -0
- data/test/engineyard-local/middelware/rails/command_test.rb +24 -0
- data/test/engineyard-local/middelware/rails/db_test.rb +23 -0
- data/test/engineyard-local/middelware/rails/install_test.rb +24 -0
- data/test/engineyard-local/ui_test.rb +22 -0
- data/test/engineyard-local/virtualbox_test.rb +34 -0
- data/test/integration/up_test.rb +28 -0
- data/test/test_helper.rb +78 -0
- metadata +178 -0
@@ -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,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
|
data/lib/vagrant_init.rb
ADDED
@@ -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
|