engineyard 1.7.0.pre2 → 2.0.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,6 +3,7 @@ require 'engineyard/error'
3
3
  require 'engineyard/thor'
4
4
  require 'engineyard/deploy_config'
5
5
  require 'engineyard/serverside_runner'
6
+ require 'launchy'
6
7
 
7
8
  module EY
8
9
  class CLI < EY::Thor
@@ -146,7 +147,7 @@ module EY
146
147
  app_env = fetch_app_environment(options[:app], options[:environment], options[:account])
147
148
  deployment = app_env.last_deployment
148
149
  if deployment
149
- ui.say "# Status of last deployment of #{app_env.to_hierarchy_str}:"
150
+ ui.say "# Status of last deployment of #{app_env.hierarchy_name}:"
150
151
  ui.say "#"
151
152
  ui.show_deployment(deployment)
152
153
  ui.say "#"
@@ -177,10 +178,9 @@ module EY
177
178
  :desc => "Show environments matching environment name"
178
179
  def environments
179
180
  if options[:all] && options[:simple]
180
- # just put each env
181
- puts api.environments.map {|env| env.name}
181
+ ui.print_simple_envs api.environments
182
182
  elsif options[:all]
183
- ui.print_envs(api.apps, config.default_environment, options[:simple], config.endpoint)
183
+ ui.print_envs(api.apps)
184
184
  else
185
185
  remotes = nil
186
186
  if options[:app] == ''
@@ -203,14 +203,17 @@ module EY
203
203
 
204
204
  apps = resolver.matches.map { |app_env| app_env.app }.uniq
205
205
 
206
- if apps.size > 1
207
- message = "This git repo matches multiple Applications in EY Cloud:\n"
208
- apps.each { |app| message << "\t#{app.name}\n" }
209
- message << "The following environments contain those applications:\n\n"
210
- ui.warn(message)
206
+ if options[:simple]
207
+ if apps.size > 1
208
+ message = "# This app matches multiple Applications in EY Cloud:\n"
209
+ apps.each { |app| message << "#\t#{app.name}\n" }
210
+ message << "# The following environments contain those applications:\n\n"
211
+ ui.warn(message)
212
+ end
213
+ ui.print_simple_envs(apps.map{ |app| app.environments }.flatten)
214
+ else
215
+ ui.print_envs(apps, config.default_environment)
211
216
  end
212
-
213
- ui.print_envs(apps, config.default_environment, options[:simple], config.endpoint)
214
217
  end
215
218
  end
216
219
  map "envs" => :environments
@@ -263,7 +266,7 @@ module EY
263
266
  env_config = config.environment_config(app_env.environment_name)
264
267
  deploy_config = EY::DeployConfig.new(options, env_config, repo, ui)
265
268
 
266
- ui.info("Rolling back #{app_env.to_hierarchy_str}")
269
+ ui.info("Rolling back #{app_env.hierarchy_name}")
267
270
 
268
271
  runner = serverside_runner(app_env, deploy_config.verbose)
269
272
  runner.rollback do |args|
@@ -1,3 +1,5 @@
1
+ require 'tempfile'
2
+
1
3
  module EY
2
4
  class CLI
3
5
  class Recipes < EY::Thor
@@ -66,10 +68,25 @@ module EY
66
68
  environment.upload_recipes_at_path(filename)
67
69
  ui.say "Recipes file #{filename} uploaded successfully for #{environment.name}"
68
70
  else
69
- environment.tar_and_upload_recipes_in_cookbooks_dir
71
+ path = cookbooks_dir_archive_path
72
+ environment.upload_recipes_at_path(path)
70
73
  ui.say "Recipes in cookbooks/ uploaded successfully for #{environment.name}"
71
74
  end
72
75
  end
76
+
77
+ def cookbooks_dir_archive_path
78
+ unless FileTest.exist?("cookbooks")
79
+ raise EY::Error, "Could not find chef recipes. Please run from the root of your recipes repo."
80
+ end
81
+
82
+ recipes_file = Tempfile.new("recipes")
83
+ cmd = "tar czf '#{recipes_file.path}' cookbooks/"
84
+
85
+ unless system(cmd)
86
+ raise EY::Error, "Could not archive recipes.\nCommand `#{cmd}` exited with an error."
87
+ end
88
+ recipes_file.path
89
+ end
73
90
  end
74
91
 
75
92
  desc "download [--environment ENVIRONMENT]",
@@ -87,9 +104,20 @@ module EY
87
104
  :required => true, :default => '',
88
105
  :desc => "Name of the account in which the environment can be found"
89
106
  def download
107
+ if File.exist?('cookbooks')
108
+ raise EY::Error, "Cannot download recipes, cookbooks directory already exists."
109
+ end
110
+
90
111
  environment = fetch_environment(options[:environment], options[:account])
91
- environment.download_recipes
92
- ui.say "Recipes downloaded successfully for #{environment.name}"
112
+
113
+ recipes = environment.download_recipes
114
+ cmd = "tar xzf '#{recipes.path}' cookbooks"
115
+
116
+ if system(cmd)
117
+ ui.say "Recipes downloaded successfully for #{environment.name}"
118
+ else
119
+ raise EY::Error, "Could not unarchive recipes.\nCommand `#{cmd}` exited with an error."
120
+ end
93
121
  end
94
122
 
95
123
  end
@@ -127,30 +127,32 @@ module EY
127
127
  return ''
128
128
  end
129
129
 
130
- def print_envs(apps, default_env_name = nil, simple = false, endpoint = 'https://cloud.engineyard.com')
131
- if simple
132
- envs = apps.map{ |app| app.environments.to_a }
133
- puts envs.flatten.map{|env| env.name }.uniq
134
- else
135
- apps.each do |app|
136
- puts "#{app.account.name}/#{app.name}"
137
- if app.environments.any?
138
- app.environments.each do |env|
139
- short_name = env.shorten_name_for(app)
140
-
141
- icount = env.instances_count
142
- iname = (icount == 1) ? "instance" : "instances"
143
-
144
- default_text = env.name == default_env_name ? " [default]" : ""
145
-
146
- puts " #{short_name}#{default_text} (#{icount} #{iname})"
147
- end
148
- else
149
- puts " (This application is not in any environments; you can make one at #{endpoint})"
130
+ def print_simple_envs(envs)
131
+ puts envs.map{|env| env.name }.uniq.sort
132
+ end
133
+
134
+ def print_envs(apps, default_env_name = nil)
135
+ apps.sort_by {|app| "#{app.account.name}/#{app.name}" }.each do |app|
136
+ puts "#{app.account.name}/#{app.name}"
137
+ if app.environments.any?
138
+ app.environments.sort_by {|env| env.name }.each do |env|
139
+ icount = env.instances_count
140
+ iname = case icount
141
+ when 0 then "(stopped)"
142
+ when 1 then "1 instance"
143
+ else "#{icount} instances"
144
+ end
145
+
146
+ name = env.name == default_env_name ? "#{env.name} (default)" : env.name
147
+ framework_env = env.framework_env && "[#{env.framework_env.center(12)}]"
148
+
149
+ puts " #{name.ljust(30)} #{framework_env} #{iname}"
150
150
  end
151
-
152
- puts ""
151
+ else
152
+ puts " (No environments)"
153
153
  end
154
+
155
+ puts ""
154
156
  end
155
157
  end
156
158
 
@@ -1,5 +1,6 @@
1
1
  require 'uri'
2
2
  require 'yaml'
3
+ require 'pathname'
3
4
  require 'engineyard/error'
4
5
 
5
6
  module EY
@@ -60,8 +61,44 @@ module EY
60
61
  environments[environment_name] ||= {}
61
62
  environments[environment_name][key] = value
62
63
  ensure_path
64
+ comments = ey_yml_comments
63
65
  @path.open('w') do |f|
64
- YAML.dump(@config, f)
66
+ f.puts comments
67
+ f.puts YAML.dump(@config)
68
+ end
69
+ end
70
+
71
+ EY_YML_HINTS = <<-HINTS
72
+ # ey.yml supports many deploy configuration options when committed in an
73
+ # application's repository.
74
+ #
75
+ # Valid locations: REPO_ROOT/ey.yml or REPO_ROOT/config/ey.yml.
76
+ #
77
+ # Examples options:
78
+ #
79
+ # environments:
80
+ # YOUR_ENVIRONMENT_NAME: # All options pertain only to the named environment
81
+ # migrate: true # Default --migrate choice for ey deploy
82
+ # migration_command: 'rake migrate' # Default migrate command to run when migrations are enabled
83
+ # branch: default_deploy_branch # Branch/ref to be deployed by default during ey deploy
84
+ # bundle_without: development test # The string to pass to bundle install --without ''
85
+ # maintenance_on_migrate: true # Enable maintenance page during migrate action (use with caution) (default: true)
86
+ # maintenance_on_restart: false # Enable maintanence page during every deploy (default: false for unicorn & passenger)
87
+ # ignore_database_adapter_warning: false # Hide the warning shown when the Gemfile does not contain a recognized database adapter (mongodb for example)
88
+ # your_own_custom_key: 'any attribute you put in ey.yml is available in deploy hooks'
89
+ #
90
+ # Further information available here:
91
+ # https://support.cloud.engineyard.com/entries/20996661-customize-your-deployment-on-engine-yard-cloud
92
+ #
93
+ # NOTE: Please commit this file into your git repository.
94
+ #
95
+ HINTS
96
+
97
+ def ey_yml_comments
98
+ if @path.exist?
99
+ existing = @path.readlines.grep(/^#/).join("\n")
100
+ else
101
+ EY_YML_HINTS
65
102
  end
66
103
  end
67
104
 
@@ -70,8 +107,11 @@ module EY
70
107
  unless EY::Repo.exist?
71
108
  raise "Not in application directory. Unable to save configuration."
72
109
  end
73
- @path = Pathname.new('config/ey.yml')
74
- @path.dirname.mkpath
110
+ if Pathname.new('config').exist?
111
+ @path = Pathname.new('config/ey.yml')
112
+ else
113
+ @path = Pathname.new('ey.yml')
114
+ end
75
115
  @path
76
116
  end
77
117
 
@@ -101,12 +101,12 @@ module EY
101
101
  command_from_interaction
102
102
  end
103
103
  ui.say "#{env_config.path}: migrate settings saved for #{env_config.name}."
104
- ui.say "It's a good idea to git commit #{env_config.path} with these new changes."
104
+ ui.info "It's a good idea to git commit #{env_config.path} with these new changes."
105
105
  true
106
106
  rescue Timeout::Error
107
107
  @perform = nil
108
108
  @command = nil
109
- ui.error "Timeout when waiting for input. This is not a terminal."
109
+ ui.error "Timeout when waiting for input. Maybe this is not a terminal?"
110
110
  ui.error "ey deploy no longer migrates when no default is set in ey.yml."
111
111
  ui.error "Run interactively for step-by-step ey.yml migration setup."
112
112
  return false
@@ -1,3 +1,3 @@
1
1
  module EY
2
- VERSION = '1.7.0.pre2'
2
+ VERSION = '2.0.0.pre1'
3
3
  end
@@ -107,43 +107,57 @@ describe "ey deploy" do
107
107
  @ssh_commands.last.should =~ %r{/usr/local/ey_resin/ruby/bin/engineyard-serverside}
108
108
  end
109
109
 
110
- context "without migrate sepecified interactively reads migration command" do
111
- after { File.unlink 'config/ey.yml' }
110
+ context "without migrate sepecified, interactively reads migration command" do
111
+ def clean_ey_yml
112
+ File.unlink 'ey.yml' if File.exist?('ey.yml')
113
+ FileUtils.rm_r 'config' if FileTest.exist?('config')
114
+ end
115
+
116
+ before { clean_ey_yml }
117
+ after { clean_ey_yml }
112
118
 
113
- it "defaults to yes, and then rake db:migrate" do
114
- File.exist?('config/ey.yml').should be_false
119
+ it "defaults to yes, and then rake db:migrate (and installs to config/ey.yml if config/ exists already)" do
120
+ ey_yml = Pathname.new('config/ey.yml')
121
+ File.exist?('ey.yml').should be_false
122
+ ey_yml.dirname.mkpath
123
+ ey_yml.should_not be_exist
115
124
  ey(%w[deploy]) do |input|
116
125
  input.puts('')
117
126
  input.puts('')
118
127
  end
119
128
  @ssh_commands.last.should =~ /engineyard-serverside.*deploy/
120
129
  @ssh_commands.last.should =~ /--migrate 'rake db:migrate'/
121
- env_conf = read_yaml('config/ey.yml')['environments']['giblets']
130
+ File.exist?('ey.yml').should be_false
131
+ ey_yml.should be_exist
132
+ env_conf = read_yaml(ey_yml.to_s)['environments']['giblets']
122
133
  env_conf['migrate'].should == true
123
134
  env_conf['migration_command'].should == 'rake db:migrate'
124
135
  end
125
136
 
126
137
  it "accepts new commands" do
127
- File.exist?('config/ey.yml').should be_false
138
+ File.exist?('ey.yml').should be_false
139
+ FileTest.exist?('config').should be_false
128
140
  ey(%w[deploy], :hide_err => true) do |input|
129
141
  input.puts("y")
130
142
  input.puts("ruby migrate")
131
143
  end
132
144
  @ssh_commands.last.should =~ /engineyard-serverside.*deploy/
133
145
  @ssh_commands.last.should =~ /--migrate 'ruby migrate'/
134
- env_conf = read_yaml('config/ey.yml')['environments']['giblets']
146
+ File.exist?('ey.yml').should be_true
147
+ env_conf = read_yaml('ey.yml')['environments']['giblets']
135
148
  env_conf['migrate'].should == true
136
149
  env_conf['migration_command'].should == 'ruby migrate'
137
150
  end
138
151
 
139
152
  it "doesn't ask for the command if you say no" do
140
- File.exist?('config/ey.yml').should be_false
153
+ File.exist?('ey.yml').should be_false
141
154
  ey(%w[deploy], :hide_err => true) do |input|
142
155
  input.puts("no")
143
156
  end
144
157
  @ssh_commands.last.should =~ /engineyard-serverside.*deploy/
145
158
  @ssh_commands.last.should_not =~ /--migrate/
146
- read_yaml('config/ey.yml')['environments']['giblets']['migrate'].should == false
159
+ File.exist?('ey.yml').should be_true
160
+ read_yaml('ey.yml')['environments']['giblets']['migrate'].should == false
147
161
  end
148
162
  end
149
163
 
@@ -114,7 +114,6 @@ describe "ey environments with an ambiguous git repo" do
114
114
 
115
115
  it "lists environments from all apps using the git repo" do
116
116
  fast_ey %w[environments]
117
- @out.should =~ /git repo matches multiple/i
118
117
  @out.should include("giblets")
119
118
  @out.should include("keycollector_production")
120
119
  end
@@ -9,12 +9,15 @@ describe "ey environments" do
9
9
  end
10
10
 
11
11
  it "outputs the status of the deployment" do
12
+ ey %w[deploy -e giblets --ref HEAD --no-migrate]
12
13
  ey %w[status -e giblets]
13
14
  @out.should =~ /Application:\s+rails232app/
14
15
  @out.should =~ /Environment:\s+giblets/
15
16
  @out.should =~ /Ref:\s+HEAD/
16
- @out.should =~ /Resolved Ref:\s+HEAD/
17
- @out.should =~ /Deployed by:\s+User Name/
17
+ @out.should =~ /Resolved Ref:\s+resolved-HEAD/
18
+ @out.should =~ /Commit:\s+[a-f0-9]{40}/
19
+ @out.should =~ /Migrate:\s+false/
20
+ @out.should =~ /Deployed by:\s+One App Many Envs/
18
21
  @out.should =~ /Started at:/
19
22
  @out.should =~ /Finished at:/
20
23
  @out.should =~ /This deployment was successful/
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: engineyard
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.0.pre2
4
+ version: 2.0.0.pre1
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-05-18 00:00:00.000000000 Z
12
+ date: 2012-05-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rest-client
@@ -82,7 +82,7 @@ dependencies:
82
82
  requirements:
83
83
  - - '='
84
84
  - !ruby/object:Gem::Version
85
- version: 1.7.0.pre2
85
+ version: 2.0.0.pre1
86
86
  type: :runtime
87
87
  prerelease: false
88
88
  version_requirements: !ruby/object:Gem::Requirement
@@ -90,7 +90,7 @@ dependencies:
90
90
  requirements:
91
91
  - - '='
92
92
  - !ruby/object:Gem::Version
93
- version: 1.7.0.pre2
93
+ version: 2.0.0.pre1
94
94
  - !ruby/object:Gem::Dependency
95
95
  name: engineyard-cloud-client
96
96
  requirement: !ruby/object:Gem::Requirement
@@ -98,7 +98,7 @@ dependencies:
98
98
  requirements:
99
99
  - - ~>
100
100
  - !ruby/object:Gem::Version
101
- version: 0.1.2
101
+ version: 1.0.1
102
102
  type: :runtime
103
103
  prerelease: false
104
104
  version_requirements: !ruby/object:Gem::Requirement
@@ -106,7 +106,7 @@ dependencies:
106
106
  requirements:
107
107
  - - ~>
108
108
  - !ruby/object:Gem::Version
109
- version: 0.1.2
109
+ version: 1.0.1
110
110
  - !ruby/object:Gem::Dependency
111
111
  name: net-ssh
112
112
  requirement: !ruby/object:Gem::Requirement
@@ -128,17 +128,17 @@ dependencies:
128
128
  requirement: !ruby/object:Gem::Requirement
129
129
  none: false
130
130
  requirements:
131
- - - '='
131
+ - - ~>
132
132
  - !ruby/object:Gem::Version
133
- version: 2.0.5
133
+ version: '2.1'
134
134
  type: :runtime
135
135
  prerelease: false
136
136
  version_requirements: !ruby/object:Gem::Requirement
137
137
  none: false
138
138
  requirements:
139
- - - '='
139
+ - - ~>
140
140
  - !ruby/object:Gem::Version
141
- version: 2.0.5
141
+ version: '2.1'
142
142
  - !ruby/object:Gem::Dependency
143
143
  name: rspec
144
144
  requirement: !ruby/object:Gem::Requirement
@@ -308,7 +308,6 @@ extensions: []
308
308
  extra_rdoc_files: []
309
309
  files:
310
310
  - bin/ey
311
- - lib/engineyard/cli/#recipes.rb#
312
311
  - lib/engineyard/cli/api.rb
313
312
  - lib/engineyard/cli/recipes.rb
314
313
  - lib/engineyard/cli/ui.rb
@@ -413,7 +412,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
413
412
  version: 1.3.1
414
413
  requirements: []
415
414
  rubyforge_project:
416
- rubygems_version: 1.8.21
415
+ rubygems_version: 1.8.24
417
416
  signing_key:
418
417
  specification_version: 3
419
418
  summary: Command-line deployment for the Engine Yard cloud
@@ -1,32 +0,0 @@
1
- module EY
2
- class CLI
3
- class Recipes < EY::Thor
4
- X1gx1GGG desc "recipes apply [ENVIRONMENT]", <<-DESC
5
- Run uploaded chef recipes on specified environment.
6
-
7
- This is similar to '#{banner_base} rebuild' except Engine Yard's main
8
- configuration step is skipped.
9
- DESC
10
-
11
- def apply(name = nil)
12
- environment = fetch_environment(name)
13
- environment.run_custom_recipes
14
- EY.ui.say "Uploaded recipes started for #{environment.name}"
15
- end
16
-
17
- desc "recipes upload [ENVIRONMENT]", <<-DESC
18
- Upload custom chef recipes to specified environment.
19
-
20
- The current directory should contain a subdirectory named "cookbooks" to be
21
- uploaded.
22
- DESC
23
-
24
- def upload(name = nil)
25
- environment = fetch_environment(name)
26
- environment.upload_recipes
27
- EY.ui.say "Recipes uploaded successfully for #{environment.name}"
28
- end
29
- end
30
- end
31
-
32
- end