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.
- 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
|