turbot 0.1.36 → 0.2.3
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.
- checksums.yaml +4 -4
- data/.gitignore +8 -0
- data/.rspec +3 -0
- data/.travis.yml +15 -0
- data/.yardopts +3 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +44 -25
- data/Rakefile +16 -0
- data/appveyor.yml +35 -0
- data/bin/turbot +2 -16
- data/data/schema.json +134 -0
- data/{templates → data/templates}/LICENSE.txt +0 -0
- data/{templates → data/templates}/manifest.json +0 -0
- data/{templates → data/templates}/python/scraper.py +0 -0
- data/{templates → data/templates}/ruby/scraper.rb +0 -0
- data/dist/deb.rake +32 -0
- data/dist/gem.rake +16 -0
- data/dist/manifest.rake +9 -0
- data/dist/pkg.rake +60 -0
- data/dist/resources/deb/control +10 -0
- data/dist/resources/deb/postinst +45 -0
- data/dist/resources/deb/turbot +25 -0
- data/dist/resources/deb/turbot-release-key.txt +30 -0
- data/dist/resources/pkg/Distribution.erb +15 -0
- data/dist/resources/pkg/PackageInfo.erb +6 -0
- data/dist/resources/pkg/postinstall +45 -0
- data/dist/resources/pkg/turbot +24 -0
- data/dist/resources/tgz/turbot +24 -0
- data/dist/rpm.rake +35 -0
- data/dist/tgz.rake +26 -0
- data/dist/zip.rake +40 -0
- data/lib/turbot.rb +18 -15
- data/lib/turbot/cli.rb +10 -27
- data/lib/turbot/command.rb +59 -212
- data/lib/turbot/command/auth.rb +72 -34
- data/lib/turbot/command/base.rb +22 -61
- data/lib/turbot/command/bots.rb +251 -300
- data/lib/turbot/command/help.rb +57 -110
- data/lib/turbot/command/version.rb +6 -10
- data/lib/turbot/handlers/base_handler.rb +21 -0
- data/lib/turbot/handlers/dump_handler.rb +10 -0
- data/lib/turbot/handlers/preview_handler.rb +30 -0
- data/lib/turbot/handlers/validation_handler.rb +17 -0
- data/lib/turbot/helpers.rb +14 -482
- data/lib/turbot/helpers/api_helper.rb +41 -0
- data/lib/turbot/helpers/netrc_helper.rb +66 -0
- data/lib/turbot/helpers/shell_helper.rb +36 -0
- data/lib/turbot/version.rb +1 -1
- data/spec/fixtures/bad_permissions +0 -0
- data/spec/fixtures/empty +0 -0
- data/spec/fixtures/netrc +6 -0
- data/spec/spec_helper.rb +17 -219
- data/spec/support/bot_helper.rb +102 -0
- data/spec/support/command_helper.rb +20 -0
- data/spec/support/custom_matchers.rb +5 -0
- data/spec/support/fixture_helper.rb +9 -0
- data/spec/support/netrc_helper.rb +21 -0
- data/spec/turbot/command/auth_spec.rb +202 -20
- data/spec/turbot/command/base_spec.rb +22 -58
- data/spec/turbot/command/bots_spec.rb +580 -89
- data/spec/turbot/command/help_spec.rb +32 -75
- data/spec/turbot/command/version_spec.rb +11 -10
- data/spec/turbot/command_spec.rb +55 -87
- data/spec/turbot/helpers_spec.rb +28 -44
- data/turbot.gemspec +31 -0
- metadata +88 -178
- data/data/cacert.pem +0 -3988
- data/lib/turbot/auth.rb +0 -315
- data/lib/turbot/client.rb +0 -757
- data/lib/turbot/client/cisaurus.rb +0 -25
- data/lib/turbot/client/pgbackups.rb +0 -113
- data/lib/turbot/client/rendezvous.rb +0 -111
- data/lib/turbot/client/ssl_endpoint.rb +0 -25
- data/lib/turbot/client/turbot_postgresql.rb +0 -148
- data/lib/turbot/command/ssl.rb +0 -43
- data/lib/turbot/deprecated.rb +0 -5
- data/lib/turbot/deprecated/help.rb +0 -38
- data/lib/turbot/distribution.rb +0 -9
- data/lib/turbot/errors.rb +0 -28
- data/lib/turbot/excon.rb +0 -11
- data/lib/turbot/helpers/log_displayer.rb +0 -70
- data/lib/turbot/helpers/pg_dump_restore.rb +0 -115
- data/lib/turbot/helpers/turbot_postgresql.rb +0 -213
- data/lib/turbot/plugin.rb +0 -165
- data/lib/turbot/updater.rb +0 -171
- data/lib/vendor/turbot/okjson.rb +0 -598
- data/spec/helper/legacy_help.rb +0 -16
- data/spec/helper/pg_dump_restore_spec.rb +0 -67
- data/spec/spec.opts +0 -1
- data/spec/support/display_message_matcher.rb +0 -49
- data/spec/support/dummy_api.rb +0 -120
- data/spec/support/openssl_mock_helper.rb +0 -8
- data/spec/support/organizations_mock_helper.rb +0 -11
- data/spec/turbot/auth_spec.rb +0 -214
- data/spec/turbot/client/pgbackups_spec.rb +0 -43
- data/spec/turbot/client/rendezvous_spec.rb +0 -62
- data/spec/turbot/client/ssl_endpoint_spec.rb +0 -48
- data/spec/turbot/client/turbot_postgresql_spec.rb +0 -71
- data/spec/turbot/client_spec.rb +0 -548
- data/spec/turbot/helpers/turbot_postgresql_spec.rb +0 -181
- data/spec/turbot/plugin_spec.rb +0 -172
- data/spec/turbot/updater_spec.rb +0 -44
data/lib/turbot/cli.rb
CHANGED
@@ -1,42 +1,25 @@
|
|
1
|
-
load('turbot/helpers.rb') # reload helpers after possible inject_loadpath
|
2
|
-
load('turbot/updater.rb') # reload updater after possible inject_loadpath
|
3
|
-
|
4
|
-
require "turbot"
|
5
|
-
require "turbot/command"
|
6
|
-
require "turbot/helpers"
|
7
|
-
|
8
|
-
# workaround for rescue/reraise to define errors in command.rb failing in 1.8.6
|
9
|
-
if RUBY_VERSION =~ /^1.8.6/
|
10
|
-
require('turbot-api')
|
11
|
-
require('rest_client')
|
12
|
-
end
|
13
|
-
|
14
1
|
class Turbot::CLI
|
15
|
-
|
16
2
|
extend Turbot::Helpers
|
17
3
|
|
18
4
|
def self.start(*args)
|
19
5
|
begin
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
$stdout.sync = true
|
25
|
-
end
|
26
|
-
command = args.shift.strip rescue "help"
|
27
|
-
Turbot::Command.load
|
28
|
-
trap "SIGINT" do
|
6
|
+
$stdout.sync = true
|
7
|
+
$stderr.sync = true
|
8
|
+
|
9
|
+
trap 'SIGINT' do
|
29
10
|
# Script terminated by Control-C.
|
30
11
|
exit 130
|
31
12
|
end
|
13
|
+
|
14
|
+
Turbot::Command.load
|
15
|
+
command = args.shift.strip rescue 'help'
|
32
16
|
Turbot::Command.run(command, args)
|
33
17
|
rescue Interrupt
|
34
18
|
`stty icanon echo`
|
35
|
-
error
|
36
|
-
rescue =>
|
37
|
-
styled_error(
|
19
|
+
error 'Command cancelled.'
|
20
|
+
rescue => e
|
21
|
+
styled_error(e)
|
38
22
|
exit(1)
|
39
23
|
end
|
40
24
|
end
|
41
|
-
|
42
25
|
end
|
data/lib/turbot/command.rb
CHANGED
@@ -1,23 +1,20 @@
|
|
1
|
-
require 'turbot/helpers'
|
2
|
-
require 'turbot/plugin'
|
3
|
-
require 'turbot/version'
|
4
|
-
require "optparse"
|
5
|
-
require 'excon'
|
6
|
-
|
7
1
|
module Turbot
|
8
2
|
module Command
|
9
|
-
class CommandFailed < RuntimeError; end
|
10
|
-
|
11
3
|
extend Turbot::Helpers
|
12
4
|
|
13
5
|
def self.load
|
14
|
-
Dir[File.join(File.dirname(__FILE__),
|
6
|
+
Dir[File.join(File.dirname(__FILE__), 'command', '*.rb')].each do |file|
|
15
7
|
require file
|
16
8
|
end
|
17
|
-
Turbot::Plugin.load!
|
18
9
|
unregister_commands_made_private_after_the_fact
|
19
10
|
end
|
20
11
|
|
12
|
+
def self.unregister_commands_made_private_after_the_fact
|
13
|
+
commands.values.
|
14
|
+
select { |c| c[:klass].private_method_defined? c[:method] }.
|
15
|
+
each { |c| commands.delete(c[:command]) }
|
16
|
+
end
|
17
|
+
|
21
18
|
def self.commands
|
22
19
|
@@commands ||= {}
|
23
20
|
end
|
@@ -38,12 +35,6 @@ module Turbot
|
|
38
35
|
commands[command[:command]] = command
|
39
36
|
end
|
40
37
|
|
41
|
-
def self.unregister_commands_made_private_after_the_fact
|
42
|
-
commands.values \
|
43
|
-
.select { |c| c[:klass].private_method_defined? c[:method] } \
|
44
|
-
.each { |c| commands.delete c[:command] }
|
45
|
-
end
|
46
|
-
|
47
38
|
def self.register_namespace(namespace)
|
48
39
|
namespaces[namespace[:name]] = namespace
|
49
40
|
end
|
@@ -52,109 +43,36 @@ module Turbot
|
|
52
43
|
@current_command
|
53
44
|
end
|
54
45
|
|
55
|
-
def self.current_command=(new_current_command)
|
56
|
-
@current_command = new_current_command
|
57
|
-
end
|
58
|
-
|
59
|
-
def self.current_args
|
60
|
-
@current_args
|
61
|
-
end
|
62
|
-
|
63
|
-
def self.current_options
|
64
|
-
@current_options ||= {}
|
65
|
-
end
|
66
|
-
|
67
|
-
def self.global_options
|
68
|
-
@global_options ||= []
|
69
|
-
end
|
70
|
-
|
71
|
-
def self.invalid_arguments
|
72
|
-
@invalid_arguments
|
73
|
-
end
|
74
|
-
|
75
|
-
def self.shift_argument
|
76
|
-
# dup argument to get a non-frozen string
|
77
|
-
@invalid_arguments.shift.dup rescue nil
|
78
|
-
end
|
79
|
-
|
80
46
|
def self.validate_arguments!
|
81
|
-
unless invalid_arguments.empty?
|
82
|
-
arguments = invalid_arguments.map
|
47
|
+
unless @invalid_arguments.empty?
|
48
|
+
arguments = @invalid_arguments.map(&:inspect)
|
83
49
|
if arguments.length == 1
|
84
50
|
message = "Invalid argument: #{arguments.first}"
|
85
|
-
|
86
|
-
message = "Invalid arguments: "
|
87
|
-
message << arguments[0...-1].join(", ")
|
88
|
-
message << " and "
|
89
|
-
message << arguments[-1]
|
51
|
+
else
|
52
|
+
message = "Invalid arguments: #{arguments[0...-1].join(', ')} and #{arguments[-1]}"
|
90
53
|
end
|
91
|
-
|
92
|
-
|
93
|
-
exit(1)
|
54
|
+
run('help', [current_command])
|
55
|
+
error message
|
94
56
|
end
|
95
57
|
end
|
96
58
|
|
97
|
-
def self.warnings
|
98
|
-
@warnings ||= []
|
99
|
-
end
|
100
|
-
|
101
|
-
def self.display_warnings
|
102
|
-
unless warnings.empty?
|
103
|
-
$stderr.puts(warnings.map {|warning| " ! #{warning}"}.join("\n"))
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
def self.global_option(name, *args, &blk)
|
108
|
-
# args.sort.reverse gives -l, --long order
|
109
|
-
global_options << { :name => name.to_s, :args => args.sort.reverse, :proc => blk }
|
110
|
-
end
|
111
|
-
|
112
|
-
global_option :bot, "-b", "--bot APP" do |bot|
|
113
|
-
raise OptionParser::InvalidOption.new(bot) if bot == "pp"
|
114
|
-
end
|
115
|
-
|
116
|
-
global_option :org, "-o", "--org ORG" do |org|
|
117
|
-
raise OptionParser::InvalidOption.new(org) if org == "rg"
|
118
|
-
end
|
119
|
-
global_option :personal, "-p", "--personal"
|
120
|
-
|
121
|
-
global_option :confirm, "--confirm APP"
|
122
|
-
global_option :help, "-h", "--help"
|
123
|
-
global_option :remote, "-r", "--remote REMOTE"
|
124
|
-
|
125
59
|
def self.prepare_run(cmd, args=[])
|
126
|
-
command =
|
127
|
-
|
128
|
-
if args.include?('-h') || args.include?('--help')
|
129
|
-
args.unshift(cmd) unless cmd =~ /^-.*/
|
130
|
-
cmd = 'help'
|
131
|
-
command = parse(cmd)
|
132
|
-
end
|
133
|
-
|
134
|
-
if cmd == '--version'
|
135
|
-
cmd = 'version'
|
136
|
-
command = parse(cmd)
|
137
|
-
end
|
138
|
-
|
60
|
+
command = commands[cmd] || commands[command_aliases[cmd]]
|
139
61
|
@current_command = cmd
|
140
|
-
@anonymized_args, @normalized_args = [], []
|
141
62
|
|
142
63
|
opts = {}
|
143
64
|
invalid_options = []
|
144
65
|
|
145
66
|
parser = OptionParser.new do |parser|
|
146
67
|
# remove OptionParsers Officious['version'] to avoid conflicts
|
147
|
-
# see: https://github.com/ruby/ruby/blob/
|
68
|
+
# see: https://github.com/ruby/ruby/blob/6860034546808d4f67ba8f407f3d7aced0c54c5a/lib/optparse.rb#L989
|
148
69
|
parser.base.long.delete('version')
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
option[:
|
70
|
+
if command && command[:options]
|
71
|
+
command[:options].each do |option|
|
72
|
+
parser.on(*option[:args]) do |value|
|
73
|
+
opts[option[:name].gsub('-', '_').to_sym] = value
|
74
|
+
ARGV.join(' ') =~ /(#{option[:args].map {|arg| arg.split(' ', 2).first}.join('|')})/
|
153
75
|
end
|
154
|
-
opts[option[:name].gsub('-', '_').to_sym] = value
|
155
|
-
ARGV.join(' ') =~ /(#{option[:args].map {|arg| arg.split(' ', 2).first}.join('|')})/
|
156
|
-
@anonymized_args << "#{$1} _"
|
157
|
-
@normalized_args << "#{option[:args].last.split(' ', 2).first} _"
|
158
76
|
end
|
159
77
|
end
|
160
78
|
end
|
@@ -162,144 +80,73 @@ module Turbot
|
|
162
80
|
begin
|
163
81
|
parser.order!(args) do |nonopt|
|
164
82
|
invalid_options << nonopt
|
165
|
-
@anonymized_args << '!'
|
166
|
-
@normalized_args << '!'
|
167
83
|
end
|
168
|
-
rescue OptionParser::InvalidOption =>
|
169
|
-
invalid_options <<
|
170
|
-
@anonymized_args << '!'
|
171
|
-
@normalized_args << '!'
|
84
|
+
rescue OptionParser::InvalidOption => e
|
85
|
+
invalid_options << e.args.first
|
172
86
|
retry
|
173
87
|
end
|
174
88
|
|
175
89
|
args.concat(invalid_options)
|
176
|
-
|
177
|
-
@current_args = args
|
178
|
-
@current_options = opts
|
179
90
|
@invalid_arguments = invalid_options
|
180
91
|
|
181
|
-
@anonymous_command = [ARGV.first, *@anonymized_args].join(' ')
|
182
|
-
begin
|
183
|
-
usage_directory = "#{home_directory}/.turbot/usage"
|
184
|
-
FileUtils.mkdir_p(usage_directory)
|
185
|
-
usage_file = usage_directory << "/#{Turbot::VERSION}"
|
186
|
-
usage = if File.exists?(usage_file)
|
187
|
-
json_decode(File.read(usage_file))
|
188
|
-
else
|
189
|
-
{}
|
190
|
-
end
|
191
|
-
usage[@anonymous_command] ||= 0
|
192
|
-
usage[@anonymous_command] += 1
|
193
|
-
File.write(usage_file, json_encode(usage) + "\n")
|
194
|
-
rescue
|
195
|
-
# usage writing is not important, allow failures
|
196
|
-
end
|
197
|
-
|
198
92
|
if command
|
199
93
|
command_instance = command[:klass].new(args.dup, opts.dup)
|
200
|
-
|
201
|
-
if !@normalized_args.include?('--bot _') && (implied_bot = command_instance.bot rescue nil)
|
202
|
-
@normalized_args << '--bot _'
|
203
|
-
end
|
204
|
-
@normalized_command = [ARGV.first, @normalized_args.sort_by {|arg| arg.gsub('-', '')}].join(' ')
|
205
|
-
|
206
|
-
[ command_instance, command[:method] ]
|
94
|
+
[command_instance, command[:method]]
|
207
95
|
else
|
208
96
|
error([
|
209
97
|
"`#{cmd}` is not a turbot command.",
|
210
98
|
suggestion(cmd, commands.keys + command_aliases.keys),
|
211
|
-
|
99
|
+
'See `turbot help` for a list of available commands.'
|
212
100
|
].compact.join("\n"))
|
213
101
|
end
|
214
102
|
end
|
215
103
|
|
216
|
-
def self.run(
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
end
|
225
|
-
rescue Turbot::API::Errors::Unauthorized, RestClient::Unauthorized
|
226
|
-
puts "Authentication failure"
|
227
|
-
if ENV['TURBOT_API_KEY']
|
228
|
-
exit 1
|
104
|
+
def self.run(command, arguments=[])
|
105
|
+
object, method = prepare_run(command, arguments.dup)
|
106
|
+
object.send(method)
|
107
|
+
rescue SocketError => e
|
108
|
+
error 'Unable to connect to Turbot API, please check internet connectivity and try again.'
|
109
|
+
rescue OptionParser::ParseError
|
110
|
+
if commands[command]
|
111
|
+
run('help', [command])
|
229
112
|
else
|
230
|
-
run
|
231
|
-
retry
|
232
|
-
end
|
233
|
-
rescue Turbot::API::Errors::NotFound => e
|
234
|
-
error extract_error(e.response.body) {
|
235
|
-
e.response.body =~ /^([\w\s]+ not found).?$/ ? $1 : "Resource not found"
|
236
|
-
}
|
237
|
-
rescue RestClient::ResourceNotFound => e
|
238
|
-
error extract_error(e.http_body) {
|
239
|
-
e.http_body =~ /^([\w\s]+ not found).?$/ ? $1 : "Resource not found"
|
240
|
-
}
|
241
|
-
rescue Turbot::API::Errors::Locked => e
|
242
|
-
bot = e.response.headers[:x_confirmation_required]
|
243
|
-
if confirm_command(bot, extract_error(e.response.body))
|
244
|
-
arguments << '--confirm' << bot
|
245
|
-
retry
|
246
|
-
end
|
247
|
-
rescue RestClient::Locked => e
|
248
|
-
bot = e.response.headers[:x_confirmation_required]
|
249
|
-
if confirm_command(bot, extract_error(e.http_body))
|
250
|
-
arguments << '--confirm' << bot
|
251
|
-
retry
|
113
|
+
run('help')
|
252
114
|
end
|
253
|
-
rescue RestClient::PaymentRequired => e
|
254
|
-
# We've repurposed a 402 as a general error
|
255
|
-
error extract_error(e.http_body)
|
256
|
-
rescue Turbot::API::Errors::Timeout, RestClient::RequestTimeout
|
257
|
-
error "API request timed out. Please try again, or contact support@turbot.com if this issue persists."
|
258
|
-
rescue Turbot::API::Errors::ErrorWithResponse => e
|
259
|
-
error extract_error(e.response.body)
|
260
|
-
rescue RestClient::RequestFailed => e
|
261
|
-
error extract_error(e.http_body)
|
262
|
-
rescue CommandFailed => e
|
263
|
-
error e.message
|
264
|
-
rescue OptionParser::ParseError
|
265
|
-
commands[cmd] ? run("help", [cmd]) : run("help")
|
266
|
-
rescue Excon::Errors::SocketError, SocketError => e
|
267
|
-
error("Unable to connect to Turbot API, please check internet connectivity and try again.")
|
268
|
-
ensure
|
269
|
-
display_warnings
|
270
115
|
end
|
271
116
|
|
272
|
-
def self.
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
end
|
280
|
-
|
281
|
-
def self.parse_error_xml(body)
|
282
|
-
xml_errors = REXML::Document.new(body).elements.to_a("//errors/error")
|
283
|
-
msg = xml_errors.map { |a| a.text }.join(" / ")
|
284
|
-
return msg unless msg.empty?
|
285
|
-
rescue Exception
|
117
|
+
def self.extract_error(body, options = {})
|
118
|
+
if block_given?
|
119
|
+
default_error = yield
|
120
|
+
else
|
121
|
+
default_error = 'Internal server error'
|
122
|
+
end
|
123
|
+
parse_error_json(body) || default_error
|
286
124
|
end
|
287
125
|
|
288
126
|
def self.parse_error_json(body)
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
json.first.join(' ') # message like [['base', 'message']]
|
293
|
-
when Hash
|
294
|
-
json['error'] || json['error_message'] || json['message'] # message like {'error' => 'message'}
|
295
|
-
else
|
127
|
+
begin
|
128
|
+
JSON.load(body.to_s)['message']
|
129
|
+
rescue JSON::ParserError
|
296
130
|
nil
|
297
131
|
end
|
298
132
|
end
|
299
133
|
|
300
|
-
|
301
|
-
|
302
|
-
|
134
|
+
private
|
135
|
+
|
136
|
+
def self.suggestion(actual, possibilities)
|
137
|
+
distances = Hash.new { |hash,key| hash[key] = [] }
|
138
|
+
possibilities.each do |possibility|
|
139
|
+
distances[Text::Levenshtein.distance(actual, possibility, 4)] << possibility
|
140
|
+
end
|
141
|
+
minimum_distance = distances.keys.min
|
142
|
+
if minimum_distance < 4
|
143
|
+
suggestions = distances[minimum_distance].sort
|
144
|
+
if suggestions.length == 1
|
145
|
+
"Perhaps you meant `#{suggestions.first}`."
|
146
|
+
else
|
147
|
+
"Perhaps you meant #{suggestions[0...-1].map { |suggestion| "`#{suggestion}`" }.join(', ')} or `#{suggestions.last}`."
|
148
|
+
end
|
149
|
+
end
|
303
150
|
end
|
304
151
|
end
|
305
152
|
end
|
data/lib/turbot/command/auth.rb
CHANGED
@@ -1,85 +1,123 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
# authentication (login, logout)
|
1
|
+
#Login or logout from Turbot
|
4
2
|
#
|
5
3
|
class Turbot::Command::Auth < Turbot::Command::Base
|
6
|
-
|
7
4
|
# auth
|
8
5
|
#
|
9
|
-
#
|
6
|
+
#Login or logout. Display your Turbot API token or email address.
|
10
7
|
def index
|
11
8
|
validate_arguments!
|
12
|
-
|
13
9
|
Turbot::Command::Help.new.send(:help_for_command, current_command)
|
14
10
|
end
|
15
11
|
|
16
12
|
# auth:login
|
17
13
|
#
|
18
|
-
#
|
14
|
+
#Login to Turbot and save your Turbot credentials.
|
19
15
|
#
|
20
16
|
#Example:
|
21
17
|
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
18
|
+
# $ turbot auth:login
|
19
|
+
# Enter your Turbot email and password:
|
20
|
+
# Email: email@example.com
|
21
|
+
# Password (typing will be hidden):
|
22
|
+
# Logged in. Saved Turbot API key.
|
27
23
|
#
|
28
24
|
def login
|
29
25
|
validate_arguments!
|
30
|
-
|
31
|
-
|
32
|
-
|
26
|
+
email_address, api_key = ask_for_email_address_and_password
|
27
|
+
if api_key.empty?
|
28
|
+
error 'Authentication failed.'
|
29
|
+
end
|
30
|
+
save_netrc_entry(email_address, api_key)
|
31
|
+
puts 'Authentication successful.'
|
33
32
|
end
|
34
|
-
|
35
|
-
alias_command "login", "auth:login"
|
33
|
+
alias_command 'login', 'auth:login'
|
36
34
|
|
37
35
|
# auth:logout
|
38
36
|
#
|
39
|
-
#
|
37
|
+
#Delete your Turbot credentials.
|
40
38
|
#
|
41
39
|
#Example:
|
42
40
|
#
|
43
|
-
#
|
44
|
-
#
|
41
|
+
# $ turbot auth:logout
|
42
|
+
# Deleted Turbot credentials.
|
45
43
|
#
|
46
44
|
def logout
|
47
45
|
validate_arguments!
|
48
|
-
|
49
|
-
Turbot
|
50
|
-
display "Local credentials cleared."
|
46
|
+
delete_netrc_entry
|
47
|
+
puts 'Deleted Turbot credentials.'
|
51
48
|
end
|
52
|
-
|
53
|
-
alias_command "logout", "auth:logout"
|
49
|
+
alias_command 'logout', 'auth:logout'
|
54
50
|
|
55
51
|
# auth:token
|
56
52
|
#
|
57
|
-
#
|
53
|
+
#Display your Turbot API token.
|
58
54
|
#
|
59
55
|
#Example:
|
60
56
|
#
|
61
|
-
#
|
62
|
-
#
|
57
|
+
# $ turbot auth:token
|
58
|
+
# 93a5c45595ed37dc9d040116
|
63
59
|
#
|
64
60
|
def token
|
65
61
|
validate_arguments!
|
66
|
-
|
67
|
-
|
62
|
+
result = email_address_and_api_key[1]
|
63
|
+
if result
|
64
|
+
puts result
|
65
|
+
else
|
66
|
+
error 'not logged in'
|
67
|
+
end
|
68
68
|
end
|
69
69
|
|
70
70
|
# auth:whoami
|
71
71
|
#
|
72
|
-
#
|
72
|
+
#Display your Turbot email address.
|
73
73
|
#
|
74
74
|
#Example:
|
75
75
|
#
|
76
|
-
#
|
77
|
-
#
|
76
|
+
# $ turbot auth:whoami
|
77
|
+
# email@example.com
|
78
78
|
#
|
79
79
|
def whoami
|
80
80
|
validate_arguments!
|
81
|
+
result = email_address_and_api_key[0]
|
82
|
+
if result
|
83
|
+
puts result
|
84
|
+
else
|
85
|
+
error 'not logged in'
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
### Shell-related
|
81
92
|
|
82
|
-
|
93
|
+
# Prompts the user for an email address and password, and returns the email
|
94
|
+
# address and the user's API key.
|
95
|
+
#
|
96
|
+
# @return [Array<String>] the user's email address and API key
|
97
|
+
def ask_for_email_address_and_password
|
98
|
+
puts 'Enter your Turbot email and password.'
|
99
|
+
|
100
|
+
print 'Email: '
|
101
|
+
email_address = ask
|
102
|
+
|
103
|
+
print 'Password (typing will be hidden): '
|
104
|
+
password = running_on_windows? ? ask_for_password_on_windows : ask_for_password
|
105
|
+
|
106
|
+
puts
|
107
|
+
|
108
|
+
[email_address, get_api_key(email_address, password)]
|
83
109
|
end
|
84
110
|
|
111
|
+
def running_on_windows?
|
112
|
+
RUBY_PLATFORM =~ /mswin32|mingw32/
|
113
|
+
end
|
114
|
+
|
115
|
+
### API-related
|
116
|
+
|
117
|
+
# Gets the user's API key.
|
118
|
+
#
|
119
|
+
# @return [String] the API key, or the empty string if authentication fails
|
120
|
+
def get_api_key(email_address, password)
|
121
|
+
api.get_api_key_for_credentials(email_address, password)['api_key']
|
122
|
+
end
|
85
123
|
end
|