turbot 0.1.36 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +8 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +15 -0
  5. data/.yardopts +3 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE +22 -0
  8. data/README.md +44 -25
  9. data/Rakefile +16 -0
  10. data/appveyor.yml +35 -0
  11. data/bin/turbot +2 -16
  12. data/data/schema.json +134 -0
  13. data/{templates → data/templates}/LICENSE.txt +0 -0
  14. data/{templates → data/templates}/manifest.json +0 -0
  15. data/{templates → data/templates}/python/scraper.py +0 -0
  16. data/{templates → data/templates}/ruby/scraper.rb +0 -0
  17. data/dist/deb.rake +32 -0
  18. data/dist/gem.rake +16 -0
  19. data/dist/manifest.rake +9 -0
  20. data/dist/pkg.rake +60 -0
  21. data/dist/resources/deb/control +10 -0
  22. data/dist/resources/deb/postinst +45 -0
  23. data/dist/resources/deb/turbot +25 -0
  24. data/dist/resources/deb/turbot-release-key.txt +30 -0
  25. data/dist/resources/pkg/Distribution.erb +15 -0
  26. data/dist/resources/pkg/PackageInfo.erb +6 -0
  27. data/dist/resources/pkg/postinstall +45 -0
  28. data/dist/resources/pkg/turbot +24 -0
  29. data/dist/resources/tgz/turbot +24 -0
  30. data/dist/rpm.rake +35 -0
  31. data/dist/tgz.rake +26 -0
  32. data/dist/zip.rake +40 -0
  33. data/lib/turbot.rb +18 -15
  34. data/lib/turbot/cli.rb +10 -27
  35. data/lib/turbot/command.rb +59 -212
  36. data/lib/turbot/command/auth.rb +72 -34
  37. data/lib/turbot/command/base.rb +22 -61
  38. data/lib/turbot/command/bots.rb +251 -300
  39. data/lib/turbot/command/help.rb +57 -110
  40. data/lib/turbot/command/version.rb +6 -10
  41. data/lib/turbot/handlers/base_handler.rb +21 -0
  42. data/lib/turbot/handlers/dump_handler.rb +10 -0
  43. data/lib/turbot/handlers/preview_handler.rb +30 -0
  44. data/lib/turbot/handlers/validation_handler.rb +17 -0
  45. data/lib/turbot/helpers.rb +14 -482
  46. data/lib/turbot/helpers/api_helper.rb +41 -0
  47. data/lib/turbot/helpers/netrc_helper.rb +66 -0
  48. data/lib/turbot/helpers/shell_helper.rb +36 -0
  49. data/lib/turbot/version.rb +1 -1
  50. data/spec/fixtures/bad_permissions +0 -0
  51. data/spec/fixtures/empty +0 -0
  52. data/spec/fixtures/netrc +6 -0
  53. data/spec/spec_helper.rb +17 -219
  54. data/spec/support/bot_helper.rb +102 -0
  55. data/spec/support/command_helper.rb +20 -0
  56. data/spec/support/custom_matchers.rb +5 -0
  57. data/spec/support/fixture_helper.rb +9 -0
  58. data/spec/support/netrc_helper.rb +21 -0
  59. data/spec/turbot/command/auth_spec.rb +202 -20
  60. data/spec/turbot/command/base_spec.rb +22 -58
  61. data/spec/turbot/command/bots_spec.rb +580 -89
  62. data/spec/turbot/command/help_spec.rb +32 -75
  63. data/spec/turbot/command/version_spec.rb +11 -10
  64. data/spec/turbot/command_spec.rb +55 -87
  65. data/spec/turbot/helpers_spec.rb +28 -44
  66. data/turbot.gemspec +31 -0
  67. metadata +88 -178
  68. data/data/cacert.pem +0 -3988
  69. data/lib/turbot/auth.rb +0 -315
  70. data/lib/turbot/client.rb +0 -757
  71. data/lib/turbot/client/cisaurus.rb +0 -25
  72. data/lib/turbot/client/pgbackups.rb +0 -113
  73. data/lib/turbot/client/rendezvous.rb +0 -111
  74. data/lib/turbot/client/ssl_endpoint.rb +0 -25
  75. data/lib/turbot/client/turbot_postgresql.rb +0 -148
  76. data/lib/turbot/command/ssl.rb +0 -43
  77. data/lib/turbot/deprecated.rb +0 -5
  78. data/lib/turbot/deprecated/help.rb +0 -38
  79. data/lib/turbot/distribution.rb +0 -9
  80. data/lib/turbot/errors.rb +0 -28
  81. data/lib/turbot/excon.rb +0 -11
  82. data/lib/turbot/helpers/log_displayer.rb +0 -70
  83. data/lib/turbot/helpers/pg_dump_restore.rb +0 -115
  84. data/lib/turbot/helpers/turbot_postgresql.rb +0 -213
  85. data/lib/turbot/plugin.rb +0 -165
  86. data/lib/turbot/updater.rb +0 -171
  87. data/lib/vendor/turbot/okjson.rb +0 -598
  88. data/spec/helper/legacy_help.rb +0 -16
  89. data/spec/helper/pg_dump_restore_spec.rb +0 -67
  90. data/spec/spec.opts +0 -1
  91. data/spec/support/display_message_matcher.rb +0 -49
  92. data/spec/support/dummy_api.rb +0 -120
  93. data/spec/support/openssl_mock_helper.rb +0 -8
  94. data/spec/support/organizations_mock_helper.rb +0 -11
  95. data/spec/turbot/auth_spec.rb +0 -214
  96. data/spec/turbot/client/pgbackups_spec.rb +0 -43
  97. data/spec/turbot/client/rendezvous_spec.rb +0 -62
  98. data/spec/turbot/client/ssl_endpoint_spec.rb +0 -48
  99. data/spec/turbot/client/turbot_postgresql_spec.rb +0 -71
  100. data/spec/turbot/client_spec.rb +0 -548
  101. data/spec/turbot/helpers/turbot_postgresql_spec.rb +0 -181
  102. data/spec/turbot/plugin_spec.rb +0 -172
  103. data/spec/turbot/updater_spec.rb +0 -44
@@ -0,0 +1,41 @@
1
+ module Turbot
2
+ module Helpers
3
+ extend self
4
+
5
+ # Returns a Turbot API client.
6
+ #
7
+ # @param [String] api_key an API key
8
+ # @return [Turbot::API] a Turbot API client
9
+ def api(api_key = nil)
10
+ # For whatever reason, unless we provide a truthy API key, Turbot::API's
11
+ # initializer immediately attempts to `#get_api_key_for_credentials`.
12
+ api_key ||= email_address_and_api_key[1] || ''
13
+ turbot_api.new(turbot_api_parameters.merge(:api_key => api_key))
14
+ end
15
+
16
+ # Returns the parameters for the Turbot API, based on the base URL of the
17
+ # Turbot server.
18
+ #
19
+ # @return [Hash] the parameters for the Turbot API
20
+ def turbot_api_parameters
21
+ uri = URI.parse(host)
22
+
23
+ {
24
+ :host => uri.host,
25
+ :port => uri.port,
26
+ :scheme => uri.scheme,
27
+ }
28
+ end
29
+
30
+ # The `turbot_api` gem is slow to load, so we defer its loading.
31
+ #
32
+ # @return [Class] the Turbot::API class
33
+ def turbot_api
34
+ @turbot_api ||= begin
35
+ require 'turbot_api'
36
+
37
+ Turbot::API
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,66 @@
1
+ module Turbot
2
+ module Helpers
3
+ extend self
4
+
5
+ # Reads the user's email address and API key from either the `TURBOT_API_KEY`
6
+ # environment variable or from a `.netrc` file.
7
+ #
8
+ # @return [Array<String>] the user's email address and API key
9
+ def email_address_and_api_key
10
+ if ENV['TURBOT_API_KEY']
11
+ ['', ENV['TURBOT_API_KEY']]
12
+ elsif netrc_exists?
13
+ open_netrc["api.#{host}"] || []
14
+ else
15
+ []
16
+ end
17
+ end
18
+
19
+ # Returns the path to the `.netrc` file containing the Turbot host's entry
20
+ # with the user's email address and API key.
21
+ #
22
+ # @return [String] the path to the `.netrc` file
23
+ def netrc_path
24
+ unencrypted = Netrc.default_path
25
+ encrypted = unencrypted + '.gpg'
26
+ if File.exists?(encrypted)
27
+ encrypted
28
+ else
29
+ unencrypted
30
+ end
31
+ end
32
+
33
+ # Returns whether a `.netrc` file exists.
34
+ #
35
+ # @return [Boolean] whether a `.netrc` file exists
36
+ def netrc_exists?
37
+ File.exist?(netrc_path)
38
+ end
39
+
40
+ # Reads a `.netrc` file.
41
+ #
42
+ # @return [Netrc] the `.netrc` file
43
+ def open_netrc
44
+ begin
45
+ Netrc.read(netrc_path)
46
+ rescue Netrc::Error => e
47
+ error e.message
48
+ end
49
+ end
50
+
51
+ # Deletes the Turbot host's entry from the `.netrc` file.
52
+ def delete_netrc_entry
53
+ netrc = open_netrc
54
+ netrc.delete("api.#{host}")
55
+ netrc.save
56
+ end
57
+
58
+ # Saves the user's email address and AP key to the Turbot host's entry in the
59
+ # `.netrc` file.
60
+ def save_netrc_entry(email_address, api_key)
61
+ netrc = open_netrc
62
+ netrc["api.#{host}"] = [email_address, api_key]
63
+ netrc.save
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,36 @@
1
+ module Turbot
2
+ module Helpers
3
+ extend self
4
+
5
+ def ask
6
+ STDIN.gets.to_s.strip
7
+ end
8
+
9
+ def ask_for_password_on_windows
10
+ require 'Win32API'
11
+
12
+ password = ''
13
+
14
+ while char = Win32API.new('crtdll', '_getch', [], 'L').Call do
15
+ if char == 10 || char == 13 # received carriage return or newline
16
+ break
17
+ end
18
+ if char == 127 || char == 8 # backspace and delete
19
+ password.slice!(-1, 1)
20
+ else
21
+ # windows might throw a -1 at us so make sure to handle RangeError
22
+ (password << char.chr) rescue RangeError
23
+ end
24
+ end
25
+
26
+ password
27
+ end
28
+
29
+ def ask_for_password
30
+ system 'stty -echo'
31
+ password = ask
32
+ system 'stty echo'
33
+ password
34
+ end
35
+ end
36
+ end
@@ -1,3 +1,3 @@
1
1
  module Turbot
2
- VERSION = "0.1.36"
2
+ VERSION = '0.2.3'
3
3
  end
File without changes
File without changes
@@ -0,0 +1,6 @@
1
+ machine api.http://turbot.opencorporates.com
2
+ login email@example.com
3
+ password apikey01
4
+ machine api.http://turbot.example.com
5
+ login example@email.com
6
+ password apikey02
data/spec/spec_helper.rb CHANGED
@@ -1,227 +1,25 @@
1
- $stdin = File.new("/dev/null")
1
+ require 'rubygems'
2
2
 
3
- require "rubygems"
4
-
5
- require "simplecov"
6
- require "coveralls"
7
- SimpleCov.formatter = Coveralls::SimpleCov::Formatter
8
- SimpleCov.start do
9
- add_filter "spec"
10
- end
11
-
12
- require "excon"
13
- Excon.defaults[:mock] = true
14
-
15
- # ensure these are around for errors
16
- # as their require is generally deferred
17
- #require "turbot-api"
18
- require "rest_client"
19
-
20
- require "turbot/cli"
21
- require "rspec"
22
- require "rr"
23
- require "fakefs/safe"
24
- require 'tmpdir'
25
- require "webmock/rspec"
26
-
27
- include WebMock::API
28
-
29
- WebMock::HttpLibAdapters::ExconAdapter.disable!
30
-
31
- def api
32
- Turbot::API.new(:api_key => "pass", :mock => true)
33
- end
34
-
35
- def org_api
36
- Turbot::Client::Organizations.api(:mock => true)
37
- end
38
-
39
- def stub_api_request(method, path)
40
- stub_request(method, "http://turbot.opencorporates.com#{path}")
41
- end
42
-
43
- def prepare_command(klass)
44
- command = klass.new
45
- command.stub!(:bot).and_return("example")
46
- command.stub!(:ask).and_return("")
47
- command.stub!(:display)
48
- command.stub!(:hputs)
49
- command.stub!(:hprint)
50
- command.stub!(:turbot).and_return(mock('turbot client', :host => 'turbot.com'))
51
- command
52
- end
53
-
54
- def execute(command_line)
55
- extend RR::Adapters::RRMethods
56
-
57
- args = command_line.split(" ")
58
- command = args.shift
59
-
60
- Turbot::Command.load
61
- object, method = Turbot::Command.prepare_run(command, args)
62
-
63
- any_instance_of(Turbot::Command::Base) do |base|
64
- stub(base).bot.returns("example")
65
- end
66
-
67
- stub(Turbot::Auth).get_credentials.returns(['email@example.com', 'apikey01'])
68
- stub(Turbot::Auth).api_key.returns('apikey01')
69
-
70
- original_stdin, original_stderr, original_stdout = $stdin, $stderr, $stdout
71
-
72
- $stdin = captured_stdin = StringIO.new
73
- $stderr = captured_stderr = StringIO.new
74
- $stdout = captured_stdout = StringIO.new
75
- class << captured_stdout
76
- def tty?
77
- true
78
- end
79
- end
80
-
81
- begin
82
- object.send(method)
83
- rescue SystemExit
84
- ensure
85
- $stdin, $stderr, $stdout = original_stdin, original_stderr, original_stdout
86
- Turbot::Command.current_command = nil
87
- end
88
-
89
- [captured_stderr.string, captured_stdout.string]
90
- end
91
-
92
- def any_instance_of(klass, &block)
93
- extend RR::Adapters::RRMethods
94
- any_instance_of(klass, &block)
95
- end
96
-
97
- def run(command_line)
98
- capture_stdout do
99
- begin
100
- Turbot::CLI.start(*command_line.split(" "))
101
- rescue SystemExit
102
- end
103
- end
104
- end
105
-
106
- alias turbot run
107
-
108
- def capture_stderr(&block)
109
- original_stderr = $stderr
110
- $stderr = captured_stderr = StringIO.new
111
- begin
112
- yield
113
- ensure
114
- $stderr = original_stderr
3
+ unless RUBY_PLATFORM =~ /mswin32|mingw32/
4
+ require 'simplecov'
5
+ require 'coveralls'
6
+ SimpleCov.formatter = Coveralls::SimpleCov::Formatter
7
+ SimpleCov.start do
8
+ add_filter 'spec'
115
9
  end
116
- captured_stderr.string
117
10
  end
118
11
 
119
- def capture_stdout(&block)
120
- original_stdout = $stdout
121
- $stdout = captured_stdout = StringIO.new
122
- begin
123
- yield
124
- ensure
125
- $stdout = original_stdout
126
- end
127
- captured_stdout.string
128
- end
12
+ require 'rspec'
13
+ require 'webmock/rspec'
129
14
 
130
- def fail_command(message)
131
- raise_error(Turbot::Command::CommandFailed, message)
132
- end
133
-
134
- def stub_core
135
- @stubbed_core ||= begin
136
- stubbed_core = nil
137
- any_instance_of(Turbot::Client) do |core|
138
- stubbed_core = stub(core)
139
- end
140
- stub(Turbot::Auth).user.returns("email@example.com")
141
- stub(Turbot::Auth).password.returns("pass")
142
- stub(Turbot::Client).auth.returns("apikey01")
143
- stubbed_core
144
- end
145
- end
146
-
147
- def stub_pg
148
- @stubbed_pg ||= begin
149
- stubbed_pg = nil
150
- any_instance_of(Turbot::Client::TurbotPostgresql) do |pg|
151
- stubbed_pg = stub(pg)
152
- end
153
- stubbed_pg
154
- end
155
- end
156
-
157
- def stub_pgbackups
158
- @stubbed_pgbackups ||= begin
159
- stubbed_pgbackups = nil
160
- any_instance_of(Turbot::Client::Pgbackups) do |pgbackups|
161
- stubbed_pgbackups = stub(pgbackups)
162
- end
163
- stubbed_pgbackups
164
- end
165
- end
166
-
167
- def stub_rendezvous
168
- @stubbed_rendezvous ||= begin
169
- stubbed_rendezvous = nil
170
- any_instance_of(Turbot::Client::Rendezvous) do |rendezvous|
171
- stubbed_rendezvous = stub(rendezvous)
172
- end
173
- stubbed_rendezvous
174
- end
175
- end
176
-
177
- def stub_cisaurus
178
- @stub_cisaurus ||= begin
179
- stub_cisaurus = nil
180
- any_instance_of(Turbot::Client::Cisaurus) do |cisaurus|
181
- stub_cisaurus = stub(cisaurus)
182
- end
183
- stub_cisaurus
184
- end
185
- end
186
-
187
- def with_blank_git_repository(&block)
188
- sandbox = File.join(Dir.tmpdir, "turbot", Process.pid.to_s)
189
- FileUtils.mkdir_p(sandbox)
190
-
191
- old_dir = Dir.pwd
192
- Dir.chdir(sandbox)
193
-
194
- `git init`
195
- block.call
196
-
197
- FileUtils.rm_rf(sandbox)
198
- ensure
199
- Dir.chdir(old_dir)
200
- end
201
-
202
- module SandboxHelper
203
- def bash(cmd)
204
- `#{cmd}`
205
- end
206
- end
207
-
208
- require "turbot/helpers"
209
- module Turbot::Helpers
210
- @home_directory = Dir.mktmpdir
211
- undef_method :home_directory
212
- def home_directory
213
- @home_directory
214
- end
215
- end
15
+ include WebMock::API
216
16
 
217
- require "support/display_message_matcher"
218
- require "support/organizations_mock_helper"
219
- require "support/dummy_api"
17
+ Dir['./spec/support/**/*.rb'].sort.each { |f| require f}
18
+ require File.dirname(__FILE__) + '/../lib/turbot'
220
19
 
221
- RSpec.configure do |config|
222
- config.color_enabled = true
223
- config.include DisplayMessageMatcher
224
- config.order = 'rand'
225
- config.before { Turbot::Helpers.error_with_failure = false }
226
- config.after { RR.reset }
20
+ RSpec.configure do |c|
21
+ c.include(BotHelper)
22
+ c.include(CommandHelper)
23
+ c.include(FixtureHelper)
24
+ c.include(NetrcHelper)
227
25
  end
@@ -0,0 +1,102 @@
1
+ module BotHelper
2
+ def valid_manifest
3
+ {
4
+ 'bot_id' => 'example',
5
+ 'data_type' => 'dummy',
6
+ 'files' => ['scraper.rb'],
7
+ 'identifying_fields' => ['name'],
8
+ 'language' => 'ruby',
9
+ 'publisher' => {},
10
+ }
11
+ end
12
+
13
+ # API
14
+
15
+ def stub_bot_info(bot = 'example')
16
+ stub_request(:get, "http://turbot.opencorporates.com/api/bots/#{bot}?api_key=apikey01").to_return({
17
+ :status => 200,
18
+ :body => JSON.dump({
19
+ 'data' => {
20
+ 'bot_id' => 'dummy_bot',
21
+ 'created_at' => '2010-01-01T00:00:00.000Z',
22
+ 'updated_at' => '2010-01-02T00:00:00.000Z',
23
+ 'state' => 'scheduled',
24
+ }
25
+ }),
26
+ })
27
+ end
28
+
29
+ def stub_bot_info_error(bot = 'example')
30
+ stub_request(:get, "http://turbot.opencorporates.com/api/bots/#{bot}?api_key=apikey01").to_return({
31
+ :status => 402,
32
+ :body => JSON.dump({
33
+ 'error_code' => 'bot-not-found',
34
+ 'message' => "No bot registered for bot_id example\nIf you have renamed your bot, ...",
35
+ }),
36
+ })
37
+ end
38
+
39
+ def stub_preview
40
+ stub_request(:put, 'http://turbot.opencorporates.com/api/bots/example').to_return(:status => 200, :body => '{}')
41
+ stub_request(:delete, 'http://turbot.opencorporates.com/api/bots/example/draft_data?api_key=apikey01').to_return(:status => 200, :body => '{}')
42
+ stub_request(:post, 'http://turbot.opencorporates.com/api/bots/example/draft_data').to_return({
43
+ :status => 200,
44
+ :body => JSON.dump({
45
+ 'data' => {
46
+ 'url' => 'http://example.com/',
47
+ },
48
+ }),
49
+ })
50
+ end
51
+
52
+ # Filesystem
53
+
54
+ def create_bot_directory(working_directory = nil)
55
+ bot_directory = File.join(working_directory || Dir.mktmpdir, 'example')
56
+ Dir.mkdir(bot_directory)
57
+ bot_directory
58
+ end
59
+
60
+ def create_manifest_file(bot_directory, data = nil)
61
+ data ||= JSON.dump(valid_manifest)
62
+
63
+ File.open(File.join(bot_directory, 'manifest.json'), 'w') do |f|
64
+ f.write(data)
65
+ end
66
+ end
67
+
68
+ def create_scraper_file(bot_directory, records = [{'name' => 'foo'}])
69
+ File.open(File.join(bot_directory, 'scraper.rb'), 'w') do |f|
70
+ f.write("require 'json'\n")
71
+ records.each do |record|
72
+ f.write("puts JSON.dump(#{record.inspect})\n")
73
+ end
74
+ end
75
+ end
76
+
77
+ def create_broken_scraper_file(bot_directory)
78
+ File.open(File.join(bot_directory, 'scraper.rb'), 'w') do |f|
79
+ f.write("class ThisErrorIsExpected < StandardError; end\n")
80
+ f.write("raise ThisErrorIsExpected\n")
81
+ end
82
+ end
83
+
84
+ # TurbotRunner
85
+
86
+ def set_turbot_runner_schemas
87
+ TurbotRunner::SCHEMAS_PATH.replace(File.expand_path(File.join('..', '..', 'schemas'), __FILE__))
88
+ end
89
+
90
+ # Testing
91
+
92
+ def execute_in_directory(command, directory)
93
+ allow_any_instance_of(Turbot::Command::Base).to receive(:working_directory).and_return(directory)
94
+ stderr, stdout = execute(command)
95
+ restore_working_directory_method
96
+ [stderr, stdout]
97
+ end
98
+
99
+ def restore_working_directory_method
100
+ allow_any_instance_of(Turbot::Command::Base).to receive(:working_directory).and_return(Dir.pwd)
101
+ end
102
+ end