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.
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