engineyard 1.4.29 → 1.7.0.pre2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. data/README.rdoc +139 -4
  2. data/bin/ey +1 -7
  3. data/lib/engineyard.rb +1 -22
  4. data/lib/engineyard/cli.rb +192 -94
  5. data/lib/engineyard/cli/#recipes.rb# +32 -0
  6. data/lib/engineyard/cli/api.rb +42 -28
  7. data/lib/engineyard/cli/recipes.rb +13 -6
  8. data/lib/engineyard/cli/ui.rb +103 -42
  9. data/lib/engineyard/cli/web.rb +16 -10
  10. data/lib/engineyard/config.rb +92 -18
  11. data/lib/engineyard/deploy_config.rb +66 -0
  12. data/lib/engineyard/deploy_config/migrate.rb +125 -0
  13. data/lib/engineyard/deploy_config/ref.rb +56 -0
  14. data/lib/engineyard/error.rb +38 -78
  15. data/lib/engineyard/repo.rb +75 -27
  16. data/lib/engineyard/serverside_runner.rb +133 -0
  17. data/lib/engineyard/thor.rb +110 -18
  18. data/lib/engineyard/version.rb +1 -1
  19. data/spec/engineyard/cli/api_spec.rb +10 -16
  20. data/spec/engineyard/cli_spec.rb +0 -11
  21. data/spec/engineyard/config_spec.rb +1 -8
  22. data/spec/engineyard/deploy_config_spec.rb +203 -0
  23. data/spec/engineyard/eyrc_spec.rb +2 -0
  24. data/spec/engineyard/repo_spec.rb +57 -34
  25. data/spec/ey/deploy_spec.rb +102 -52
  26. data/spec/ey/list_environments_spec.rb +69 -14
  27. data/spec/ey/login_spec.rb +11 -7
  28. data/spec/ey/logout_spec.rb +4 -4
  29. data/spec/ey/logs_spec.rb +6 -6
  30. data/spec/ey/recipes/apply_spec.rb +1 -1
  31. data/spec/ey/recipes/download_spec.rb +1 -1
  32. data/spec/ey/recipes/upload_spec.rb +6 -6
  33. data/spec/ey/rollback_spec.rb +3 -3
  34. data/spec/ey/ssh_spec.rb +9 -9
  35. data/spec/ey/status_spec.rb +2 -2
  36. data/spec/ey/whoami_spec.rb +9 -8
  37. data/spec/spec_helper.rb +18 -15
  38. data/spec/support/{fake_awsm.rb → git_repos.rb} +0 -14
  39. data/spec/support/helpers.rb +84 -28
  40. data/spec/support/matchers.rb +0 -16
  41. data/spec/support/shared_behavior.rb +83 -103
  42. metadata +65 -51
  43. data/lib/engineyard/api.rb +0 -117
  44. data/lib/engineyard/collection.rb +0 -7
  45. data/lib/engineyard/collection/abstract.rb +0 -71
  46. data/lib/engineyard/collection/apps.rb +0 -8
  47. data/lib/engineyard/collection/environments.rb +0 -8
  48. data/lib/engineyard/model.rb +0 -12
  49. data/lib/engineyard/model/account.rb +0 -8
  50. data/lib/engineyard/model/api_struct.rb +0 -33
  51. data/lib/engineyard/model/app.rb +0 -32
  52. data/lib/engineyard/model/deployment.rb +0 -90
  53. data/lib/engineyard/model/environment.rb +0 -194
  54. data/lib/engineyard/model/instance.rb +0 -166
  55. data/lib/engineyard/model/log.rb +0 -9
  56. data/lib/engineyard/model/user.rb +0 -6
  57. data/lib/engineyard/resolver.rb +0 -134
  58. data/lib/engineyard/rest_client_ext.rb +0 -9
  59. data/lib/engineyard/ruby_ext.rb +0 -9
  60. data/spec/engineyard/api_spec.rb +0 -39
  61. data/spec/engineyard/collection/apps_spec.rb +0 -16
  62. data/spec/engineyard/collection/environments_spec.rb +0 -16
  63. data/spec/engineyard/model/api_struct_spec.rb +0 -41
  64. data/spec/engineyard/model/environment_spec.rb +0 -198
  65. data/spec/engineyard/model/instance_spec.rb +0 -27
  66. data/spec/engineyard/resolver_spec.rb +0 -112
  67. data/spec/support/fake_awsm.ru +0 -245
  68. data/spec/support/scenarios.rb +0 -417
@@ -4,50 +4,105 @@ describe "ey environments" do
4
4
 
5
5
  given "integration"
6
6
 
7
+ before { @succeeds_on_multiple_matches = true }
8
+
9
+ def command_to_run(opts)
10
+ cmd = ["environments"]
11
+ cmd << "--environment" << opts[:environment] if opts[:environment]
12
+ cmd << "--app" << opts[:app] if opts[:app]
13
+ cmd << "--account" << opts[:account] if opts[:account]
14
+ cmd
15
+ end
16
+
17
+ def verify_ran(scenario)
18
+ @out.should match(/#{scenario[:environment]}/) if scenario[:environment]
19
+ @out.should match(/#{scenario[:application]}/) if scenario[:application]
20
+ end
21
+
22
+ include_examples "it takes an environment name and an app name and an account name"
23
+
7
24
  context "with no apps" do
8
25
  before do
9
- api_scenario "empty"
26
+ login_scenario "empty"
10
27
  end
11
28
 
12
29
  it "suggests that you use environments --all" do
13
- ey %w[environments]
14
- @out.should =~ /Use ey environments --all to see all environments./
30
+ fast_failing_ey %w[environments]
31
+ @err.should =~ /Use ey environments --all to see all environments./
15
32
  end
16
33
  end
17
34
 
18
35
  context "with apps" do
19
36
  before(:all) do
20
- api_scenario "one app, many environments"
37
+ login_scenario "one app, many environments"
21
38
  end
22
39
 
23
40
  it "lists the environments your app is in" do
24
- ey %w[environments]
25
- @out.should include('rails232app (main)')
41
+ fast_ey %w[environments]
42
+ @out.should include('main/rails232app')
26
43
  @out.should =~ /giblets/
27
44
  @out.should =~ /bakon/
28
45
  end
29
46
 
47
+ it "lists the environments with specified app" do
48
+ fast_ey %w[environments --app rails232app]
49
+ @out.should include('main/rails232app')
50
+ @out.should =~ /giblets/
51
+ @out.should =~ /bakon/
52
+ end
53
+
54
+ it "finds no environments with gibberish app" do
55
+ fast_failing_ey %w[environments --account main --app gibberish]
56
+ @err.should =~ /Use ey environments --all to see all environments./
57
+ end
58
+
59
+ it "finds no environments with gibberish account" do
60
+ fast_failing_ey %w[environments --account gibberish --app rails232]
61
+ @err.should =~ /Use ey environments --all to see all environments./
62
+ end
63
+
64
+ it "lists the environments that the app is in" do
65
+ fast_ey %w[environments --app rails232app]
66
+ @out.should include('main/rails232app')
67
+ @out.should =~ /giblets/
68
+ @out.should =~ /bakon/
69
+ end
70
+
71
+ it "lists the environments that the app is in" do
72
+ fast_ey %w[environments --account main]
73
+ @out.should include('main/rails232app')
74
+ @out.should =~ /giblets/
75
+ @out.should =~ /bakon/
76
+ end
77
+
78
+ it "lists the environments matching --environment" do
79
+ fast_ey %w[environments -e gib]
80
+ @out.should include('main/rails232app')
81
+ @out.should =~ /giblets/
82
+ @out.should_not =~ /bakon/
83
+ end
84
+
30
85
  it "reports failure to find a git repo when not in one" do
31
86
  Dir.chdir(Dir.tmpdir) do
32
- ey %w[environments], :expect_failure => true
33
- @err.should =~ /fatal: No git remotes found in .*#{Regexp.escape(Dir.tmpdir)}/
87
+ fast_failing_ey %w[environments]
88
+ @err.should =~ /fatal: Not a git repository \(or any of the parent directories\): .*#{Regexp.escape(Dir.tmpdir)}/
34
89
  @out.should_not =~ /no application configured/
35
90
  end
36
91
  end
37
92
 
38
- it "lists all environments that have apps with -a" do
39
- ey %w[environments -a]
93
+ it "lists all environments that have apps with -A" do
94
+ fast_ey %w[environments -A]
40
95
  @out.should include("bakon")
41
96
  @out.should include("giblets")
42
97
  end
43
98
 
44
99
  it "outputs simply with -s" do
45
- ey %w[environments -s], :debug => false
100
+ fast_ey %w[environments -s], :debug => false
46
101
  @out.split(/\n/).sort.should == ["bakon", "giblets"]
47
102
  end
48
103
 
49
- it "outputs all environments (including ones with no apps) simply with -a and -s" do
50
- ey %w[environments -a -s], :debug => false
104
+ it "outputs all environments (including ones with no apps) simply with -A and -s" do
105
+ fast_ey %w[environments -A -s], :debug => false
51
106
  @out.split(/\n/).sort.should == ["bakon", "beef", "giblets"]
52
107
  end
53
108
  end
@@ -58,7 +113,7 @@ describe "ey environments with an ambiguous git repo" do
58
113
  include_examples "it has an ambiguous git repo"
59
114
 
60
115
  it "lists environments from all apps using the git repo" do
61
- ey %w[environments]
116
+ fast_ey %w[environments]
62
117
  @out.should =~ /git repo matches multiple/i
63
118
  @out.should include("giblets")
64
119
  @out.should include("keycollector_production")
@@ -1,29 +1,33 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe "ey login" do
4
+ given "integration"
5
+
4
6
  context "logged in" do
5
- given "integration"
7
+ before do
8
+ login_scenario 'empty'
9
+ end
6
10
 
7
11
  it "returns the logged in user name" do
8
12
  ey %w[login]
9
- @out.should include("User Name (test@test.test)")
13
+ @out.should include("User Name (#{scenario_email})")
10
14
  end
11
15
  end
12
16
 
13
17
  context "not logged in" do
14
- given "integration without an eyrc file"
15
-
16
18
  it "prompts for authentication before outputting the logged in user" do
19
+ api_scenario "empty"
20
+
17
21
  ey(%w[login], :hide_err => true) do |input|
18
- input.puts("test@test.test")
19
- input.puts("test")
22
+ input.puts(scenario_email)
23
+ input.puts(scenario_password)
20
24
  end
21
25
 
22
26
  @out.should include("We need to fetch your API token; please log in.")
23
27
  @out.should include("Email:")
24
28
  @out.should include("Password:")
25
29
 
26
- @out.should include("User Name (test@test.test)")
30
+ @out.should include("User Name (#{scenario_email})")
27
31
  end
28
32
  end
29
33
  end
@@ -1,8 +1,10 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe "ey logout" do
4
+ given "integration"
5
+
4
6
  context "logged in" do
5
- given "integration"
7
+ before { login_scenario 'empty' }
6
8
 
7
9
  it "logs you out" do
8
10
  ey %w[logout]
@@ -12,9 +14,7 @@ describe "ey logout" do
12
14
  end
13
15
 
14
16
  context "not logged in" do
15
- given "integration without an eyrc file"
16
-
17
- it "prompts for authentication before outputting the logged in user" do
17
+ it "doesn't prompt for login before logging out" do
18
18
  ey %w[logout]
19
19
  @out.should_not include("API token removed:")
20
20
  @out.should include("Already logged out.")
data/spec/ey/logs_spec.rb CHANGED
@@ -4,17 +4,17 @@ describe "ey logs" do
4
4
  given "integration"
5
5
 
6
6
  it "prints logs returned by awsm" do
7
- api_scenario "one app, one environment"
8
- ey %w[logs -e giblets]
7
+ login_scenario "one app, one environment"
8
+ fast_ey %w[logs -e giblets]
9
9
  @out.should match(/MAIN LOG OUTPUT/)
10
10
  @out.should match(/CUSTOM LOG OUTPUT/)
11
- @err.should be_empty
11
+ @err.should == ''
12
12
  end
13
13
 
14
14
  it "complains when it can't infer the environment" do
15
- api_scenario "one app, many environments"
16
- ey %w[logs], :expect_failure => true
17
- @err.should =~ /repository url in this directory is ambiguous/i
15
+ login_scenario "one app, many environments"
16
+ fast_failing_ey %w[logs]
17
+ @err.should =~ /Multiple environments possible, please be more specific/i
18
18
  end
19
19
  end
20
20
 
@@ -17,7 +17,7 @@ describe "ey recipes apply" do
17
17
  include_examples "it takes an environment name and an account name"
18
18
 
19
19
  it "fails when given a bad option" do
20
- ey %w[web enable --lots --of --bogus --options], :expect_failure => true
20
+ fast_failing_ey %w[web enable --lots --of --bogus --options]
21
21
  @err.should include("Unknown switches")
22
22
  end
23
23
  end
@@ -29,7 +29,7 @@ describe "ey recipes download" do
29
29
  include_examples "it takes an environment name and an account name"
30
30
 
31
31
  it "fails when cookbooks/ already exists" do
32
- api_scenario "one app, one environment"
32
+ login_scenario "one app, one environment"
33
33
  Dir.mkdir("cookbooks")
34
34
  ey %w[recipes download], :expect_failure => true
35
35
  @err.should match(/cookbooks.*already exists/i)
@@ -5,7 +5,7 @@ describe "ey recipes upload" do
5
5
 
6
6
  define_git_repo('+cookbooks') do |git_dir|
7
7
  git_dir.join("cookbooks").mkdir
8
- File.open(git_dir.join("cookbooks/file"), "w"){|f| f << "boo" }
8
+ git_dir.join("cookbooks/file").open("w") {|f| f << "boo" }
9
9
  end
10
10
  use_git_repo('+cookbooks')
11
11
 
@@ -57,8 +57,8 @@ describe "ey recipes upload -f with a missing filenamen" do
57
57
  end
58
58
 
59
59
  it "errors with file not found" do
60
- api_scenario "one app, one environment"
61
- ey(%w[recipes upload --environment giblets -f recipes.tgz], :expect_failure => true)
60
+ login_scenario "one app, one environment"
61
+ fast_failing_ey(%w[recipes upload --environment giblets -f recipes.tgz])
62
62
  @err.should match(/Recipes file not found: recipes.tgz/i)
63
63
  end
64
64
  end
@@ -85,7 +85,7 @@ describe "ey recipes upload from a separate cookbooks directory" do
85
85
  use_git_repo "only cookbooks, no remotes"
86
86
 
87
87
  it "takes the environment specified by -e" do
88
- api_scenario "one app, one environment"
88
+ login_scenario "one app, one environment"
89
89
 
90
90
  ey %w[recipes upload -e giblets]
91
91
  @out.should =~ %r|Recipes in cookbooks/ uploaded successfully|
@@ -93,7 +93,7 @@ describe "ey recipes upload from a separate cookbooks directory" do
93
93
  end
94
94
 
95
95
  it "applies the recipes with --apply" do
96
- api_scenario "one app, one environment"
96
+ login_scenario "one app, one environment"
97
97
 
98
98
  ey %w[recipes upload -e giblets --apply]
99
99
  @out.should =~ %r|Recipes in cookbooks/ uploaded successfully|
@@ -116,7 +116,7 @@ describe "ey recipes upload from a separate cookbooks directory" do
116
116
  use_git_repo "only cookbooks, unrelated remotes"
117
117
 
118
118
  it "takes the environment specified by -e" do
119
- api_scenario "one app, one environment"
119
+ login_scenario "one app, one environment"
120
120
 
121
121
  ey %w[recipes upload -e giblets]
122
122
  @out.should =~ %r|Recipes in cookbooks/ uploaded successfully|
@@ -14,7 +14,7 @@ describe "ey rollback" do
14
14
 
15
15
  def verify_ran(scenario)
16
16
  @out.should match(/Rolling back.*#{scenario[:application]}.*#{scenario[:environment]}/)
17
- @err.should be_empty
17
+ @err.should == ''
18
18
  @ssh_commands.last.should match(/engineyard-serverside.*deploy rollback.*--app #{scenario[:application]}/)
19
19
  end
20
20
 
@@ -22,14 +22,14 @@ describe "ey rollback" do
22
22
  include_examples "it invokes engineyard-serverside"
23
23
 
24
24
  it "passes along the web server stack to engineyard-serverside" do
25
- api_scenario "one app, one environment"
25
+ login_scenario "one app, one environment"
26
26
  ey %w[rollback]
27
27
  @ssh_commands.last.should =~ /--stack nginx_mongrel/
28
28
  end
29
29
 
30
30
  context "--extra-deploy-hook-options" do
31
31
  before(:all) do
32
- api_scenario "one app, one environment"
32
+ login_scenario "one app, one environment"
33
33
  end
34
34
 
35
35
  def extra_deploy_hook_options
data/spec/ey/ssh_spec.rb CHANGED
@@ -30,8 +30,8 @@ shared_examples_for "running ey ssh for select role" do
30
30
  end
31
31
 
32
32
  it "runs the command on the right servers" do
33
- api_scenario "one app, one environment"
34
- run_ey(:ssh_command => "ls", :environment => 'giblets', :verbose => true)
33
+ login_scenario "one app, one environment"
34
+ ey command_to_run(:ssh_command => "ls", :environment => 'giblets', :verbose => true)
35
35
  @hosts.each do |host|
36
36
  @raw_ssh_commands.select do |command|
37
37
  command =~ /^ssh turkey@#{host}.+ ls$/
@@ -43,14 +43,14 @@ shared_examples_for "running ey ssh for select role" do
43
43
  end
44
44
 
45
45
  it "raises an error when there are no matching hosts" do
46
- api_scenario "one app, one environment, no instances"
47
- run_ey({:ssh_command => "ls", :environment => 'giblets', :verbose => true}, :expect_failure => true)
46
+ login_scenario "one app, one environment, no instances"
47
+ ey command_to_run({:ssh_command => "ls", :environment => 'giblets', :verbose => true}), :expect_failure => true
48
48
  end
49
49
 
50
50
  it "responds correctly when there is no command" do
51
51
  if @hosts.count != 1
52
- api_scenario "one app, one environment"
53
- run_ey({:environment => 'giblets', :verbose => true}, :expect_failure => true)
52
+ login_scenario "one app, one environment"
53
+ ey command_to_run({:environment => 'giblets', :verbose => true}), :expect_failure => true
54
54
  end
55
55
  end
56
56
  end
@@ -59,7 +59,7 @@ describe "ey ssh" do
59
59
  include_examples "running ey ssh"
60
60
 
61
61
  before(:all) do
62
- api_scenario "one app, many environments"
62
+ login_scenario "one app, many environments"
63
63
  end
64
64
 
65
65
  it "complains if it has no app master" do
@@ -127,8 +127,8 @@ describe "ey ssh with a command that fails" do
127
127
  end
128
128
 
129
129
  it "fails just like the ssh command fails" do
130
- api_scenario "one app, one environment"
131
- run_ey({:ssh_command => "ls", :environment => 'giblets', :verbose => true}, :expect_failure => true)
130
+ login_scenario "one app, one environment"
131
+ ey command_to_run({:ssh_command => "ls", :environment => 'giblets', :verbose => true}), :expect_failure => true
132
132
  end
133
133
  end
134
134
 
@@ -5,7 +5,7 @@ describe "ey environments" do
5
5
  given "integration"
6
6
 
7
7
  before(:all) do
8
- api_scenario "one app, many environments"
8
+ login_scenario "one app, many environments"
9
9
  end
10
10
 
11
11
  it "outputs the status of the deployment" do
@@ -15,7 +15,7 @@ describe "ey environments" do
15
15
  @out.should =~ /Ref:\s+HEAD/
16
16
  @out.should =~ /Resolved Ref:\s+HEAD/
17
17
  @out.should =~ /Deployed by:\s+User Name/
18
- @out.should =~ /Created at:/
18
+ @out.should =~ /Started at:/
19
19
  @out.should =~ /Finished at:/
20
20
  @out.should =~ /This deployment was successful/
21
21
  end
@@ -1,29 +1,30 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe "ey whoami" do
4
- context "logged in" do
5
- given "integration"
4
+ given "integration"
6
5
 
6
+ context "logged in" do
7
+ before { login_scenario 'empty' }
7
8
  it "outputs the currently logged in user" do
8
9
  ey %w[whoami]
9
- @out.should include("User Name (test@test.test)")
10
+ @out.should include("User Name (#{scenario_email})")
10
11
  end
11
12
  end
12
13
 
13
14
  context "not logged in" do
14
- given "integration without an eyrc file"
15
-
16
15
  it "prompts for authentication before outputting the logged in user" do
16
+ api_scenario 'empty'
17
+
17
18
  ey(%w[whoami], :hide_err => true) do |input|
18
- input.puts("test@test.test")
19
- input.puts("test")
19
+ input.puts(scenario_email)
20
+ input.puts(scenario_password)
20
21
  end
21
22
 
22
23
  @out.should include("We need to fetch your API token; please log in.")
23
24
  @out.should include("Email:")
24
25
  @out.should include("Password:")
25
26
 
26
- @out.should include("User Name (test@test.test)")
27
+ @out.should include("User Name (#{scenario_email})")
27
28
  end
28
29
  end
29
30
  end
data/spec/spec_helper.rb CHANGED
@@ -2,6 +2,11 @@ if self.class.const_defined?(:EY_ROOT)
2
2
  raise "don't require the spec helper twice!"
3
3
  end
4
4
 
5
+ if ENV['COVERAGE']
6
+ require 'simplecov'
7
+ SimpleCov.start
8
+ end
9
+
5
10
  EY_ROOT = File.expand_path("../..", __FILE__)
6
11
  require 'rubygems'
7
12
  require 'bundler/setup'
@@ -18,15 +23,23 @@ require 'json'
18
23
  $LOAD_PATH.unshift(File.join(EY_ROOT, "lib"))
19
24
  require 'engineyard'
20
25
 
26
+ require 'engineyard-cloud-client/test'
27
+
21
28
  # Spec stuff
22
29
  require 'rspec'
23
30
  require 'tmpdir'
24
31
  require 'yaml'
25
32
  require 'pp'
26
- support = Dir[File.join(EY_ROOT,'/spec/support/*.rb')]
27
- support.each{|helper| require helper }
33
+
34
+ Dir[File.join(EY_ROOT,'/spec/support/*.rb')].each do |helper|
35
+ require helper
36
+ end
28
37
 
29
38
  RSpec.configure do |config|
39
+ config.treat_symbols_as_metadata_keys_with_true_values = true
40
+ config.run_all_when_everything_filtered = true
41
+ config.filter_run :focus
42
+
30
43
  config.include SpecHelpers
31
44
  config.include SpecHelpers::IntegrationHelpers
32
45
 
@@ -49,8 +62,7 @@ RSpec.configure do |config|
49
62
  end
50
63
 
51
64
  config.before(:each) do
52
- clean_eyrc
53
- EY.instance_eval{ @config = nil }
65
+ EY::CloudClient.default_endpoint!
54
66
  end
55
67
  end
56
68
 
@@ -60,12 +72,12 @@ EY.define_git_repo("default") do |git_dir|
60
72
  system("git commit -m 'initial commit' >/dev/null 2>&1")
61
73
  end
62
74
 
63
- shared_examples_for "integration without an eyrc file" do
75
+ shared_examples_for "integration" do
64
76
  use_git_repo('default')
65
77
 
66
78
  before(:all) do
67
79
  FakeWeb.allow_net_connect = true
68
- ENV['CLOUD_URL'] = EY.fake_awsm
80
+ ENV['CLOUD_URL'] = EY::CloudClient::Test::FakeAwsm.uri
69
81
  end
70
82
 
71
83
  after(:all) do
@@ -73,12 +85,3 @@ shared_examples_for "integration without an eyrc file" do
73
85
  FakeWeb.allow_net_connect = false
74
86
  end
75
87
  end
76
-
77
- # Use this in conjunction with the 'ey' helper method
78
- shared_examples_for "integration" do
79
- given "integration without an eyrc file"
80
-
81
- before(:each) do
82
- write_eyrc({"api_token" => "f81a1706ddaeb148cfb6235ddecfc1cf"})
83
- end
84
- end