engineyard 2.0.0.rc1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -10,7 +10,7 @@ Note: Don't add engineyard to your application's Gemfile. The engineyard gem is
10
10
 
11
11
  == Login
12
12
 
13
- The first command you run will notice that you are not logged in and will ask you for your AppCloud email and password.
13
+ The first command you run will notice that you are not logged in and will ask you for your Engine Yard email and password.
14
14
 
15
15
  == Configuration
16
16
 
@@ -27,7 +27,6 @@ The ey.yml file allows options to be saved for each environment to which an appl
27
27
  bundle_without: test development mygroup # exclude groups on bundle install
28
28
  copy_exclude: # don't rsync the following dirs
29
29
  - .git
30
- verbose: true # always run verbose deploy (unless overriden on command line)
31
30
  maintenance_on_restart: false # show maintenance page during app restart (default: false except for glassfish and mongrel)
32
31
  maintenance_on_migrate: false # show maintenance page during migrations (default: true)
33
32
  precompile_assets: true # enables rails assets precompilation (default: inferred using app/assets and config/application.rb)
@@ -37,193 +36,199 @@ Many of the options in ey.yml will only work if the file is committed to your ap
37
36
 
38
37
  == Commands
39
38
 
40
- Command:
41
- ey deploy
39
+ === ey deploy
42
40
 
43
- Options:
44
- -r, [--ref=REF] [--branch=] [--tag=] # Git ref to deploy. May be a branch, a tag, or a SHA.
45
- -c, [--account=ACCOUNT] # Name of the account in which the environment can be found
46
- -a, [--app=APP] # Name of the application to deploy
47
- -e, [--environment=ENVIRONMENT] # Environment in which to deploy this application
48
- -m, [--migrate=MIGRATE] # Run migrations via [MIGRATE], defaults to 'rake db:migrate'; use --no-migrate to avoid running migrations
49
- -v, [--verbose] # Be verbose
50
- [--ignore-default-branch] # Force a deploy of the specified branch even if a default is set
51
- [--ignore-bad-master] # Force a deploy even if the master is in a bad state
52
- [--extra-deploy-hook-options key:val] # Additional options to be made available in deploy hooks (in the 'config' hash)
53
- # Add more keys as follows: --extra-deploy-hook-options key1:val1 key2:val2
41
+ This command must be run within the current directory containing the app to be
42
+ deployed. If ey.yml specifies a default branch then the ref parameter can be
43
+ omitted. Furthermore, if a default branch is specified but a different
44
+ command is supplied the deploy will fail unless --ignore-default-branch
45
+ is used.
54
46
 
47
+ If ey.yml does not specify a default migrate choice, you will be prompted to
48
+ specify a migration choice. A different command can later be specified via
49
+ --migrate "ruby do_migrations.rb". Migrations can also be skipped entirely
50
+ by using --no-migrate.
55
51
 
56
- Description:
57
- This command must be run within the current directory containing the app to be
58
- deployed. If ey.yml specifies a default branch then the ref parameter can be
59
- omitted. Furthermore, if a default branch is specified but a different
60
- command is supplied the deploy will fail unless --ignore-default-branch
61
- is used.
52
+ Options:
62
53
 
63
- If ey.yml does not specify a default migrate choice, you will be prompted to
64
- specify a migration choice. A different command can later be specified via
65
- --migrate "ruby do_migrations.rb". Migrations can also be skipped entirely
66
- by using --no-migrate.
54
+ -r, [--ref=REF] [--branch=] [--tag=] # Git ref to deploy. May be a branch, a tag, or a SHA.
55
+ -c, [--account=ACCOUNT] # Name of the account in which the environment can be found
56
+ -a, [--app=APP] # Name of the application to deploy
57
+ -e, [--environment=ENVIRONMENT] # Environment in which to deploy this application
58
+ -m, [--migrate=MIGRATE] # Run migrations via [MIGRATE], defaults to 'rake db:migrate'; use --no-migrate to avoid running migrations
59
+ -v, [--verbose] # Be verbose
60
+ [--ignore-default-branch] # Force a deploy of the specified branch even if a default is set
61
+ [--ignore-bad-master] # Force a deploy even if the master is in a bad state
62
+ [--extra-deploy-hook-options key:val] # Additional options to be made available in deploy hooks (in the 'config' hash)
63
+ # Add more keys as follows: --extra-deploy-hook-options key1:val1 key2:val2
67
64
 
68
- Command:
69
- ey environments
70
65
 
71
- Options:
72
- -c, [--account=ACCOUNT] # Name of the account in which the environment can be found
73
- -a, [--app=APP] # Name of the application containing the environments
74
- -e, [--environment=ENVIRONMENT] # Show only environments matching named environment
75
- -s, [--simple] # Print each environment name on its own on a new line
76
- -a, [--all] # Show all environments, not just ones associated with this application.
66
+ === ey status
77
67
 
78
- Description:
79
- By default, environments for this app are displayed. The --all option will display all environments, including those for this app.
68
+ Show the status of most recent deployment of the specified application and environment. This action only informational and will not change your application.
80
69
 
81
- Command:
82
- ey logs
70
+ Options:
83
71
 
84
- Options:
85
- -e, [--environment=ENVIRONMENT] # Environment with the interesting logs
86
- -c, [--account=ACCOUNT] # Name of the account in which the environment can be found
72
+ -c, [--account=ACCOUNT] # Name of the account in which the environment can be found
73
+ -a, [--app=APP] # Name of the application containing the environment
74
+ -e, [--environment=ENVIRONMENT] # Name of the environment with the desired deployment
87
75
 
88
- Description:
89
- Displays Engine Yard configuration logs for all servers in the environment. If recipes were uploaded to the environment & run, their logs will also be displayed beneath the
90
- main configuration logs.
76
+ === ey environments
91
77
 
92
- Command:
93
- ey rebuild
94
-
95
- Options:
96
- -e, [--environment=ENVIRONMENT] # Environment to rebuild
97
- -c, [--account=ACCOUNT] # Name of the account in which the environment can be found
78
+ By default, environments for this app are displayed. The --all option will display all environments, including those for this app.
98
79
 
99
- Description:
100
- Engine Yard's main configuration run occurs on all servers. Mainly used to fix failed configuration of new or existing servers, or to update servers to latest Engine Yard stack
101
- (e.g. to apply an Engine Yard supplied security patch).
80
+ Options:
102
81
 
103
- Note that uploaded recipes are also run after the main configuration run has successfully completed.
82
+ -c, [--account=ACCOUNT] # Name of the account in which the environment can be found
83
+ -a, [--app=APP] # Name of the application containing the environments
84
+ -e, [--environment=ENVIRONMENT] # Show only environments matching named environment
85
+ -s, [--simple] # Print each environment name on its own on a new line
86
+ -a, [--all] # Show all environments, not just ones associated with this application.
104
87
 
105
- Command:
106
- ey rollback
107
88
 
108
- Options:
109
- -v, [--verbose] # Be verbose
110
- -a, [--app=APP] # Name of the application to roll back
111
- -e, [--environment=ENVIRONMENT] # Environment in which to roll back the application
112
- -c, [--account=ACCOUNT] # Name of the account in which the environment can be found
89
+ === ey logs
113
90
 
114
- Description:
115
- Uses code from previous deploy in the "/data/APP_NAME/releases" directory on remote server(s) to restart application servers.
91
+ Displays Engine Yard configuration logs for all servers in the environment. If recipes were uploaded to the environment & run, their logs will also be displayed beneath the main configuration logs.
116
92
 
117
- Command:
118
- ey recipes apply
93
+ Options:
119
94
 
120
- Options:
121
- -e, [--environment=ENVIRONMENT] # Environment in which to apply recipes
122
- -c, [--account=ACCOUNT] # Name of the account in which the environment can be found
95
+ -e, [--environment=ENVIRONMENT] # Environment with the interesting logs
96
+ -c, [--account=ACCOUNT] # Name of the account in which the environment can be found
123
97
 
124
- Description:
125
- This is similar to 'ey rebuild' except Engine Yard's main configuration step is skipped.
98
+ === ey rebuild
126
99
 
127
- Command:
128
- ey recipes upload
100
+ Engine Yard's main configuration run occurs on all servers. Mainly used to fix failed configuration of new or existing servers, or to update servers to latest Engine Yard stack
101
+ (e.g. to apply an Engine Yard supplied security patch).
129
102
 
130
- Options:
131
- -e, [--environment=ENVIRONMENT] # Environment that will receive the recipes
132
- -c, [--account=ACCOUNT] # Name of the account in which the environment can be found
103
+ Note that uploaded recipes are also run after the main configuration run has successfully completed.
133
104
 
134
- Description:
135
- The current directory should contain a subdirectory named "cookbooks" to be uploaded.
105
+ Options:
136
106
 
137
- Command:
138
- ey recipes download
107
+ -e, [--environment=ENVIRONMENT] # Environment to rebuild
108
+ -c, [--account=ACCOUNT] # Name of the account in which the environment can be found
139
109
 
140
- Options:
141
- -e, [--environment=ENVIRONMENT] # Environment for which to download the recipes
142
- -c, [--account=ACCOUNT] # Name of the account in which the environment can be found
110
+ === ey rollback
143
111
 
144
- Description:
145
- The recipes will be unpacked into a directory called "cookbooks" in the current directory.
112
+ Uses code from previous deploy in the "/data/APP_NAME/releases" directory on remote server(s) to restart application servers.
146
113
 
147
- If the cookbooks directory already exists, an error will be raised.
114
+ Options:
148
115
 
149
- Command:
150
- ey web enable
116
+ -v, [--verbose] # Be verbose
117
+ -a, [--app=APP] # Name of the application to roll back
118
+ -e, [--environment=ENVIRONMENT] # Environment in which to roll back the application
119
+ -c, [--account=ACCOUNT] # Name of the account in which the environment can be found
151
120
 
152
- Options:
153
- -v, [--verbose] # Be verbose
154
- -a, [--app=APP] # Name of the application whose maintenance page will be removed
155
- -e, [--environment=ENVIRONMENT] # Environment on which to take down the maintenance page
156
- -c, [--account=ACCOUNT] # Name of the account in which the environment can be found
121
+ === ey recipes apply
157
122
 
158
- Remove the maintenance page for this application in the given environment.
123
+ This is similar to 'ey rebuild' except Engine Yard's main configuration step is skipped.
159
124
 
160
- Command:
161
- ey web disable
125
+ Options:
162
126
 
163
- Options:
164
- -v, [--verbose] # Be verbose
165
- -a, [--app=APP] # Name of the application whose maintenance page will be put up
166
- -e, [--environment=ENVIRONMENT] # Environment on which to put up the maintenance page
167
- -c, [--account=ACCOUNT] # Name of the account in which the environment can be found
127
+ -e, [--environment=ENVIRONMENT] # Environment in which to apply recipes
128
+ -c, [--account=ACCOUNT] # Name of the account in which the environment can be found
168
129
 
169
- Description:
170
- The maintenance page is taken from the app currently being deployed. This means that you can customize maintenance pages to tell users the reason for downtime on every
171
- particular deploy.
130
+ === ey recipes upload
172
131
 
173
- Maintenance pages searched for in order of decreasing priority:
174
- * public/maintenance.html.custom
175
- * public/maintenance.html.tmp
176
- * public/maintenance.html
177
- * public/system/maintenance.html.default
132
+ The current directory should contain a subdirectory named "cookbooks" to be uploaded.
178
133
 
179
- Command:
180
- ey ssh
134
+ Options:
181
135
 
182
- Options:
183
- [--utilities=one two three] # Run command on the utility servers with the given names. If no names are given, run on all utility servers.
184
- [--app-servers] # Run command on all application servers
185
- [--db-servers] # Run command on the database servers
186
- [--db-master] # Run command on the master database server
187
- -a, [--all] # Run command on all servers
188
- [--db-slaves] # Run command on the slave database servers
189
- -e, [--environment=ENVIRONMENT] # Environment to ssh into
190
- -c, [--account=ACCOUNT] # Name of the account in which the environment can be found
136
+ -e, [--environment=ENVIRONMENT] # Environment that will receive the recipes
137
+ -c, [--account=ACCOUNT] # Name of the account in which the environment can be found
138
+ [--apply] # Apply the recipes (same as above) immediately after uploading
139
+ -f, [--file=FILE] # Specify a gzipped tar file (.tgz) for upload instead of cookbooks/ directory
191
140
 
192
- Description:
193
- If a command is supplied, it will be run, otherwise a session will be opened. The application master is used for environments with clusters. Option --all requires a command to
194
- be supplied and runs it on all servers.
141
+ === ey recipes download
195
142
 
196
- Note: this command is a bit picky about its ordering. To run a command with arguments on all servers, like "rm -f /some/file", you need to order it like so:
143
+ The recipes will be unpacked into a directory called "cookbooks" in the current directory.
197
144
 
198
- $ ey ssh "rm -f /some/file" -e my-environment --all
145
+ If the cookbooks directory already exists, an error will be raised.
199
146
 
200
- Command:
201
- ey launch
147
+ Options:
202
148
 
203
- Options:
204
- -e, [--environment=ENVIRONMENT] # Environment to ssh into
205
- -c, [--account=ACCOUNT] # Name of the account in which the environment can be found
149
+ -e, [--environment=ENVIRONMENT] # Environment for which to download the recipes
150
+ -c, [--account=ACCOUNT] # Name of the account in which the environment can be found
206
151
 
207
- Description:
208
- Open the application in a browser.
152
+ === ey web enable
209
153
 
210
- Command:
211
- ey whoami
154
+ Remove the maintenance page for this application in the given environment.
212
155
 
213
- Description:
214
- Who am I logged in as?
156
+ Options:
215
157
 
216
- Command:
217
- ey login
158
+ -v, [--verbose] # Be verbose
159
+ -a, [--app=APP] # Name of the application whose maintenance page will be removed
160
+ -e, [--environment=ENVIRONMENT] # Environment on which to take down the maintenance page
161
+ -c, [--account=ACCOUNT] # Name of the account in which the environment can be found
218
162
 
219
- Description:
220
- Log in and verify access to EY Cloud. Use logout first if you need to switch user accounts.
163
+ === ey web disable
221
164
 
222
- Command:
223
- ey logout
165
+ The maintenance page is taken from the app currently being deployed. This means that you can customize maintenance pages to tell users the reason for downtime on every particular deploy.
224
166
 
225
- Description:
226
- Remove the current API key from ~/.eyrc or env variable $EYRC
167
+ Maintenance pages searched for in order of decreasing priority:
168
+ * public/maintenance.html.custom
169
+ * public/maintenance.html.tmp
170
+ * public/maintenance.html
171
+ * public/system/maintenance.html.default
172
+
173
+ Options:
174
+
175
+ -v, [--verbose] # Be verbose
176
+ -a, [--app=APP] # Name of the application whose maintenance page will be put up
177
+ -e, [--environment=ENVIRONMENT] # Environment on which to put up the maintenance page
178
+ -c, [--account=ACCOUNT] # Name of the account in which the environment can be found
179
+
180
+
181
+ === ey web restart
182
+
183
+ Restarts the application servers for the given application. Enables maintenance pages if it would be enabled during a normal deploy. Respects the maintenance_on_restart ey.yml configuration.
184
+
185
+ Options:
186
+
187
+ -v, [--verbose] # Be verbose
188
+ -a, [--app=APP] # Name of the application to restart
189
+ -e, [--environment=ENVIRONMENT] # Name of the environment to restart
190
+ -c, [--account=ACCOUNT] # Name of the account in which the app and environment can be found
191
+
192
+ === ey ssh
193
+
194
+ If a command is supplied, it will be run, otherwise a session will be opened. The application master is used for environments with clusters. Option --all requires a command to be supplied and runs it on all servers.
195
+
196
+ Note: this command is a bit picky about its ordering. To run a command with arguments on all servers, like "rm -f /some/file", you need to order it like so:
197
+
198
+ $ ey ssh "rm -f /some/file" -e my-environment --all
199
+
200
+ Options:
201
+
202
+ [--utilities=one two three] # Run command on the utility servers with the given names. If no names are given, run on all utility servers.
203
+ [--app-servers] # Run command on all application servers
204
+ [--db-servers] # Run command on the database servers
205
+ [--db-master] # Run command on the master database server
206
+ -A, [--all] # Run command on all servers
207
+ [--db-slaves] # Run command on the slave database servers
208
+ -e, [--environment=ENVIRONMENT] # Name of the environment to ssh into
209
+ -c, [--account=ACCOUNT] # Name of the account in which the environment can be found
210
+
211
+ === ey launch
212
+
213
+ Open the application in a browser.
214
+
215
+ Options:
216
+
217
+ -c, [--account=ACCOUNT] # Name of the account in which the environment can be found
218
+ -a, [--app=APP] # Name of the application to launch
219
+ -e, [--environment=ENVIRONMENT] # Name of the environment for the application
220
+
221
+ === ey whoami
222
+
223
+ Who am I logged in as? Prints the name and email of the current logged in user.
224
+
225
+ === ey login
226
+
227
+ Log in and verify access to EY Cloud. Use logout first if you need to switch user accounts.
228
+
229
+ === ey logout
230
+
231
+ Remove the current API key from ~/.eyrc or env variable $EYRC
227
232
 
228
233
 
229
234
  == API Client
@@ -234,15 +239,16 @@ See https://github.com/engineyard/engineyard-cloud-client for the API client lib
234
239
 
235
240
  The API commands will print internal information if $DEBUG is set:
236
241
 
237
- DEBUG=1 ey environments --all
238
- Token YOURTOKEN
239
- Request GET https://cloud.engineyard.com/api/v2/apps
240
- Params {}
241
- Response
242
- {"apps"=>
243
- [{"environments"=>[],
244
- "name"=>"myapp",
245
- "repository_uri"=>"git@github.com:myaccount/myapp.git",
246
- "app_type_id"=>"rails3",
247
- "account"=>{"name"=>"myaccount", "id"=>1234},
248
- "id"=>12345}]}
242
+ $ DEBUG=1 ey environments --all
243
+ GET https://cloud.engineyard.com/api/v2/apps
244
+ Params {"no_instances"=>"true"}
245
+ Headers {"User-Agent"=>"EngineYard/2.0.0 EngineYardCloudClient/1.0.5",
246
+ "Accept"=>"application/json",
247
+ "X-EY-Cloud-Token"=>"YOURTOKEN"}
248
+ Response {"apps"=>
249
+ [{"environments"=>[],
250
+ "name"=>"myapp",
251
+ "repository_uri"=>"git@github.com:myaccount/myapp.git",
252
+ "app_type_id"=>"rails3",
253
+ "account"=>{"name"=>"myaccount", "id"=>1234},
254
+ "id"=>12345}]}
@@ -107,8 +107,8 @@ module EY
107
107
  deployment.successful = runner.call(out, err)
108
108
  rescue Interrupt
109
109
  err << "Interrupted. Deployment halted.\n"
110
- ui.warn "Recording canceled deployment in EY Cloud..."
111
- ui.warn "WARNING: Interrupting again may result in a never-finished deployment in the deployment history on EY Cloud."
110
+ ui.warn "Recording canceled deployment in Engine Yard Cloud..."
111
+ ui.warn "WARNING: Interrupting again may result in a never-finished deployment in the deployment history on Engine Yard Cloud."
112
112
  raise
113
113
  rescue StandardError => e
114
114
  deployment.err << "Error encountered during deploy.\n#{e.class} #{e}\n"
@@ -118,11 +118,11 @@ module EY
118
118
  deployment.finished
119
119
 
120
120
  if deployment.successful?
121
- ui.info "Successful deployment recorded on EY Cloud"
121
+ ui.info "Successful deployment recorded on Engine Yard Cloud"
122
122
  ui.info "Deploy complete"
123
123
  ui.info "Now you can run `ey launch' to open the application in a browser."
124
124
  else
125
- ui.info "Failed deployment recorded on EY Cloud"
125
+ ui.info "Failed deployment recorded on Engine Yard Cloud"
126
126
  raise EY::Error, "Deploy failed"
127
127
  end
128
128
  end
@@ -204,7 +204,7 @@ module EY
204
204
 
205
205
  if options[:simple]
206
206
  if apps.size > 1
207
- message = "# This app matches multiple Applications in EY Cloud:\n"
207
+ message = "# This app matches multiple Applications in Engine Yard Cloud:\n"
208
208
  apps.each { |app| message << "#\t#{app.name}\n" }
209
209
  message << "# The following environments contain those applications:\n\n"
210
210
  ui.warn(message)
@@ -296,7 +296,7 @@ module EY
296
296
  method_option :account, :type => :string, :aliases => %w(-c),
297
297
  :required => true, :default => '',
298
298
  :desc => "Name of the account in which the environment can be found"
299
- method_option :all, :type => :boolean, :aliases => %(-a),
299
+ method_option :all, :type => :boolean, :aliases => %(-A),
300
300
  :desc => "Run command on all servers"
301
301
  method_option :app_servers, :type => :boolean,
302
302
  :desc => "Run command on all application servers"
@@ -457,7 +457,19 @@ module EY
457
457
  ui.say "#{current_user.name} (#{current_user.email})"
458
458
  end
459
459
 
460
- desc "login", "Log in and verify access to EY Cloud."
460
+ desc "login", "Log in and verify access to Engine Yard Cloud."
461
+ long_desc <<-DESC
462
+ You may run this command to log in to EY Cloud without performing
463
+ any other action.
464
+
465
+ Once you are logged in, a file will be stored at ~/.eyrc with your
466
+ API token. You may override the location of this file using the
467
+ $EYRC environment variable.
468
+
469
+ Instead of logging in, you may specify a token on the command line
470
+ with --api-token or using the $ENGINEYARD_API_TOKEN environment
471
+ variable.
472
+ DESC
461
473
  def login
462
474
  whoami
463
475
  end
@@ -5,71 +5,94 @@ require 'engineyard/eyrc'
5
5
  module EY
6
6
  class CLI
7
7
  class API
8
- def self.authenticate(ui)
9
- ui.info("We need to fetch your API token; please log in.")
10
- begin
11
- email = ui.ask("Email: ")
12
- password = ui.ask("Password: ", true)
13
- token = EY::CloudClient.authenticate(email, password, ui)
14
- EY::EYRC.load.api_token = token
15
- token
16
- rescue EY::CloudClient::InvalidCredentials
17
- ui.warn "Invalid username or password; please try again."
18
- retry
19
- end
20
- end
8
+ USER_AGENT = "EngineYard/#{EY::VERSION}"
21
9
 
22
10
  attr_reader :token
23
11
 
24
12
  def initialize(endpoint, ui, token = nil)
13
+ @client = EY::CloudClient.new(:endpoint => endpoint, :output => ui.out, :user_agent => USER_AGENT)
25
14
  @ui = ui
26
- EY::CloudClient.endpoint = endpoint
27
-
28
- # If the token is specified, we don't ask for authentication when
29
- # the token is reject, we just exit.
30
- if @token = token
31
- @specified = true
32
- @source = 'token from --api-token'
33
- elsif @token = ENV['ENGINEYARD_API_TOKEN']
34
- @specified = true
35
- @source = 'token from $ENGINEYARD_API_TOKEN'
36
- elsif @token = EY::EYRC.load.api_token
37
- @specified = false
38
- @source = "api_token in #{EY::EYRC.load.path}"
39
- elsif @token = self.class.authenticate(ui)
40
- @specified = false
41
- @source = 'credentials'
42
- else
43
- raise EY::Error, "Sorry, we couldn't get your API token."
44
- end
45
-
46
- @api = EY::CloudClient.new(@token, @ui)
15
+ @eyrc = EY::EYRC.load
16
+ token_from('--api-token') { token } ||
17
+ token_from('$ENGINEYARD_API_TOKEN') { ENV['ENGINEYARD_API_TOKEN'] } ||
18
+ token_from(@eyrc.path, false) { @eyrc.api_token } ||
19
+ authenticate ||
20
+ token_not_loaded
47
21
  end
48
22
 
49
23
  def respond_to?(*a)
50
- super or @api.respond_to?(*a)
24
+ super or @client.respond_to?(*a)
51
25
  end
52
26
 
53
27
  protected
54
28
 
55
29
  def method_missing(meth, *args, &block)
56
- if @api.respond_to?(meth)
57
- @api.send(meth, *args, &block)
30
+ if @client.respond_to?(meth)
31
+ with_reauthentication { @client.send(meth, *args, &block) }
58
32
  else
59
33
  super
60
34
  end
61
- rescue EY::CloudClient::InvalidCredentials
62
- if @specified
63
- ui.error "Authentication failed: Invalid #{@source}."
64
- exit(255)
35
+ end
36
+
37
+ def with_reauthentication
38
+ begin
39
+ yield
40
+ rescue EY::CloudClient::InvalidCredentials
41
+ if @specified || !@ui.interactive?
42
+ # If the token is specified, we raise immediately if it is rejected.
43
+ raise EY::Error, "Authentication failed: Invalid #{@source}."
44
+ else
45
+ @ui.warn "Authentication failed: Invalid #{@source}."
46
+ authenticate
47
+ retry
48
+ end
49
+ end
50
+ end
51
+
52
+ # Get the token from the provided block, saving it if it works.
53
+ # Specified will help us know what to do if loading the token fails.
54
+ # Returns true if it gets a token.
55
+ # Returns false if there is no token.
56
+ def token_from(source, specified = true)
57
+ token = yield
58
+ if token
59
+ @client.token = token
60
+ @specified = specified
61
+ @source = "token from #{source}"
62
+ @token = token
63
+ true
65
64
  else
66
- ui.warn "Authentication failed: Invalid #{@source}. Retrying..."
67
- @token = self.class.authenticate(@ui)
68
- @api = EY::CloudClient.new(@token, @ui)
65
+ false
66
+ end
67
+ end
68
+
69
+ # Load the token from EY Cloud if interactive and
70
+ # token wasn't explicitly specified previously.
71
+ def authenticate
72
+ if @specified
73
+ return false
74
+ end
75
+
76
+ @source = "credentials"
77
+ @specified = false
78
+
79
+ @ui.info("We need to fetch your API token; please log in.")
80
+ begin
81
+ email = @ui.ask("Email: ")
82
+ passwd = @ui.ask("Password: ", true)
83
+ @token = @client.authenticate!(email, passwd)
84
+ @eyrc.api_token = @token
85
+ true
86
+ rescue EY::CloudClient::InvalidCredentials
87
+ @ui.warn "Authentication failed. Please try again."
69
88
  retry
70
89
  end
71
90
  end
72
91
 
92
+ # Occurs when all avenues for getting the token are exhausted.
93
+ def token_not_loaded
94
+ raise EY::Error, "Sorry, we couldn't get your API token."
95
+ end
73
96
  end
74
97
  end
75
98
  end
@@ -28,7 +28,7 @@ module EY
28
28
  "Upload custom chef recipes to specified environment so they can be applied."
29
29
  long_desc <<-DESC
30
30
  Make an archive of the "cookbooks/" subdirectory in your current working
31
- directory and upload it to EY Cloud's recipe storage.
31
+ directory and upload it to Engine Yard Cloud's recipe storage.
32
32
 
33
33
  Alternatively, specify a .tgz of a cookbooks/ directory yourself as follows:
34
34
 
@@ -49,6 +49,37 @@ module EY
49
49
  ui.info "Putting up maintenance page for '#{app_env.app.name}' in '#{app_env.environment.name}'"
50
50
  serverside_runner(app_env, options[:verbose]).put_up_maintenance_page.call(ui.out, ui.err)
51
51
  end
52
+
53
+ desc "restart [--environment ENVIRONMENT]",
54
+ "Restart the application servers without deploying."
55
+ long_desc <<-DESC
56
+ Restarts the application servers (e.g. Passenger, Unicorn, etc).
57
+
58
+ Respects the maintenance_on_restart settings in the application's ey.yml.
59
+
60
+ Note: Uses the version of the ey.yml currently checked out on the servers.
61
+ DESC
62
+ method_option :environment, :type => :string, :aliases => %w(-e),
63
+ :required => true, :default => false,
64
+ :desc => "Environment in which to deploy this application"
65
+ method_option :app, :type => :string, :aliases => %w(-a),
66
+ :required => true, :default => '',
67
+ :desc => "Name of the application to deploy"
68
+ method_option :account, :type => :string, :aliases => %w(-c),
69
+ :required => true, :default => '',
70
+ :desc => "Name of the account in which the environment can be found"
71
+ method_option :verbose, :type => :boolean, :aliases => %w(-v),
72
+ :desc => "Be verbose"
73
+ def restart
74
+ app_env = fetch_app_environment(options[:app], options[:environment], options[:account])
75
+ ui.info "Restarting servers on #{app_env.hierarchy_name}"
76
+ if serverside_runner(app_env, options[:verbose]).restart.call(ui.out, ui.err)
77
+ ui.info "Restart complete"
78
+ else
79
+ raise EY::Error, "Restart failed"
80
+ end
81
+ end
82
+
52
83
  end
53
84
  end
54
85
  end
@@ -36,8 +36,8 @@ class EY
36
36
  deployment.successful = runner.call(out, err)
37
37
  rescue Interrupt
38
38
  err << "Interrupted. Deployment halted.\n"
39
- ui.warn "Recording canceled deployment in EY Cloud..."
40
- ui.warn "WARNING: Interrupting again may result in a never-finished deployment in the deployment history on EY Cloud."
39
+ ui.warn "Recording canceled deployment in Engine Yard Cloud..."
40
+ ui.warn "WARNING: Interrupting again may result in a never-finished deployment in the deployment history on Engine Yard Cloud."
41
41
  raise
42
42
  rescue StandardError => e
43
43
  deployment.err << "Error encountered during deploy.\n#{e.class} #{e}\n"
@@ -47,11 +47,11 @@ class EY
47
47
  deployment.finished
48
48
 
49
49
  if deployment.successful?
50
- ui.info "Successful deployment recorded on EY Cloud"
50
+ ui.info "Successful deployment recorded on Engine Yard Cloud"
51
51
  ui.info "Deploy complete"
52
52
  ui.info "Now you can run `ey launch' to open the application in a browser."
53
53
  else
54
- ui.info "Failed deployment recorded on EY Cloud"
54
+ ui.info "Failed deployment recorded on Engine Yard Cloud"
55
55
  raise EY::Error, "Deploy failed"
56
56
  end
57
57
  end
@@ -96,7 +96,7 @@ module EY
96
96
 
97
97
  def ey_yml_comments
98
98
  if @path.exist?
99
- existing = @path.readlines.grep(/^#/).join("\n")
99
+ existing = @path.readlines.grep(/^#/).map {|line| line.strip }.join("\n")
100
100
  else
101
101
  EY_YML_HINTS
102
102
  end
@@ -90,18 +90,15 @@ module EY
90
90
  end
91
91
 
92
92
  def perform_from_interaction
93
- ui.warn "**********************************************************************"
94
- ui.warn "No default migrate choice for environment: #{env_config.name}"
95
- ui.warn "Migrate can be toggled per-deploy using --migrate or --no-migrate."
96
- ui.warn "Let's set a default migration choice."
97
- ui.warn "**********************************************************************"
98
- @perform = ui.agree('Migrate every deploy by default? ', true)
93
+ ui.warn "Please choose a default migration behavior for this environment."
94
+ @perform = ui.agree("Run migrations by default on #{env_config.name}? ", true)
99
95
  env_config.migrate = @perform
100
96
  if @perform
101
97
  command_from_interaction
102
98
  end
103
99
  ui.say "#{env_config.path}: migrate settings saved for #{env_config.name}."
104
- ui.info "It's a good idea to git commit #{env_config.path} with these new changes."
100
+ ui.say "You can override this default with --migrate or --no-migrate."
101
+ ui.info "Please git commit #{env_config.path} with these new changes."
105
102
  true
106
103
  rescue Timeout::Error
107
104
  @perform = nil
@@ -2,14 +2,14 @@ module EY
2
2
  class EYRC
3
3
  attr_reader :path
4
4
 
5
- DEFAULT_PATH = "~/.eyrc"
5
+ DEFAULT_PATH = "#{ENV['HOME']}/.eyrc"
6
6
 
7
7
  def self.load
8
8
  new(ENV['EYRC'] || DEFAULT_PATH)
9
9
  end
10
10
 
11
11
  def initialize(path)
12
- self.path = path
12
+ @path = Pathname.new(path).expand_path
13
13
  end
14
14
 
15
15
  def exist?
@@ -30,10 +30,6 @@ module EY
30
30
 
31
31
  private
32
32
 
33
- def path=(p)
34
- @path = Pathname.new(p).expand_path
35
- end
36
-
37
33
  def [](key)
38
34
  read_data[key.to_s]
39
35
  end
@@ -10,6 +10,7 @@ module EY
10
10
  @username = environment.username
11
11
  @hostname = bridge
12
12
  @command = nil
13
+ @acc_env_name = "#{app.account.name}/#{environment.name}"
13
14
  end
14
15
 
15
16
  def deploy(&block)
@@ -22,6 +23,11 @@ module EY
22
23
  self
23
24
  end
24
25
 
26
+ def restart(&block)
27
+ @command = @adapter.restart(&block)
28
+ self
29
+ end
30
+
25
31
  def put_up_maintenance_page(&block)
26
32
  @command = @adapter.enable_maintenance(&block)
27
33
  self
@@ -89,16 +95,30 @@ module EY
89
95
  begin
90
96
  ssh(cmd, @hostname, @username, out, err)
91
97
  rescue Net::SSH::AuthenticationFailed
92
- raise EY::Error, "Authentication Failed: Please add your environment's ssh key with: ssh-add path/to/key"
98
+ raise EY::Error, <<-ERROR
99
+ Authentication Failed. Things to fix:
100
+ 1. Add your SSH key to your local SSH agent with `ssh-add path/to/key`.
101
+ 2. Add your SSH key to #{@acc_env_name} on Engine Yard Cloud and apply the changes.
102
+ (https://support.cloud.engineyard.com/entries/20996846-set-up-ssh-keys)
103
+ ERROR
104
+ end
105
+ end
106
+ end
107
+
108
+ def net_ssh_options
109
+ level = :fatal # default in Net::SSH
110
+ if debug = ENV["DEBUG"]
111
+ level = :info
112
+ if %w[debug info warn error fatal].include?(debug.downcase)
113
+ level = debug.downcase.to_sym
93
114
  end
94
115
  end
116
+ {:paranoid => false, :verbose => level}
95
117
  end
96
118
 
97
119
  def ssh(cmd, hostname, username, out, err)
98
120
  exit_code = 1
99
- options_for_ssh = {:paranoid => false}
100
- options_for_ssh[:verbose] = ENV["DEBUG"].downcase.to_sym if ENV["DEBUG"]
101
- Net::SSH.start(hostname, username, options_for_ssh) do |net_ssh|
121
+ Net::SSH.start(hostname, username, net_ssh_options) do |net_ssh|
102
122
  net_ssh.open_channel do |channel|
103
123
  channel.exec cmd do |_, success|
104
124
  unless success
@@ -40,7 +40,7 @@ module EY
40
40
  end
41
41
 
42
42
  def fetch_environment(environment_name, account_name)
43
- ui.info "Loading application data from EY Cloud..."
43
+ ui.info "Loading application data from Engine Yard Cloud..."
44
44
 
45
45
  environment_name ||= use_default_environment
46
46
  remotes = repo.remotes if in_repo?
@@ -72,7 +72,7 @@ module EY
72
72
  end
73
73
 
74
74
  def fetch_app_environment(app_name, environment_name, account_name)
75
- ui.info "Loading application data from EY Cloud..."
75
+ ui.info "Loading application data from Engine Yard Cloud..."
76
76
 
77
77
  environment_name ||= use_default_environment
78
78
  remotes = repo.remotes if in_repo?
@@ -1,3 +1,3 @@
1
1
  module EY
2
- VERSION = '2.0.0.rc1'
2
+ VERSION = '2.0.0'
3
3
  end
@@ -17,7 +17,7 @@ describe EY::Config do
17
17
  end
18
18
 
19
19
  describe "endpoint" do
20
- it "defaults to production EY Cloud" do
20
+ it "defaults to production Engine Yard Cloud" do
21
21
  EY::Config.new.endpoint.should == EY::Config.new.default_endpoint
22
22
  end
23
23
 
@@ -11,7 +11,7 @@ describe EY::EYRC do
11
11
 
12
12
  it "looks for .eyrc in $HOME/.eyrc by default" do
13
13
  ENV.delete('EYRC')
14
- EY::EYRC.load.path.should == Pathname.new("~/.eyrc").expand_path
14
+ EY::EYRC.load.path.should == Pathname.new("#{ENV['HOME']}/.eyrc")
15
15
  end
16
16
  end
17
17
 
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe "ey web restart" do
4
+ given "integration"
5
+
6
+ def command_to_run(opts)
7
+ cmd = %w[web restart]
8
+ cmd << "-e" << opts[:environment] if opts[:environment]
9
+ cmd << "-a" << opts[:app] if opts[:app]
10
+ cmd << "-c" << opts[:account] if opts[:account]
11
+ cmd << "--verbose" if opts[:verbose]
12
+ cmd
13
+ end
14
+
15
+ def verify_ran(scenario)
16
+ @ssh_commands.should have_command_like(/engineyard-serverside.*restart.*--app #{scenario[:application]}/)
17
+ end
18
+
19
+ include_examples "it takes an environment name and an app name and an account name"
20
+ include_examples "it invokes engineyard-serverside"
21
+ end
data/spec/spec_helper.rb CHANGED
@@ -72,10 +72,6 @@ RSpec.configure do |config|
72
72
  ENV["NO_SSH"] = "true"
73
73
  end
74
74
 
75
- config.before(:each) do
76
- EY::CloudClient.default_endpoint!
77
- end
78
-
79
75
  config.after(:all) do
80
76
  clean_eyrc
81
77
  end
@@ -75,7 +75,7 @@ module SpecHelpers
75
75
  ZeroExitStatus = Class.new(UnexpectedExit)
76
76
 
77
77
  def ey_api
78
- @api ||= EY::CloudClient.new('asdf', EY::CLI::UI.new)
78
+ @api ||= EY::CloudClient.new(:token => 'asdf')
79
79
  end
80
80
 
81
81
  def ensure_eyrc
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: engineyard
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.rc1
5
- prerelease: 6
4
+ version: 2.0.0
5
+ prerelease:
6
6
  platform: ruby
7
7
  authors:
8
- - EY Cloud Team
8
+ - Engine Yard Cloud Team
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-21 00:00:00.000000000 Z
12
+ date: 2012-08-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rest-client
@@ -98,7 +98,7 @@ dependencies:
98
98
  requirements:
99
99
  - - '='
100
100
  - !ruby/object:Gem::Version
101
- version: 2.0.0.rc1
101
+ version: 2.0.0
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: 2.0.0.rc1
109
+ version: 2.0.0
110
110
  - !ruby/object:Gem::Dependency
111
111
  name: engineyard-cloud-client
112
112
  requirement: !ruby/object:Gem::Requirement
@@ -114,7 +114,7 @@ dependencies:
114
114
  requirements:
115
115
  - - ~>
116
116
  - !ruby/object:Gem::Version
117
- version: 1.0.3
117
+ version: 1.0.5
118
118
  type: :runtime
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
@@ -122,7 +122,7 @@ dependencies:
122
122
  requirements:
123
123
  - - ~>
124
124
  - !ruby/object:Gem::Version
125
- version: 1.0.3
125
+ version: 1.0.5
126
126
  - !ruby/object:Gem::Dependency
127
127
  name: net-ssh
128
128
  requirement: !ruby/object:Gem::Requirement
@@ -144,17 +144,17 @@ dependencies:
144
144
  requirement: !ruby/object:Gem::Requirement
145
145
  none: false
146
146
  requirements:
147
- - - ~>
147
+ - - '='
148
148
  - !ruby/object:Gem::Version
149
- version: '2.1'
149
+ version: 2.1.0
150
150
  type: :runtime
151
151
  prerelease: false
152
152
  version_requirements: !ruby/object:Gem::Requirement
153
153
  none: false
154
154
  requirements:
155
- - - ~>
155
+ - - '='
156
156
  - !ruby/object:Gem::Version
157
- version: '2.1'
157
+ version: 2.1.0
158
158
  - !ruby/object:Gem::Dependency
159
159
  name: rspec
160
160
  requirement: !ruby/object:Gem::Requirement
@@ -366,6 +366,7 @@ files:
366
366
  - spec/ey/status_spec.rb
367
367
  - spec/ey/web/disable_spec.rb
368
368
  - spec/ey/web/enable_spec.rb
369
+ - spec/ey/web/restart_spec.rb
369
370
  - spec/ey/whoami_spec.rb
370
371
  - spec/spec_helper.rb
371
372
  - spec/support/bundled_ey
@@ -377,11 +378,26 @@ files:
377
378
  - spec/support/shared_behavior.rb
378
379
  homepage: http://github.com/engineyard/engineyard
379
380
  licenses: []
380
- post_install_message: ! "\nWelcome to Engine Yard!\n \nDeploying for the first time?
381
- The Engine Yard Pandas want to help you! \n\nEmail pandas@engineyard.com with your
382
- questions or queries. \n(Panda = 1. Polite Agent of Non-Destructive Assimilation;
383
- 2. Cute fluffy animal.)\n \nWe wish you every success with your business!\n \n -
384
- The Pandas\n\n"
381
+ post_install_message: ! "Thank you for downloading engineyard gem version 2!\n\n############
382
+ NOTICE when upgrading from 1.x to 2.x ############\n\nFirst, if you have any trouble,
383
+ you can uninstall this version to downgrade.\nThis version of the CLI does not affect
384
+ the web deploy system.\nPlease file a support ticket if you have any issues at:
385
+ support.cloud.engineyard.com\n\n* IMPORTANT: eydeploy.rb modifications MUST be verified
386
+ in staging!\n Many internals have changed that could break eydeploy.rb!\n* The
387
+ order of compile_assets has *changed*. It now runs before\n the maintenance page
388
+ is enabled, to reduce downtime.\n* ey.yml files should be checked in to your repository.\n*
389
+ Default bundler version is now 1.1.5.\n\nA few other nice changes:\n\n* All CLI
390
+ commands are significantly faster. Woo!\n* Deploy hooks now have access to `account_name`
391
+ and `environment_name`.\n* Deploy hooks can now use run! and sudo! to abort on failure.\n*
392
+ Supports new ey.yml options when ey.yml is committed:\n * maintenance_on_restart:
393
+ true/false (default: false except for glassfish and mongrel)\n * maintenance_on_migrate:
394
+ true/false (default: true)\n * precompile_assets: true/false (default: inferred
395
+ using app/assets and config/application.rb)\n * ignore_database_adapter_warning:
396
+ true (hides adapter warning)\n* Don't remove maintenance pages that weren't put
397
+ up during this deploy if maintenance options (above) are set to false.\n* ey web
398
+ restart - restarts web servers without deploying.\n\nDeploying for the first time?
399
+ The Engine Yard Pandas want to help you!\nEmail pandas@engineyard.com with your
400
+ questions.\n"
385
401
  rdoc_options: []
386
402
  require_paths:
387
403
  - lib
@@ -391,12 +407,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
391
407
  - - ! '>='
392
408
  - !ruby/object:Gem::Version
393
409
  version: '0'
410
+ segments:
411
+ - 0
412
+ hash: -4522439113898007272
394
413
  required_rubygems_version: !ruby/object:Gem::Requirement
395
414
  none: false
396
415
  requirements:
397
- - - ! '>'
416
+ - - ! '>='
398
417
  - !ruby/object:Gem::Version
399
- version: 1.3.1
418
+ version: '0'
419
+ segments:
420
+ - 0
421
+ hash: -4522439113898007272
400
422
  requirements: []
401
423
  rubyforge_project:
402
424
  rubygems_version: 1.8.24
@@ -426,6 +448,7 @@ test_files:
426
448
  - spec/ey/status_spec.rb
427
449
  - spec/ey/web/disable_spec.rb
428
450
  - spec/ey/web/enable_spec.rb
451
+ - spec/ey/web/restart_spec.rb
429
452
  - spec/ey/whoami_spec.rb
430
453
  - spec/spec_helper.rb
431
454
  - spec/support/bundled_ey