engineyard 1.4.29 → 1.7.0.pre2

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