engineyard-local 0.2.1 → 1.0.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/Gemfile +1 -0
- data/Gemfile.lock +73 -1
- data/README.md +40 -38
- data/config/dna.json +92 -66
- data/config/locales/en.yml +94 -9
- data/config/patches/chef-ey-1.1.336.patch +55 -0
- data/config/settings.yml +6 -1
- data/engineyard-local.gemspec +5 -4
- data/install/osx/README.md +42 -4
- data/install/osx/engineyard-local/engineyard-local.pkgproj +35 -6
- data/install/osx/images/dmg_background.png +0 -0
- data/install/osx/images/dmg_icon.icns +0 -0
- data/lib/engineyard-local.rb +64 -0
- data/lib/engineyard-local/command.rb +23 -0
- data/lib/engineyard-local/command/base.rb +78 -1
- data/lib/engineyard-local/command/group.rb +70 -6
- data/lib/engineyard-local/command/help.rb +36 -0
- data/lib/engineyard-local/command/helpers.rb +12 -0
- data/lib/engineyard-local/command/start.rb +26 -0
- data/lib/engineyard-local/command/status.rb +33 -0
- data/lib/engineyard-local/command/stop.rb +26 -0
- data/lib/engineyard-local/command/terminate.rb +26 -0
- data/lib/engineyard-local/command/up.rb +24 -15
- data/lib/engineyard-local/command/update.rb +42 -0
- data/lib/engineyard-local/middleware.rb +1 -0
- data/lib/engineyard-local/middleware/bundle.rb +1 -0
- data/lib/engineyard-local/middleware/chef.rb +52 -2
- data/lib/engineyard-local/middleware/cookbooks.rb +111 -0
- data/lib/engineyard-local/middleware/dna.rb +6 -4
- data/lib/engineyard-local/middleware/exec.rb +2 -1
- data/lib/engineyard-local/middleware/helpers/executable.rb +14 -2
- data/lib/engineyard-local/middleware/network.rb +3 -3
- data/lib/engineyard-local/middleware/rails.rb +1 -0
- data/lib/engineyard-local/middleware/rails/assets.rb +35 -0
- data/lib/engineyard-local/middleware/rails/command.rb +1 -1
- data/lib/engineyard-local/middleware/rails/db.rb +0 -1
- data/lib/engineyard-local/middleware/rails/new.rb +1 -1
- data/lib/engineyard-local/version.rb +1 -1
- data/test/engineyard-local/command/up_test.rb +1 -0
- data/test/integration/commands_test.rb +30 -0
- data/test/test_helper.rb +8 -2
- metadata +81 -70
- data/install/osx/images/eylocal_installer.png +0 -0
- data/test/integration/up_test.rb +0 -28
@@ -0,0 +1,42 @@
|
|
1
|
+
module Engineyard
|
2
|
+
module Local
|
3
|
+
module Command
|
4
|
+
class Update < Base
|
5
|
+
|
6
|
+
def exec(*args)
|
7
|
+
installed_cookbook_version = []
|
8
|
+
la_brea_data = []
|
9
|
+
run( Vagrant::Action::Builder.new do
|
10
|
+
use( Engineyard::Local::Middleware::Cookbooks,:get_installed_version, installed_cookbook_version )
|
11
|
+
use( Engineyard::Local::Middleware::Cookbooks,:get_la_brea_data, la_brea_data )
|
12
|
+
end )
|
13
|
+
|
14
|
+
installed_cookbook_version = installed_cookbook_version.first
|
15
|
+
la_brea_data = la_brea_data.first
|
16
|
+
|
17
|
+
if ( installed_cookbook_version == la_brea_data[:cookbooks_version] )
|
18
|
+
@env.ui.info I18n.t("eylocal.update.nothing")
|
19
|
+
else
|
20
|
+
@env.ui.info I18n.t("eylocal.update.updating")
|
21
|
+
|
22
|
+
new_cookbook_version = []
|
23
|
+
run( Vagrant::Action::Builder.new do
|
24
|
+
use( Engineyard::Local::Middleware::Cookbooks,:update_cookbooks )
|
25
|
+
use( Engineyard::Local::Middleware::Cookbooks,:get_installed_version, new_cookbook_version )
|
26
|
+
end )
|
27
|
+
new_cookbook_version = new_cookbook_version.first
|
28
|
+
|
29
|
+
if (installed_cookbook_version == new_cookbook_version)
|
30
|
+
@env.ui.info I18n.t("eylocal.update.fail")
|
31
|
+
else
|
32
|
+
@env.ui.info I18n.t("eylocal.update.success")
|
33
|
+
run Engineyard::Local::Command::Up.setup_stack(options)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -5,6 +5,7 @@ require "engineyard-local/middleware/rails"
|
|
5
5
|
require "engineyard-local/middleware/exec"
|
6
6
|
require "engineyard-local/middleware/tag"
|
7
7
|
require "engineyard-local/middleware/network"
|
8
|
+
require "engineyard-local/middleware/cookbooks"
|
8
9
|
require "engineyard-local/middleware/default_provisioner"
|
9
10
|
|
10
11
|
# alter some of the core vagrant middleware stacks to make sure
|
@@ -23,6 +23,7 @@ module Engineyard
|
|
23
23
|
"cd #{project_dir}",
|
24
24
|
"sudo mkdir -p #{project_dir} /data/#{Engineyard::Local.config['app_name']}/",
|
25
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 [[ ! -e /data/#{Engineyard::Local.config['app_name']}/current/public ]]; then sudo mkdir -p /data/#{Engineyard::Local.config['app_name']}/current/public; fi",
|
26
27
|
if_gemfile_exists("sudo bundle install")
|
27
28
|
]
|
28
29
|
end
|
@@ -2,6 +2,7 @@ module Engineyard
|
|
2
2
|
module Local
|
3
3
|
module Middleware
|
4
4
|
class Chef
|
5
|
+
include Middleware::Helpers::Uploadable
|
5
6
|
include Middleware::Helpers::Executable
|
6
7
|
include Middleware::Helpers::Rvm
|
7
8
|
|
@@ -12,22 +13,38 @@ module Engineyard
|
|
12
13
|
|
13
14
|
def call(env)
|
14
15
|
@env[:ui].info I18n.t("eylocal.setup.chef")
|
16
|
+
copy_patches(env)
|
15
17
|
ssh_exec!(env, commands)
|
16
18
|
@app.call(env)
|
17
19
|
end
|
18
20
|
|
21
|
+
def cached_data_path
|
22
|
+
"#{@env[:root_path]}/.ey_local_data"
|
23
|
+
end
|
24
|
+
|
25
|
+
def copy_patches(env)
|
26
|
+
patchdir = "/tmp/eylocal_patches"
|
27
|
+
ssh_exec!(env, ["mkdir -p #{patchdir}"])
|
28
|
+
|
29
|
+
Local.config[:box_defaults][:patches].each do |p|
|
30
|
+
from = File.expand_path("config/patches/#{p}", Engineyard::Local.project_root)
|
31
|
+
ssh_upload!(env, from, File.join(patchdir,p))
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
19
35
|
def commands
|
20
36
|
rvm_env +
|
21
37
|
[
|
22
38
|
ensure_that_recipes_are_installed,
|
23
39
|
"cd /etc/chef",
|
24
40
|
"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",
|
41
|
+
"if [[ ! -e /usr/bin/rake ]]; then sudo ln -s /usr/bin/rake19 /usr/bin/rake; fi",
|
25
42
|
run_custom_chef_in_application_if_it_exists
|
26
43
|
]
|
27
44
|
end
|
28
45
|
|
29
46
|
def ensure_that_recipes_are_installed
|
30
|
-
"if [[ ! -d /etc/chef/recipes ]]; then curl -s #{cookbook_uri} > /tmp/chef.tar
|
47
|
+
"if [[ ! -d /etc/chef/recipes ]]; then curl -s #{cookbook_uri} > /tmp/chef.tar#{cookbook_suffix}; sudo mkdir -p /etc/chef/recipes && cd /etc/chef/recipes && sudo tar #{tar_flags} /tmp/chef.tar#{cookbook_suffix}; sudo patch -p1 < /tmp/eylocal_patches/* >& /dev/null; sudo touch #{Engineyard::Local::Middleware::Cookbooks::COOKBOOK_VERSION_FILE}; sudo chown vagrant #{Engineyard::Local::Middleware::Cookbooks::COOKBOOK_VERSION_FILE}; echo \"#{cookbook_version}\" > #{Engineyard::Local::Middleware::Cookbooks::COOKBOOK_VERSION_FILE}; rm /tmp/chef.tar#{cookbook_suffix}; fi"
|
31
48
|
end
|
32
49
|
|
33
50
|
def run_custom_chef_in_application_if_it_exists
|
@@ -35,7 +52,40 @@ module Engineyard
|
|
35
52
|
end
|
36
53
|
|
37
54
|
def cookbook_uri
|
38
|
-
|
55
|
+
ey_local_data = nil
|
56
|
+
if ( !@cookbook_uri && File.exist?( cached_data_path ) )
|
57
|
+
ey_local_data = YAML.load( File.read( cached_data_path ) )
|
58
|
+
end
|
59
|
+
@la_brea_data ||= ey_local_data ? ey_local_data[:la_brea_data] : nil
|
60
|
+
@cookbook_uri ||= ( ey_local_data && ey_local_data[:la_brea_data][:cookbooks_url] ) ?
|
61
|
+
ey_local_data[:la_brea_data][:cookbooks_url] : Local.config[:box_defaults][:cookbook_uri]
|
62
|
+
end
|
63
|
+
|
64
|
+
def cookbook_suffix
|
65
|
+
cookbook_uri =~ /\.(\w+)$/
|
66
|
+
case $1
|
67
|
+
when /bz2|tbz/
|
68
|
+
".bz2"
|
69
|
+
when /gz|tgz/
|
70
|
+
".gz"
|
71
|
+
else
|
72
|
+
""
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def tar_flags
|
77
|
+
case cookbook_suffix
|
78
|
+
when /bz2|tbz/
|
79
|
+
"-xjf"
|
80
|
+
when /gz|tgz/
|
81
|
+
"-xzf"
|
82
|
+
else
|
83
|
+
"-xf"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def cookbook_version
|
88
|
+
( @la_brea_data && @la_brea_data[:cookbooks_version] ) ? @la_brea_data[:cookbooks_version] : Local.config[:box_defaults][:cookbook_version]
|
39
89
|
end
|
40
90
|
|
41
91
|
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
|
3
|
+
module Engineyard
|
4
|
+
module Local
|
5
|
+
module Middleware
|
6
|
+
class Cookbooks
|
7
|
+
include Middleware::Helpers::Executable
|
8
|
+
include Middleware::Helpers::Rvm
|
9
|
+
extend Middleware::Helpers::Executable
|
10
|
+
|
11
|
+
DATA_EXPIRATION = 600
|
12
|
+
COOKBOOK_VERSION_FILE = "/etc/chef/ey_local_cookbook_version"
|
13
|
+
|
14
|
+
def cookbook_query_commands
|
15
|
+
[
|
16
|
+
"cat #{COOKBOOK_VERSION_FILE}"
|
17
|
+
]
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(app, env, *args)
|
21
|
+
@app = app
|
22
|
+
@env = env
|
23
|
+
@args = args
|
24
|
+
end
|
25
|
+
|
26
|
+
def cached_data_path
|
27
|
+
"#{@env[:root_path]}/.ey_local_data"
|
28
|
+
end
|
29
|
+
|
30
|
+
def call(env)
|
31
|
+
cmd,response = @args
|
32
|
+
|
33
|
+
if File.exist?(cached_data_path)
|
34
|
+
ey_local_data = YAML.load(File.read(cached_data_path))
|
35
|
+
else
|
36
|
+
ey_local_data = {
|
37
|
+
:installed_cookbook_version => {
|
38
|
+
:data => nil,
|
39
|
+
:as_of => Time.at(1)
|
40
|
+
},
|
41
|
+
:la_brea_data => {
|
42
|
+
:changelog => nil,
|
43
|
+
:cookbooks_url => nil,
|
44
|
+
:cookbooks_version => nil,
|
45
|
+
:created_at => nil,
|
46
|
+
:updated_at => nil,
|
47
|
+
:uuid => nil,
|
48
|
+
:as_of => Time.at(1)
|
49
|
+
}
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
case cmd
|
54
|
+
when :get_installed_version
|
55
|
+
get_installed_cookbook_version(ey_local_data)
|
56
|
+
response << ey_local_data[:installed_cookbook_version][:data]
|
57
|
+
|
58
|
+
when :get_la_brea_data
|
59
|
+
get_la_brea_data(ey_local_data)
|
60
|
+
response << ey_local_data[:la_brea_data]
|
61
|
+
|
62
|
+
when :update_cookbooks
|
63
|
+
get_la_brea_data(ey_local_data)
|
64
|
+
|
65
|
+
ssh_exec!(@env, update_cookbook_commands(
|
66
|
+
ey_local_data[:la_brea_data][:cookbooks_url],
|
67
|
+
ey_local_data[:la_brea_data][:cookbooks_version]))
|
68
|
+
get_installed_cookbook_version(ey_local_data, true)
|
69
|
+
end
|
70
|
+
|
71
|
+
@app.call(env)
|
72
|
+
end
|
73
|
+
|
74
|
+
def get_installed_cookbook_version(ey_local_data, force = false)
|
75
|
+
if ( force || ( Time.now > ( ey_local_data[:installed_cookbook_version][:as_of] + DATA_EXPIRATION ) ) )
|
76
|
+
cmd_output = ssh_exec(@env, cookbook_query_commands, {:error_check => false})
|
77
|
+
ey_local_data[:installed_cookbook_version][:data] = cmd_output[:stdout] ? cmd_output[:stdout].join.chomp : nil
|
78
|
+
ey_local_data[:installed_cookbook_version][:as_of] = Time.now
|
79
|
+
write_cached_data(ey_local_data)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def get_la_brea_data(ey_local_data)
|
84
|
+
if ( Time.now > ( ey_local_data[:la_brea_data][:as_of] + DATA_EXPIRATION ) )
|
85
|
+
r = YAML.load(open("http://#{Engineyard::Local.config[:la_brea_bridge]}/stack")) rescue nil
|
86
|
+
if r
|
87
|
+
r[:as_of] = Time.now
|
88
|
+
ey_local_data[:la_brea_data] = r
|
89
|
+
write_cached_data(ey_local_data)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def write_cached_data(ey_local_data)
|
95
|
+
File.open(cached_data_path, "w+") {|fh| fh.write YAML.dump(ey_local_data)}
|
96
|
+
end
|
97
|
+
|
98
|
+
def update_cookbook_commands(cookbook_uri, cookbook_version)
|
99
|
+
rvm_env +
|
100
|
+
[
|
101
|
+
"curl -s #{cookbook_uri} > /tmp/_chef.tgz",
|
102
|
+
"sudo mkdir -p /etc/chef/recipes && cd /etc/chef/recipes && sudo tar -xzf /tmp/_chef.tgz",
|
103
|
+
"if (( ! $? )); then sudo chown \`whoami\` #{COOKBOOK_VERSION_FILE}; echo \"#{cookbook_version}\" > #{COOKBOOK_VERSION_FILE}; fi",
|
104
|
+
"rm /tmp/_chef.tgz"
|
105
|
+
]
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -45,8 +45,10 @@ module Engineyard
|
|
45
45
|
|
46
46
|
def commands
|
47
47
|
[
|
48
|
-
|
49
|
-
|
48
|
+
# Windows slashes are eliminated when these commands are
|
49
|
+
# passed, so we need to ensure they are correctly escaped.
|
50
|
+
"sudo mv #{solo_tmp_to.gsub("\\","\\\\\\")} #{solo_to}",
|
51
|
+
"sudo mv #{dna_tmp_to.gsub("\\","\\\\\\")} #{dna_to}",
|
50
52
|
]
|
51
53
|
end
|
52
54
|
|
@@ -55,7 +57,7 @@ module Engineyard
|
|
55
57
|
end
|
56
58
|
|
57
59
|
def dna_tmp_to
|
58
|
-
"
|
60
|
+
File.join(Engineyard::Local.tmp_dir,"dna.json.#{$$}")
|
59
61
|
end
|
60
62
|
|
61
63
|
def dna_to
|
@@ -67,7 +69,7 @@ module Engineyard
|
|
67
69
|
end
|
68
70
|
|
69
71
|
def solo_tmp_to
|
70
|
-
"
|
72
|
+
File.join(Engineyard::Local.tmp_dir,"solo.rb.#{$$}")
|
71
73
|
end
|
72
74
|
|
73
75
|
def solo_to
|
@@ -9,13 +9,25 @@ module Engineyard
|
|
9
9
|
|
10
10
|
env[:vm].channel.execute(commands) do |stream, data|
|
11
11
|
if stream == :stdout
|
12
|
-
env[:vm].ui.info(data.strip)
|
12
|
+
env[:vm].ui.info(data.strip, opts)
|
13
13
|
else
|
14
|
-
env[:vm].ui.error(data.strip)
|
14
|
+
env[:vm].ui.error(data.strip, opts)
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
+
def ssh_exec(env, bash_commands, opts = {})
|
20
|
+
commands = bash_commands.join(";\n")
|
21
|
+
|
22
|
+
r = Hash.new {|h,k| h[k] = []}
|
23
|
+
|
24
|
+
env[:vm].channel.execute(commands, opts) do |stream, data|
|
25
|
+
r[stream] << data
|
26
|
+
end
|
27
|
+
|
28
|
+
r
|
29
|
+
end
|
30
|
+
|
19
31
|
# TODO might belong in a general helpers mixin
|
20
32
|
def project_dir
|
21
33
|
@env[:vm].config.vm.shared_folders["v-root"][:guestpath]
|
@@ -19,17 +19,17 @@ module Engineyard
|
|
19
19
|
# if the proposed ip matches a different vms tagged ip
|
20
20
|
# let the user decide if this is intended or needs to be fixed
|
21
21
|
if(!@options[:silent] && existing_ip == proposed_ip)
|
22
|
-
while !["Y",
|
22
|
+
while !["Y","y","N","n"].include?(result ||= nil)
|
23
23
|
result = check_with_user(name)
|
24
24
|
end
|
25
25
|
|
26
|
-
if result == "N"
|
26
|
+
if result.upcase == "N"
|
27
27
|
raise(Errors::PossibleIPCollision,
|
28
28
|
:proposed_ip => proposed_ip,
|
29
29
|
:vm_name => name)
|
30
30
|
end
|
31
31
|
|
32
|
-
if result == "Y"
|
32
|
+
if result.upcase == "Y"
|
33
33
|
break
|
34
34
|
end
|
35
35
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Engineyard
|
2
|
+
module Local
|
3
|
+
module Middleware
|
4
|
+
module Rails
|
5
|
+
class Assets
|
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.assets")
|
16
|
+
ssh_exec!(env, commands)
|
17
|
+
@app.call(env)
|
18
|
+
end
|
19
|
+
|
20
|
+
def commands
|
21
|
+
[ "cd #{project_dir}",
|
22
|
+
if_task_exists("assets:precompile"),
|
23
|
+
"sudo /etc/init.d/nginx restart" ]
|
24
|
+
end
|
25
|
+
|
26
|
+
# if there's a Rakefile, and rake -T contains the task we're looking for
|
27
|
+
# execute the task
|
28
|
+
def if_task_exists(task)
|
29
|
+
"if [[ `rake -T > /dev/null 2>&1 && rake -T | grep -e '#{task}'` ]]; then rake #{task}; fi"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -16,6 +16,7 @@ class CommandUpTest < Test::Unit::TestCase
|
|
16
16
|
# prevent the bundle middleware from executing
|
17
17
|
@klass.any_instance.stubs(:with_target_vms).returns([])
|
18
18
|
@klass.any_instance.stubs(:env).returns(@env)
|
19
|
+
@klass.any_instance.stubs(:pwd_matches_root_path).returns(true)
|
19
20
|
|
20
21
|
@env.stubs(:cli)
|
21
22
|
@env.stubs(:root_path).returns(nil)
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
module Integration
|
4
|
+
class CommandsTest < Test::Unit::TestCase
|
5
|
+
include Engineyard::Local::TestHelpers::Integration
|
6
|
+
|
7
|
+
def setup
|
8
|
+
Dir.chdir(ensure_test_directory)
|
9
|
+
fail_on_stderr
|
10
|
+
clean_env
|
11
|
+
end
|
12
|
+
|
13
|
+
# TODO cramming it all in here to ensure sequence
|
14
|
+
should "up completes as do dependent commands" do
|
15
|
+
assert_cmd("ey-local up --silent")
|
16
|
+
assert(`ey-local list` != "", "the output should not be empty")
|
17
|
+
assert(`ey-local exec echo "foo"`.include?("foo"), "output should include the echo value")
|
18
|
+
|
19
|
+
log_setup
|
20
|
+
assert(`ey-local log`.strip == "dev", "log output default should come from dev log without prefix")
|
21
|
+
assert(`ey-local log --environment=production`.strip == "prod", "log output default should come from dev log without prefix")
|
22
|
+
assert_cmd("ey-local destroy -f")
|
23
|
+
end
|
24
|
+
|
25
|
+
def log_setup
|
26
|
+
`echo "dev" > log/development.log`
|
27
|
+
`echo "prod" > log/production.log`
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|