| Class | Heroku::CommandLine |
| In: |
lib/heroku/command_line.rb
|
| Parent: | Object |
This wraps the Heroku::Client class with higher-level actions suitable for use from the command line.
| credentials | [RW] |
# File lib/heroku/command_line.rb, line 121
121: def add_collaborator(name, email, access)
122: display heroku.add_collaborator(name, email, access)
123: end
# File lib/heroku/command_line.rb, line 329
329: def add_key(keyfile=nil)
330: keyfile ||= find_key
331: key = File.read(keyfile)
332:
333: display "Uploading ssh public key #{keyfile}"
334: heroku.add_key(key)
335: end
# File lib/heroku/command_line.rb, line 202
202: def ask_for_credentials
203: puts "Enter your Heroku credentials."
204:
205: print "Email: "
206: user = gets.strip
207:
208: print "Password: "
209: password = running_on_windows? ? ask_for_password_on_windows : ask_for_password
210:
211: [ user, password ]
212: end
# File lib/heroku/command_line.rb, line 231
231: def ask_for_password
232: echo_off
233: password = gets.strip
234: puts
235: echo_on
236: return password
237: end
# File lib/heroku/command_line.rb, line 214
214: def ask_for_password_on_windows
215: require "Win32API"
216: char = nil
217: password = ''
218:
219: while char = Win32API.new("crtdll", "_getch", [ ], "L").Call do
220: break if char == 10 || char == 13 # received carriage return or newline
221: if char == 127 || char == 8 # backspace and delete
222: password.slice!(-1, 1)
223: else
224: password << char.chr
225: end
226: end
227: puts
228: return password
229: end
# File lib/heroku/command_line.rb, line 377
377: def authkey
378: return @ssh_key if @ssh_key
379: %w( rsa dsa ).each do |key_type|
380: key = authkey_type(key_type)
381: return key if key
382: end
383: raise "Your ssh public key was not found. Make sure you have a rsa or dsa key in #{home_directory}/.ssh, or specify the full path to the keyfile."
384: end
# File lib/heroku/command_line.rb, line 373
373: def authkey_read(filename)
374: File.read(filename) if File.exists?(filename)
375: end
# File lib/heroku/command_line.rb, line 369
369: def authkey_type(key_type)
370: authkey_read("#{home_directory}/.ssh/id_#{key_type}.pub")
371: end
# File lib/heroku/command_line.rb, line 76
76: def clone(args)
77: name = args.shift.downcase.strip rescue ""
78: if name.length == 0 or name.slice(0, 1) == '-'
79: display "Usage: heroku clone <app>"
80: display "(this command is deprecated in favor of using the git repo url directly)"
81: else
82: cmd = "git clone #{git_repo_for(name)}"
83: display cmd
84: system cmd
85: end
86: end
# File lib/heroku/command_line.rb, line 117
117: def collaborators(args)
118: sharing(args)
119: end
# File lib/heroku/command_line.rb, line 49
49: def create(args)
50: name = args.shift.downcase.strip rescue nil
51: name = heroku.create(name, {})
52: display "Created http://#{name}.#{heroku.host}/ | git@#{heroku.host}:#{name}.git"
53: end
# File lib/heroku/command_line.rb, line 175
175: def credentials_file
176: "#{home_directory}/.heroku/credentials"
177: end
# File lib/heroku/command_line.rb, line 276
276: def delete_credentials
277: FileUtils.rm_f(credentials_file)
278: end
# File lib/heroku/command_line.rb, line 88
88: def destroy(args)
89: name = args.shift.strip.downcase rescue ""
90: if name.length == 0 or name.slice(0, 1) == '-'
91: display "Usage: heroku destroy <app>"
92: else
93: heroku.destroy(name)
94: display "Destroyed #{name}"
95: end
96: end
^^^ Deprecated
# File lib/heroku/command_line.rb, line 387
387: def display(msg)
388: puts msg
389: end
# File lib/heroku/command_line.rb, line 6
6: def execute(command, args)
7: send(command, args)
8: rescue RestClient::Unauthorized
9: display "Authentication failure"
10: rescue RestClient::ResourceNotFound
11: display "Resource not found. (Did you mistype the app name?)"
12: rescue RestClient::RequestFailed => e
13: display extract_error(e.response)
14: rescue Heroku::CommandLine::CommandFailed => e
15: display e.message
16: end
# File lib/heroku/command_line.rb, line 395
395: def extract_error(response)
396: return "Not found" if response.code.to_i == 404
397:
398: msg = parse_error_xml(response.body) rescue ''
399: msg = 'Internal server error' if msg.empty?
400: msg
401: end
# File lib/heroku/command_line.rb, line 363
363: def extract_key!
364: return unless key_path = extract_option(ARGV, ['-k', '--key'])
365: raise "Please inform the full path for your ssh public key" if File.directory?(key_path)
366: raise "Could not read ssh public key in #{key_path}" unless @ssh_key = authkey_read(key_path)
367: end
# File lib/heroku/command_line.rb, line 280
280: def extract_option(args, options, valid_values=nil)
281: values = options.is_a?(Array) ? options : [options]
282: return unless opt_index = args.select { |a| values.include? a }.first
283: opt_value = args[args.index(opt_index) + 1] rescue nil
284:
285: # remove option from args
286: args.delete(opt_index)
287: args.delete(opt_value)
288:
289: if valid_values
290: opt_value = opt_value.downcase if opt_value
291: raise CommandFailed, "Invalid value '#{opt_value}' for option #{values.last}" unless valid_values.include?(opt_value)
292: end
293:
294: block_given? ? yield(opt_value) : opt_value
295: end
# File lib/heroku/command_line.rb, line 347
347: def find_key
348: %w(rsa dsa).each do |key_type|
349: keyfile = "#{home_directory}/.ssh/id_#{key_type}.pub"
350: return keyfile if File.exists? keyfile
351: end
352: raise CommandFailed, "No ssh public key found in #{home_directory}/.ssh/id_[rd]sa.pub. You may want to specify the full path to the keyfile."
353: end
# File lib/heroku/command_line.rb, line 140
140: def git_repo_for(name)
141: "git@#{heroku.host}:#{name}.git"
142: end
# File lib/heroku/command_line.rb, line 391
391: def home_directory
392: running_on_windows? ? ENV['USERPROFILE'] : ENV['HOME']
393: end
# File lib/heroku/command_line.rb, line 27
27: def info(args)
28: name = args.shift.downcase.strip rescue ""
29: if name.length == 0 or name.slice(0, 1) == '-'
30: display "Usage: heroku info <app>"
31: else
32: attrs = heroku.info(name)
33: display "=== #{attrs[:name]}"
34: display "Web URL: http://#{attrs[:name]}.#{heroku.host}/"
35: display "Domain name: http://#{attrs[:domain_name]}/" if attrs[:domain_name]
36: display "Git Repo: git@#{heroku.host}:#{attrs[:name]}.git"
37: display "Mode: #{ attrs[:production] == 'true' ? 'production' : 'development' }"
38: display "Public: #{ attrs[:'share-public'] == 'true' ? 'true' : 'false' }"
39:
40: first = true
41: lead = "Collaborators:"
42: attrs[:collaborators].each do |collaborator|
43: display "#{first ? lead : ' ' * lead.length} #{collaborator[:email]} (#{collaborator[:access]})"
44: first = false
45: end
46: end
47: end
# File lib/heroku/command_line.rb, line 297
297: def keys(*args)
298: args = args.first # something weird with ruby argument passing
299:
300: if args.empty?
301: list_keys
302: return
303: end
304:
305: extract_option(args, '--add') do |keyfile|
306: add_key(keyfile)
307: return
308: end
309: extract_option(args, '--remove') do |arg|
310: remove_key(arg)
311: return
312: end
313:
314: display "Usage: heroku keys [--add or --remove]"
315: end
# File lib/heroku/command_line.rb, line 18
18: def list(args)
19: list = heroku.list
20: if list.size > 0
21: display list.join("\n")
22: else
23: display "You have no apps."
24: end
25: end
# File lib/heroku/command_line.rb, line 135
135: def list_collaborators(name)
136: list = heroku.list_collaborators(name)
137: display list.map { |c| "#{c[:email]} (#{c[:access]})" }.join("\n")
138: end
# File lib/heroku/command_line.rb, line 317
317: def list_keys
318: keys = heroku.keys
319: if keys.empty?
320: display "No keys for #{user}"
321: else
322: display "=== #{keys.size} key#{keys.size > 1 ? 's' : ''} for #{user}"
323: keys.each do |key|
324: display key
325: end
326: end
327: end
# File lib/heroku/command_line.rb, line 403
403: def parse_error_xml(body)
404: xml_errors = REXML::Document.new(body).elements.to_a("//errors/error")
405: xml_errors.map { |a| a.text }.join(" / ")
406: end
# File lib/heroku/command_line.rb, line 144
144: def rake(args)
145: app_name = args.shift.strip.downcase rescue ""
146: cmd = args.join(' ')
147: if app_name.length == 0 or cmd.length == 0
148: display "Usage: heroku rake <app> <command>"
149: else
150: puts heroku.rake(app_name, cmd)
151: end
152: end
# File lib/heroku/command_line.rb, line 188
188: def read_credentials
189: if File.exists? credentials_file
190: return File.read(credentials_file).split("\n")
191: end
192: end
# File lib/heroku/command_line.rb, line 130
130: def remove_collaborator(name, email)
131: heroku.remove_collaborator(name, email)
132: display "Collaborator removed"
133: end
# File lib/heroku/command_line.rb, line 337
337: def remove_key(arg)
338: if arg == 'all'
339: heroku.remove_all_keys
340: display "All keys removed."
341: else
342: heroku.remove_key(arg)
343: display "Key #{arg} removed."
344: end
345: end
# File lib/heroku/command_line.rb, line 257
257: def retry_login?
258: @login_attempts ||= 0
259: @login_attempts += 1
260: @login_attempts < 3
261: end
# File lib/heroku/command_line.rb, line 408
408: def running_on_windows?
409: RUBY_PLATFORM =~ /mswin32/
410: end
# File lib/heroku/command_line.rb, line 239
239: def save_credentials
240: begin
241: write_credentials
242: add_key
243: rescue RestClient::Unauthorized => e
244: delete_credentials
245: raise e unless retry_login?
246:
247: display "\nAuthentication failed"
248: @credentials = ask_for_credentials
249: @heroku = init_heroku
250: retry
251: rescue Exception => e
252: delete_credentials
253: raise e
254: end
255: end
# File lib/heroku/command_line.rb, line 271
271: def set_credentials_permissions
272: FileUtils.chmod 0700, File.dirname(credentials_file)
273: FileUtils.chmod 0600, credentials_file
274: end
# File lib/heroku/command_line.rb, line 98
98: def sharing(args)
99: name = args.shift.strip.downcase rescue ""
100: if name.length == 0 or name.slice(0, 1) == '-'
101: display "Usage: heroku sharing <app>"
102: else
103: access = extract_option(args, '--access', %w( edit view )) || 'view'
104: extract_option(args, '--add') do |email|
105: return add_collaborator(name, email, access)
106: end
107: extract_option(args, '--update') do |email|
108: return update_collaborator(name, email, access)
109: end
110: extract_option(args, '--remove') do |email|
111: return remove_collaborator(name, email)
112: end
113: return list_collaborators(name)
114: end
115: end
# File lib/heroku/command_line.rb, line 55
55: def update(args)
56: name = args.shift.downcase.strip rescue ""
57: raise CommandFailed, "Invalid app name" if name.length == 0 or name.slice(0, 1) == '-'
58:
59: attributes = {}
60: extract_option(args, '--name') do |new_name|
61: attributes[:name] = new_name
62: end
63: extract_option(args, '--public', %w( true false )) do |public|
64: attributes[:share_public] = (public == 'true')
65: end
66: extract_option(args, '--mode', %w( production development )) do |mode|
67: attributes[:production] = (mode == 'production')
68: end
69: raise CommandFailed, "Nothing to update" if attributes.empty?
70: heroku.update(name, attributes)
71:
72: app_name = attributes[:name] || name
73: display "http://#{app_name}.#{heroku.host}/ updated"
74: end
# File lib/heroku/command_line.rb, line 125
125: def update_collaborator(name, email, access)
126: heroku.update_collaborator(name, email, access)
127: display "Collaborator updated"
128: end
vvv Deprecated
# File lib/heroku/command_line.rb, line 356
356: def upload_authkey(*args)
357: extract_key!
358: display "Uploading ssh public key"
359: display "(upload_authkey is deprecated, please use \"heroku keys --add\" instead)"
360: heroku.add_key(authkey)
361: end