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,28 @@
|
|
1
|
+
require "engineyard-local/middleware/bundle"
|
2
|
+
require "engineyard-local/middleware/dna"
|
3
|
+
require "engineyard-local/middleware/chef"
|
4
|
+
require "engineyard-local/middleware/rails"
|
5
|
+
require "engineyard-local/middleware/exec"
|
6
|
+
require "engineyard-local/middleware/tag"
|
7
|
+
require "engineyard-local/middleware/network"
|
8
|
+
require "engineyard-local/middleware/default_provisioner"
|
9
|
+
|
10
|
+
# alter some of the core vagrant middleware stacks to make sure
|
11
|
+
# the the default provisioner is run where necessary
|
12
|
+
module Engineyard
|
13
|
+
module Local
|
14
|
+
module Middleware
|
15
|
+
registry = Vagrant.actions
|
16
|
+
up = registry.get(:up)
|
17
|
+
reload = registry.get(:reload)
|
18
|
+
|
19
|
+
up.insert(4, DefaultProvisioner)
|
20
|
+
|
21
|
+
# alter the reload middelware to check for default provisioning
|
22
|
+
reload.insert(1, DefaultProvisioner)
|
23
|
+
|
24
|
+
registry.register(:up, up)
|
25
|
+
registry.register(:reload, reload)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Engineyard
|
2
|
+
module Local
|
3
|
+
module Middleware
|
4
|
+
class Bundle
|
5
|
+
include Middleware::Helpers::Rvm
|
6
|
+
include Middleware::Helpers::Executable
|
7
|
+
|
8
|
+
def initialize(app, env)
|
9
|
+
@app = app
|
10
|
+
@env = env
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(env)
|
14
|
+
@env[:ui].info I18n.t("eylocal.setup.bundling")
|
15
|
+
ssh_exec!(env, commands)
|
16
|
+
@app.call(env)
|
17
|
+
end
|
18
|
+
|
19
|
+
def commands
|
20
|
+
rvm_env +
|
21
|
+
[
|
22
|
+
ensure_bundler_is_installed,
|
23
|
+
"cd #{project_dir}",
|
24
|
+
"sudo mkdir -p #{project_dir} /data/#{Engineyard::Local.config['app_name']}/",
|
25
|
+
"if [[ ! -e /data/#{Engineyard::Local.config['app_name']}/current ]]; then sudo ln -sf #{project_dir} /data/#{Engineyard::Local.config['app_name']}/current; fi",
|
26
|
+
if_gemfile_exists("sudo bundle install")
|
27
|
+
]
|
28
|
+
end
|
29
|
+
|
30
|
+
def ensure_bundler_is_installed
|
31
|
+
"sudo bash -c 'command -v bundle &>/dev/null || { sudo gem install bundler; exit 0; }'"
|
32
|
+
end
|
33
|
+
|
34
|
+
def if_gemfile_exists(cmd)
|
35
|
+
"if [[ -e Gemfile || -e Gemfile.lock ]]; then #{cmd}; fi"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Engineyard
|
2
|
+
module Local
|
3
|
+
module Middleware
|
4
|
+
class Chef
|
5
|
+
include Middleware::Helpers::Executable
|
6
|
+
include Middleware::Helpers::Rvm
|
7
|
+
|
8
|
+
def initialize(app, env)
|
9
|
+
@app = app
|
10
|
+
@env = env
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(env)
|
14
|
+
@env[:ui].info I18n.t("eylocal.setup.chef")
|
15
|
+
ssh_exec!(env, commands)
|
16
|
+
@app.call(env)
|
17
|
+
end
|
18
|
+
|
19
|
+
def commands
|
20
|
+
rvm_env +
|
21
|
+
[
|
22
|
+
ensure_that_recipes_are_installed,
|
23
|
+
"cd /etc/chef",
|
24
|
+
"sudo env PATH=/usr/local/ey_resin/bin:/sbin:/bin:/usr/sbin:/usr/bin chef-solo -j /etc/chef/dna.json -c /etc/chef/solo.rb",
|
25
|
+
run_custom_chef_in_application_if_it_exists
|
26
|
+
]
|
27
|
+
end
|
28
|
+
|
29
|
+
def ensure_that_recipes_are_installed
|
30
|
+
"if [[ ! -d /etc/chef/recipes ]]; then curl -s #{cookbook_uri} > /tmp/chef.tar.bz2; sudo mkdir -p /etc/chef/recipes && cd /etc/chef/recipes && sudo tar -xjf /tmp/chef.tar.bz2; rm /tmp/chef.tar.bz2; fi"
|
31
|
+
end
|
32
|
+
|
33
|
+
def run_custom_chef_in_application_if_it_exists
|
34
|
+
"if [[ -d /vagrant/deploy ]] ; then shopt -s nullglob; for rb in /vagrant/deploy/*.rb; do sudo env PATH=/usr/local/ey_resin/bin:/sbin:/bin:/usr/sbin:/usr/bin chef-solo -j /etc/chef/dna.json -c ${rb}; done; shopt -u nullglob; fi"
|
35
|
+
end
|
36
|
+
|
37
|
+
def cookbook_uri
|
38
|
+
Local.config[:box_defaults][:cookbook_uri]
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Engineyard
|
2
|
+
module Local
|
3
|
+
module Middleware
|
4
|
+
class DefaultProvisioner
|
5
|
+
def initialize(app, env)
|
6
|
+
@app, @env = app, env
|
7
|
+
end
|
8
|
+
|
9
|
+
# if the default recipe cookbooks/main/recipes/default.rb exists
|
10
|
+
# and the user doesn't already have a provisioner configured use
|
11
|
+
# the default recipe
|
12
|
+
def call(env)
|
13
|
+
if File.exists?(default_recipe_path) && !provisioner_configured?
|
14
|
+
@env[:ui].info I18n.t("eylocal.provisioner", :recipe_path => default_recipe_path)
|
15
|
+
@env[:vm].config.vm.provision :chef_solo do |chef|
|
16
|
+
chef.cookbooks_path = "cookbooks"
|
17
|
+
chef.add_recipe "main"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
@app.call(env)
|
22
|
+
end
|
23
|
+
|
24
|
+
def default_recipe_path
|
25
|
+
File.join(@env[:root_path], "cookbooks", "main", "recipes", "default.rb")
|
26
|
+
end
|
27
|
+
|
28
|
+
def provisioner_configured?
|
29
|
+
!@env[:vm].config.vm.provisioners.empty?
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Engineyard
|
4
|
+
module Local
|
5
|
+
module Middleware
|
6
|
+
class DNA
|
7
|
+
include Middleware::Helpers::Uploadable
|
8
|
+
include Middleware::Helpers::Executable
|
9
|
+
|
10
|
+
def initialize(app, env)
|
11
|
+
@app = app
|
12
|
+
@env = env
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(env)
|
16
|
+
@env[:ui].info I18n.t("eylocal.setup.dna")
|
17
|
+
|
18
|
+
create_dna
|
19
|
+
ssh_upload!(env, dna_tmp_to, dna_tmp_to)
|
20
|
+
ssh_upload!(env, solo_from, solo_tmp_to)
|
21
|
+
ssh_exec!(env, commands)
|
22
|
+
FileUtils.rm dna_tmp_to
|
23
|
+
@app.call(env)
|
24
|
+
end
|
25
|
+
|
26
|
+
def create_dna
|
27
|
+
dna_data = File.read(dna_from)
|
28
|
+
|
29
|
+
app_url = %Q{#{`git config remote.origin.url`}}.strip
|
30
|
+
app_url = app_url.empty? ? "file://#{Dir.pwd}" : app_url
|
31
|
+
Engineyard::Local.config['app_git_url'] = app_url
|
32
|
+
|
33
|
+
Engineyard::Local.config['app_name'] = Engineyard::Local.config['app_git_url'].sub(/^.*\/([^\/\.]+)(?:\.git)?/,'\1').strip.gsub(/\s/,'_')
|
34
|
+
|
35
|
+
Engineyard::Local.config['app_revision'] = %Q{#{`git show --format=oneline`.gsub(/^(\w+).*$/m,'\1')}}.strip
|
36
|
+
app_type = 'rack'
|
37
|
+
|
38
|
+
dna_data.gsub!(/APPNAME/,Engineyard::Local.config['app_name'])
|
39
|
+
dna_data.gsub!(/APPURL/,Engineyard::Local.config['app_git_url'])
|
40
|
+
dna_data.gsub!(/APPREVISION/,Engineyard::Local.config['app_revision'])
|
41
|
+
dna_data.gsub!(/APPTYPE/,app_type)
|
42
|
+
|
43
|
+
File.open(dna_tmp_to, "w+") {|fh| fh.write dna_data}
|
44
|
+
end
|
45
|
+
|
46
|
+
def commands
|
47
|
+
[
|
48
|
+
"sudo mv #{solo_tmp_to} #{solo_to}",
|
49
|
+
"sudo mv #{dna_tmp_to} #{dna_to}",
|
50
|
+
]
|
51
|
+
end
|
52
|
+
|
53
|
+
def dna_from
|
54
|
+
File.expand_path("config/dna.json", Engineyard::Local.project_root)
|
55
|
+
end
|
56
|
+
|
57
|
+
def dna_tmp_to
|
58
|
+
"/tmp/dna.json.#{$$}"
|
59
|
+
end
|
60
|
+
|
61
|
+
def dna_to
|
62
|
+
"/etc/chef/dna.json"
|
63
|
+
end
|
64
|
+
|
65
|
+
def solo_from
|
66
|
+
File.expand_path("config/solo.rb", Engineyard::Local.project_root)
|
67
|
+
end
|
68
|
+
|
69
|
+
def solo_tmp_to
|
70
|
+
"/tmp/solo.rb.#{$$}"
|
71
|
+
end
|
72
|
+
|
73
|
+
def solo_to
|
74
|
+
"/etc/chef/solo.rb"
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Engineyard
|
2
|
+
module Local
|
3
|
+
module Middleware
|
4
|
+
class Exec
|
5
|
+
include Middleware::Helpers::Rvm
|
6
|
+
include Middleware::Helpers::Executable
|
7
|
+
|
8
|
+
def initialize(app, env)
|
9
|
+
@app, @env = app, env
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(env)
|
13
|
+
ssh_exec!(env, commands, :prefix => false)
|
14
|
+
@app.call(env)
|
15
|
+
end
|
16
|
+
|
17
|
+
def commands
|
18
|
+
rvm_env + [ "cd #{project_dir}", command_args ]
|
19
|
+
end
|
20
|
+
|
21
|
+
def command_args
|
22
|
+
@env["eylocal.exec.command_args"].join(" ")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Engineyard
|
2
|
+
module Local
|
3
|
+
module Middleware
|
4
|
+
module Helpers
|
5
|
+
module Executable
|
6
|
+
# Depends soley on the commands method
|
7
|
+
def ssh_exec!(env, bash_commands, opts = {})
|
8
|
+
commands = bash_commands.join(";\n")
|
9
|
+
|
10
|
+
env[:vm].channel.execute(commands) do |stream, data|
|
11
|
+
if stream == :stdout
|
12
|
+
env[:vm].ui.info(data.strip)
|
13
|
+
else
|
14
|
+
env[:vm].ui.error(data.strip)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# TODO might belong in a general helpers mixin
|
20
|
+
def project_dir
|
21
|
+
@env[:vm].config.vm.shared_folders["v-root"][:guestpath]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Engineyard
|
2
|
+
module Local
|
3
|
+
module Middleware
|
4
|
+
module Helpers
|
5
|
+
module Network
|
6
|
+
def proposed_ip
|
7
|
+
# networks is an array of pairs, snd is the ip, fst is type
|
8
|
+
# TODO this generally sucks and is tightly coupled to vagrant internals
|
9
|
+
(networks.first || [[]]).last.first || Local.config[:network] || '10.0.0.1'
|
10
|
+
end
|
11
|
+
|
12
|
+
def networks
|
13
|
+
@env[:vm].config.vm.networks
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Engineyard
|
2
|
+
module Local
|
3
|
+
module Middleware
|
4
|
+
module Helpers
|
5
|
+
# TODO this whole helper should be removed by setting up rvm properly
|
6
|
+
# for the vagrant ssh session user inside the vm
|
7
|
+
module Rvm
|
8
|
+
def ruby_env_const
|
9
|
+
Local.config[:rvm][:ruby_env_const]
|
10
|
+
end
|
11
|
+
|
12
|
+
# get the first ruby listed by rvm list
|
13
|
+
# TODO fragile
|
14
|
+
def export_ruby
|
15
|
+
%Q(export #{ ruby_env_const }=`rvm list | grep "^ " | awk '{ print $1 }' | tail -1`)
|
16
|
+
end
|
17
|
+
|
18
|
+
# TODO determine gemset and app name and export
|
19
|
+
def use_ruby_with_gemset
|
20
|
+
"rvm use $#{ ruby_env_const } > /dev/null"
|
21
|
+
end
|
22
|
+
|
23
|
+
def bash_rvm_setup
|
24
|
+
"source /etc/profile.d/*"
|
25
|
+
end
|
26
|
+
|
27
|
+
# everything needed to setup the proper gemset env
|
28
|
+
def rvm_env
|
29
|
+
[ bash_rvm_setup,
|
30
|
+
export_ruby,
|
31
|
+
use_ruby_with_gemset ]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Engineyard
|
2
|
+
module Local
|
3
|
+
module Middleware
|
4
|
+
class Network
|
5
|
+
include Helpers::Network
|
6
|
+
|
7
|
+
def initialize(app, env, options)
|
8
|
+
@app, @env, @options = app, env, options
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
Virtualbox.uuid_map.each do |name, uuid|
|
13
|
+
# skip the current vm
|
14
|
+
next if uuid == env[:vm].uuid
|
15
|
+
|
16
|
+
# get the configured ip from the tag data stored by ey-local
|
17
|
+
existing_ip = Virtualbox.extra_data(uuid, Local.config[:network_ip_key])
|
18
|
+
|
19
|
+
# if the proposed ip matches a different vms tagged ip
|
20
|
+
# let the user decide if this is intended or needs to be fixed
|
21
|
+
if(!@options[:silent] && existing_ip == proposed_ip)
|
22
|
+
while !["Y", "N"].include?(result ||= nil)
|
23
|
+
result = check_with_user(name)
|
24
|
+
end
|
25
|
+
|
26
|
+
if result == "N"
|
27
|
+
raise(Errors::PossibleIPCollision,
|
28
|
+
:proposed_ip => proposed_ip,
|
29
|
+
:vm_name => name)
|
30
|
+
end
|
31
|
+
|
32
|
+
if result == "Y"
|
33
|
+
break
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
@app.call(env)
|
39
|
+
end
|
40
|
+
|
41
|
+
def check_with_user(name)
|
42
|
+
@env[:ui].ask(prompt(name), :color => Thor::Shell::Color::YELLOW)
|
43
|
+
end
|
44
|
+
|
45
|
+
def prompt(name)
|
46
|
+
@prompt ||= I18n.t("eylocal.actions.network.prompt",
|
47
|
+
:vm_name => name,
|
48
|
+
:proposed_ip => proposed_ip)
|
49
|
+
end
|
50
|
+
|
51
|
+
#taken directly from Vagrant source
|
52
|
+
def recover(env)
|
53
|
+
if env[:vm].created? && env["vagrant.error"].is_a?(Errors::PossibleIPCollision)
|
54
|
+
# Interrupted, destroy the VM. We note that we don't want to
|
55
|
+
# validate the configuration here.
|
56
|
+
destroy_env = env.clone
|
57
|
+
destroy_env[:validate] = false
|
58
|
+
env[:action_runner].run(:destroy, destroy_env)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|