pogo 2.31.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. data/README.md +73 -0
  2. data/bin/pogo +22 -0
  3. data/data/cacert.pem +3988 -0
  4. data/lib/heroku.rb +22 -0
  5. data/lib/heroku/auth.rb +320 -0
  6. data/lib/heroku/cli.rb +38 -0
  7. data/lib/heroku/client.rb +764 -0
  8. data/lib/heroku/client/heroku_postgresql.rb +111 -0
  9. data/lib/heroku/client/pgbackups.rb +113 -0
  10. data/lib/heroku/client/rendezvous.rb +105 -0
  11. data/lib/heroku/client/ssl_endpoint.rb +25 -0
  12. data/lib/heroku/command.rb +273 -0
  13. data/lib/heroku/command/account.rb +23 -0
  14. data/lib/heroku/command/accounts.rb +34 -0
  15. data/lib/heroku/command/addons.rb +305 -0
  16. data/lib/heroku/command/apps.rb +311 -0
  17. data/lib/heroku/command/auth.rb +86 -0
  18. data/lib/heroku/command/base.rb +230 -0
  19. data/lib/heroku/command/certs.rb +148 -0
  20. data/lib/heroku/command/config.rb +137 -0
  21. data/lib/heroku/command/db.rb +218 -0
  22. data/lib/heroku/command/domains.rb +85 -0
  23. data/lib/heroku/command/drains.rb +46 -0
  24. data/lib/heroku/command/git.rb +65 -0
  25. data/lib/heroku/command/help.rb +163 -0
  26. data/lib/heroku/command/keys.rb +115 -0
  27. data/lib/heroku/command/labs.rb +161 -0
  28. data/lib/heroku/command/logs.rb +98 -0
  29. data/lib/heroku/command/maintenance.rb +61 -0
  30. data/lib/heroku/command/pg.rb +277 -0
  31. data/lib/heroku/command/pgbackups.rb +289 -0
  32. data/lib/heroku/command/plugins.rb +110 -0
  33. data/lib/heroku/command/ps.rb +232 -0
  34. data/lib/heroku/command/releases.rb +124 -0
  35. data/lib/heroku/command/run.rb +179 -0
  36. data/lib/heroku/command/sharing.rb +89 -0
  37. data/lib/heroku/command/ssl.rb +61 -0
  38. data/lib/heroku/command/stack.rb +62 -0
  39. data/lib/heroku/command/status.rb +51 -0
  40. data/lib/heroku/command/update.rb +47 -0
  41. data/lib/heroku/command/version.rb +23 -0
  42. data/lib/heroku/deprecated.rb +5 -0
  43. data/lib/heroku/deprecated/help.rb +38 -0
  44. data/lib/heroku/distribution.rb +9 -0
  45. data/lib/heroku/helpers.rb +517 -0
  46. data/lib/heroku/helpers/heroku_postgresql.rb +104 -0
  47. data/lib/heroku/plugin.rb +161 -0
  48. data/lib/heroku/updater.rb +158 -0
  49. data/lib/heroku/version.rb +3 -0
  50. data/lib/vendor/heroku/okjson.rb +598 -0
  51. data/spec/helper/legacy_help.rb +16 -0
  52. data/spec/heroku/auth_spec.rb +246 -0
  53. data/spec/heroku/client/heroku_postgresql_spec.rb +34 -0
  54. data/spec/heroku/client/pgbackups_spec.rb +43 -0
  55. data/spec/heroku/client/rendezvous_spec.rb +62 -0
  56. data/spec/heroku/client/ssl_endpoint_spec.rb +48 -0
  57. data/spec/heroku/client_spec.rb +564 -0
  58. data/spec/heroku/command/addons_spec.rb +585 -0
  59. data/spec/heroku/command/apps_spec.rb +351 -0
  60. data/spec/heroku/command/auth_spec.rb +38 -0
  61. data/spec/heroku/command/base_spec.rb +109 -0
  62. data/spec/heroku/command/certs_spec.rb +178 -0
  63. data/spec/heroku/command/config_spec.rb +144 -0
  64. data/spec/heroku/command/db_spec.rb +110 -0
  65. data/spec/heroku/command/domains_spec.rb +87 -0
  66. data/spec/heroku/command/drains_spec.rb +34 -0
  67. data/spec/heroku/command/git_spec.rb +116 -0
  68. data/spec/heroku/command/help_spec.rb +93 -0
  69. data/spec/heroku/command/keys_spec.rb +120 -0
  70. data/spec/heroku/command/labs_spec.rb +99 -0
  71. data/spec/heroku/command/logs_spec.rb +60 -0
  72. data/spec/heroku/command/maintenance_spec.rb +51 -0
  73. data/spec/heroku/command/pg_spec.rb +223 -0
  74. data/spec/heroku/command/pgbackups_spec.rb +280 -0
  75. data/spec/heroku/command/plugins_spec.rb +104 -0
  76. data/spec/heroku/command/ps_spec.rb +195 -0
  77. data/spec/heroku/command/releases_spec.rb +130 -0
  78. data/spec/heroku/command/run_spec.rb +86 -0
  79. data/spec/heroku/command/sharing_spec.rb +59 -0
  80. data/spec/heroku/command/ssl_spec.rb +32 -0
  81. data/spec/heroku/command/stack_spec.rb +46 -0
  82. data/spec/heroku/command/status_spec.rb +48 -0
  83. data/spec/heroku/command/version_spec.rb +16 -0
  84. data/spec/heroku/command_spec.rb +211 -0
  85. data/spec/heroku/helpers/heroku_postgresql_spec.rb +109 -0
  86. data/spec/heroku/helpers_spec.rb +48 -0
  87. data/spec/heroku/plugin_spec.rb +172 -0
  88. data/spec/heroku/updater_spec.rb +44 -0
  89. data/spec/spec.opts +1 -0
  90. data/spec/spec_helper.rb +209 -0
  91. data/spec/support/display_message_matcher.rb +49 -0
  92. data/spec/support/openssl_mock_helper.rb +8 -0
  93. metadata +220 -0
@@ -0,0 +1,86 @@
1
+ require "heroku/command/base"
2
+
3
+ # authentication (login, logout)
4
+ #
5
+ class Heroku::Command::Auth < Heroku::Command::Base
6
+
7
+ # auth
8
+ #
9
+ # Authenticate, display token and current user
10
+ def index
11
+ validate_arguments!
12
+
13
+ Heroku::Command::Help.new.send(:help_for_command, current_command)
14
+ end
15
+
16
+ # auth:login
17
+ #
18
+ # log in with your heroku credentials
19
+ #
20
+ #Example:
21
+ #
22
+ # $ heroku auth:login
23
+ # Enter your Heroku credentials:
24
+ # Email: email@example.com
25
+ # Password (typing will be hidden):
26
+ # Authentication successful.
27
+ #
28
+ def login
29
+ validate_arguments!
30
+
31
+ Heroku::Auth.login
32
+ display "Authentication successful."
33
+ end
34
+
35
+ alias_command "login", "auth:login"
36
+
37
+ # auth:logout
38
+ #
39
+ # clear local authentication credentials
40
+ #
41
+ #Example:
42
+ #
43
+ # $ heroku auth:logout
44
+ # Local credentials cleared.
45
+ #
46
+ def logout
47
+ validate_arguments!
48
+
49
+ Heroku::Auth.logout
50
+ display "Local credentials cleared."
51
+ end
52
+
53
+ alias_command "logout", "auth:logout"
54
+
55
+ # auth:token
56
+ #
57
+ # display your api token
58
+ #
59
+ #Example:
60
+ #
61
+ # $ heroku auth:token
62
+ # ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCD
63
+ #
64
+ def token
65
+ validate_arguments!
66
+
67
+ display Heroku::Auth.api_key
68
+ end
69
+
70
+ # auth:whoami
71
+ #
72
+ # display your heroku email address
73
+ #
74
+ #Example:
75
+ #
76
+ # $ heroku auth:whoami
77
+ # email@example.com
78
+ #
79
+ def whoami
80
+ validate_arguments!
81
+
82
+ display Heroku::Auth.user
83
+ end
84
+
85
+ end
86
+
@@ -0,0 +1,230 @@
1
+ require "fileutils"
2
+ require "heroku/auth"
3
+ require "heroku/client/rendezvous"
4
+ require "heroku/command"
5
+
6
+ class Heroku::Command::Base
7
+ include Heroku::Helpers
8
+
9
+ def self.namespace
10
+ self.to_s.split("::").last.downcase
11
+ end
12
+
13
+ attr_reader :args
14
+ attr_reader :options
15
+
16
+ def initialize(args=[], options={})
17
+ @args = args
18
+ @options = options
19
+ end
20
+
21
+ def app
22
+ @app ||= if options[:confirm].is_a?(String)
23
+ if options[:app] && (options[:app] != options[:confirm])
24
+ error("Mismatch between --app and --confirm")
25
+ end
26
+ options[:confirm]
27
+ elsif options[:app].is_a?(String)
28
+ options[:app]
29
+ elsif ENV.has_key?('HEROKU_APP')
30
+ ENV['HEROKU_APP']
31
+ elsif app_from_dir = extract_app_in_dir(Dir.pwd)
32
+ app_from_dir
33
+ else
34
+ # raise instead of using error command to enable rescuing when app is optional
35
+ raise Heroku::Command::CommandFailed.new("No app specified.\nRun this command from an app folder or specify which app to use with --app APP.")
36
+ end
37
+ end
38
+
39
+ def api
40
+ Heroku::Auth.api
41
+ end
42
+
43
+ def heroku
44
+ Heroku::Auth.client
45
+ end
46
+
47
+ protected
48
+
49
+ def self.inherited(klass)
50
+ unless klass == Heroku::Command::Base
51
+ help = extract_help_from_caller(caller.first)
52
+
53
+ Heroku::Command.register_namespace(
54
+ :name => klass.namespace,
55
+ :description => help.first
56
+ )
57
+ end
58
+ end
59
+
60
+ def self.method_added(method)
61
+ return if self == Heroku::Command::Base
62
+ return if private_method_defined?(method)
63
+ return if protected_method_defined?(method)
64
+
65
+ help = extract_help_from_caller(caller.first)
66
+ resolved_method = (method.to_s == "index") ? nil : method.to_s
67
+ command = [ self.namespace, resolved_method ].compact.join(":")
68
+ banner = extract_banner(help) || command
69
+
70
+ Heroku::Command.register_command(
71
+ :klass => self,
72
+ :method => method,
73
+ :namespace => self.namespace,
74
+ :command => command,
75
+ :banner => banner.strip,
76
+ :help => help.join("\n"),
77
+ :summary => extract_summary(help),
78
+ :description => extract_description(help),
79
+ :options => extract_options(help)
80
+ )
81
+ end
82
+
83
+ def self.alias_command(new, old)
84
+ raise "no such command: #{old}" unless Heroku::Command.commands[old]
85
+ Heroku::Command.command_aliases[new] = old
86
+ end
87
+
88
+ def extract_app
89
+ output_with_bang "Command::Base#extract_app has been deprecated. Please use Command::Base#app instead. #{caller.first}"
90
+ app
91
+ end
92
+
93
+ #
94
+ # Parse the caller format and identify the file and line number as identified
95
+ # in : http://www.ruby-doc.org/core/classes/Kernel.html#M001397. This will
96
+ # look for a colon followed by a digit as the delimiter. The biggest
97
+ # complication is windows paths, which have a color after the drive letter.
98
+ # This regex will match paths as anything from the beginning to a colon
99
+ # directly followed by a number (the line number).
100
+ #
101
+ # Examples of the caller format :
102
+ # * c:/Ruby192/lib/.../lib/heroku/command/addons.rb:8:in `<module:Command>'
103
+ # * c:/Ruby192/lib/.../heroku-2.0.1/lib/heroku/command/pg.rb:96:in `<class:Pg>'
104
+ # * /Users/ph7/...../xray-1.1/lib/xray/thread_dump_signal_handler.rb:9
105
+ #
106
+ def self.extract_help_from_caller(line)
107
+ # pull out of the caller the information for the file path and line number
108
+ if line =~ /^(.+?):(\d+)/
109
+ extract_help($1, $2)
110
+ else
111
+ raise("unable to extract help from caller: #{line}")
112
+ end
113
+ end
114
+
115
+ def self.extract_help(file, line_number)
116
+ buffer = []
117
+ lines = Heroku::Command.files[file]
118
+
119
+ (line_number.to_i-2).downto(0) do |i|
120
+ line = lines[i]
121
+ case line[0..0]
122
+ when ""
123
+ when "#"
124
+ buffer.unshift(line[1..-1])
125
+ else
126
+ break
127
+ end
128
+ end
129
+
130
+ buffer
131
+ end
132
+
133
+ def self.extract_banner(help)
134
+ help.first
135
+ end
136
+
137
+ def self.extract_summary(help)
138
+ extract_description(help).split("\n")[2].to_s.split("\n").first
139
+ end
140
+
141
+ def self.extract_description(help)
142
+ help.reject do |line|
143
+ line =~ /^\s+-(.+)#(.+)/
144
+ end.join("\n")
145
+ end
146
+
147
+ def self.extract_options(help)
148
+ help.select do |line|
149
+ line =~ /^\s+-(.+)#(.+)/
150
+ end.inject([]) do |options, line|
151
+ args = line.split('#', 2).first
152
+ args = args.split(/,\s*/).map {|arg| arg.strip}.sort.reverse
153
+ name = args.last.split(' ', 2).first[2..-1]
154
+ options << { :name => name, :args => args }
155
+ end
156
+ end
157
+
158
+ def current_command
159
+ Heroku::Command.current_command
160
+ end
161
+
162
+ def extract_option(key)
163
+ options[key.dup.gsub('-','_').to_sym]
164
+ end
165
+
166
+ def invalid_arguments
167
+ Heroku::Command.invalid_arguments
168
+ end
169
+
170
+ def shift_argument
171
+ Heroku::Command.shift_argument
172
+ end
173
+
174
+ def validate_arguments!
175
+ Heroku::Command.validate_arguments!
176
+ end
177
+
178
+ def extract_app_in_dir(dir)
179
+ return unless remotes = git_remotes(dir)
180
+
181
+ if remote = options[:remote]
182
+ remotes[remote]
183
+ elsif remote = extract_app_from_git_config
184
+ remotes[remote]
185
+ else
186
+ apps = remotes.values.uniq
187
+ if apps.size == 1
188
+ apps.first
189
+ else
190
+ raise(Heroku::Command::CommandFailed, "Multiple apps in folder and no app specified.\nSpecify app with --app APP.")
191
+ end
192
+ end
193
+ end
194
+
195
+ def extract_app_from_git_config
196
+ remote = git("config heroku.remote")
197
+ remote == "" ? nil : remote
198
+ end
199
+
200
+ def git_remotes(base_dir=Dir.pwd)
201
+ remotes = {}
202
+ original_dir = Dir.pwd
203
+ Dir.chdir(base_dir)
204
+
205
+ return unless File.exists?(".git")
206
+ git("remote -v").split("\n").each do |remote|
207
+ name, url, method = remote.split(/\s/)
208
+ if url =~ /^git@#{Heroku::Auth.git_host}:([\w\d-]+)\.git$/
209
+ remotes[name] = $1
210
+ end
211
+ end
212
+
213
+ Dir.chdir(original_dir)
214
+ if remotes.empty?
215
+ nil
216
+ else
217
+ remotes
218
+ end
219
+ end
220
+
221
+ def escape(value)
222
+ heroku.escape(value)
223
+ end
224
+ end
225
+
226
+ module Heroku::Command
227
+ unless const_defined?(:BaseWithApp)
228
+ BaseWithApp = Base
229
+ end
230
+ end
@@ -0,0 +1,148 @@
1
+ require "heroku/command/base"
2
+
3
+ # manage ssl endpoints for an app
4
+ #
5
+ class Heroku::Command::Certs < Heroku::Command::Base
6
+
7
+ # certs
8
+ #
9
+ # list ssl endpoints for an app
10
+ #
11
+ def index
12
+ endpoints = heroku.ssl_endpoint_list(app)
13
+
14
+ if endpoints.empty?
15
+ display "#{app} has no SSL Endpoints."
16
+ display "Use `heroku certs:add PEM KEY` to add one."
17
+ else
18
+ endpoints.map! do |endpoint|
19
+ {
20
+ 'cname' => endpoint['cname'],
21
+ 'domains' => endpoint['ssl_cert']['cert_domains'].join(', '),
22
+ 'expires_at' => format_date(endpoint['ssl_cert']['expires_at']),
23
+ 'ca_signed?' => endpoint['ssl_cert']['ca_signed?'].to_s.capitalize
24
+ }
25
+ end
26
+ display_table(
27
+ endpoints,
28
+ %w( cname domains expires_at ca_signed? ),
29
+ [ "Endpoint", "Common Name(s)", "Expires", "Trusted" ]
30
+ )
31
+ end
32
+ end
33
+
34
+ # certs:add PEM KEY
35
+ #
36
+ # add an ssl endpoint to an app
37
+ #
38
+ def add
39
+ fail("Usage: heroku certs:add PEM KEY\nMust specify PEM and KEY to add cert.") if args.size < 2
40
+ pem = File.read(args[0]) rescue error("Unable to read #{args[0]} PEM")
41
+ key = File.read(args[1]) rescue error("Unable to read #{args[1]} KEY")
42
+
43
+ endpoint = action("Adding SSL Endpoint to #{app}") do
44
+ heroku.ssl_endpoint_add(app, pem, key)
45
+ end
46
+
47
+ display_warnings(endpoint)
48
+ display "#{app} now served by #{endpoint['cname']}"
49
+ display "Certificate details:"
50
+ display_certificate_info(endpoint)
51
+ end
52
+
53
+ # certs:info
54
+ #
55
+ # show certificate information for an ssl endpoint
56
+ #
57
+ def info
58
+ cname = options[:endpoint] || current_endpoint
59
+ endpoint = action("Fetching SSL Endpoint #{cname} info for #{app}") do
60
+ heroku.ssl_endpoint_info(app, cname)
61
+ end
62
+
63
+ display "Certificate details:"
64
+ display_certificate_info(endpoint)
65
+ end
66
+
67
+ # certs:remove
68
+ #
69
+ # remove an SSL Endpoint from an app
70
+ #
71
+ def remove
72
+ cname = options[:endpoint] || current_endpoint
73
+ action("Removing SSL Endpoint #{cname} from #{app}") do
74
+ heroku.ssl_endpoint_remove(app, cname)
75
+ end
76
+ display "NOTE: Billing is still active. Remove SSL Endpoint add-on to stop billing."
77
+ end
78
+
79
+ # certs:update PEM KEY
80
+ #
81
+ # update an SSL Endpoint on an app
82
+ #
83
+ def update
84
+ fail("Usage: heroku certs:update PEM KEY\nMust specify PEM and KEY to update cert.") if args.size < 2
85
+ pem = File.read(args[0]) rescue error("Unable to read #{args[0]} PEM")
86
+ key = File.read(args[1]) rescue error("Unable to read #{args[1]} KEY")
87
+ app = self.app
88
+ cname = options[:endpoint] || current_endpoint
89
+
90
+ endpoint = action("Updating SSL Endpoint #{cname} for #{app}") do
91
+ heroku.ssl_endpoint_update(app, cname, pem, key)
92
+ end
93
+
94
+ display_warnings(endpoint)
95
+ display "Updated certificate details:"
96
+ display_certificate_info(endpoint)
97
+ end
98
+
99
+ # certs:rollback
100
+ #
101
+ # rollback an SSL Endpoint for an app
102
+ #
103
+ def rollback
104
+ cname = options[:endpoint] || current_endpoint
105
+
106
+ endpoint = action("Rolling back SSL Endpoint #{cname} for #{app}") do
107
+ heroku.ssl_endpoint_rollback(app, cname)
108
+ end
109
+
110
+ display "New active certificate details:"
111
+ display_certificate_info(endpoint)
112
+ end
113
+
114
+ private
115
+
116
+ def current_endpoint
117
+ endpoint = heroku.ssl_endpoint_list(app).first || error("#{app} has no SSL Endpoints.")
118
+ endpoint["cname"]
119
+ end
120
+
121
+ def display_certificate_info(endpoint)
122
+ data = {
123
+ 'Common Name(s)' => endpoint['ssl_cert']['cert_domains'],
124
+ 'Expires At' => format_date(endpoint['ssl_cert']['expires_at']),
125
+ 'Issuer' => endpoint['ssl_cert']['issuer'],
126
+ 'Starts At' => format_date(endpoint['ssl_cert']['starts_at']),
127
+ 'Subject' => endpoint['ssl_cert']['subject']
128
+ }
129
+ styled_hash(data)
130
+
131
+ if endpoint["ssl_cert"]["ca_signed?"]
132
+ display "SSL certificate is verified by a root authority."
133
+ elsif endpoint["issuer"] == endpoint["subject"]
134
+ display "SSL certificate is self signed."
135
+ else
136
+ display "SSL certificate is not trusted."
137
+ end
138
+ end
139
+
140
+ def display_warnings(endpoint)
141
+ if endpoint["warnings"]
142
+ endpoint["warnings"].each do |field, warning|
143
+ display "WARNING: #{field} #{warning}"
144
+ end
145
+ end
146
+ end
147
+
148
+ end