mode 0.0.17 → 0.0.18

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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -134
  3. data/lib/connect.rb +5 -5
  4. data/lib/mode.rb +12 -8
  5. data/lib/mode/api/form.rb +30 -8
  6. data/lib/mode/api/request.rb +34 -16
  7. data/lib/mode/commands/connect.rb +0 -8
  8. data/lib/mode/commands/import.rb +1 -1
  9. data/lib/mode/config.rb +9 -1
  10. data/lib/mode/connector/commands/select_report_run_dataset.rb +84 -0
  11. data/lib/mode/connector/commands/select_table_metadata.rb +113 -0
  12. data/lib/mode/connector/daemon.rb +3 -3
  13. data/lib/mode/connector/data_sources/base.rb +191 -0
  14. data/lib/mode/connector/databases/rdbms.rb +69 -0
  15. data/lib/mode/connector/dataset.rb +0 -1
  16. data/lib/mode/connector/dispatcher.rb +27 -0
  17. data/lib/mode/connector/poller.rb +2 -3
  18. data/lib/mode/connector/registrar.rb +74 -16
  19. data/lib/mode/connector/scheduler.rb +24 -15
  20. data/lib/mode/connector/selector.rb +1 -0
  21. data/lib/mode/connector/tables/rdbms.rb +130 -0
  22. data/lib/mode/version.rb +2 -2
  23. data/mode.gemspec +2 -0
  24. data/script/console.rb +11 -0
  25. data/spec/api/form_spec.rb +17 -8
  26. data/spec/api/request_spec.rb +3 -3
  27. data/spec/commands/connect_spec.rb +1 -10
  28. data/spec/config_spec.rb +1 -1
  29. data/spec/connector/commands/select_report_run_dataset_spec.rb +96 -0
  30. data/spec/connector/commands/select_table_metadata_spec.rb +115 -0
  31. data/spec/connector/{data_source_spec.rb → data_sources/base_spec.rb} +8 -8
  32. data/spec/connector/databases/rdbms_spec.rb +43 -0
  33. data/spec/connector/dispatcher_spec.rb +47 -0
  34. data/spec/connector/poller_spec.rb +2 -1
  35. data/spec/connector/registrar_spec.rb +111 -26
  36. data/spec/connector/scheduler_spec.rb +12 -31
  37. data/spec/connector/selector_spec.rb +1 -1
  38. data/spec/connector/tables/rdbms_spec.rb +85 -0
  39. metadata +49 -15
  40. data/lib/mode/connector/connect.rb +0 -11
  41. data/lib/mode/connector/data_source.rb +0 -171
  42. data/lib/mode/connector/message.rb +0 -31
  43. data/lib/mode/connector/processor.rb +0 -58
  44. data/lib/mode/connector/uploader.rb +0 -54
  45. data/spec/connector/message_spec.rb +0 -22
  46. data/spec/connector/processor_spec.rb +0 -93
  47. data/spec/connector/uploader_spec.rb +0 -57
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 74f1b2ce9baad12179eacc6a688af0cc4c1a63ea
4
- data.tar.gz: 3d8f7f5cab8366b0eb3bf454c62e4374ce9fccf3
3
+ metadata.gz: ba4667740570363fcc09c91a5ab6306678f54731
4
+ data.tar.gz: 9d1e27811b305bd7f81da09fdb0794583852744e
5
5
  SHA512:
6
- metadata.gz: 1e288584297b41d8e45ce8886b987531dc5aa77650a9dc188426e25c1b1f47727fd7b6c92a378bad2c3df863c6ddf4671eddb5f48e2b3cea55635cd2da158061
7
- data.tar.gz: b091fee08b2215bb46ead6ec37c207db6641f53fa4b71b8a59e012f930d998dfb22d438211ded8f4b7997d0c090f98854914a7d25bdc463283ab5cbdc1895cca
6
+ metadata.gz: 6a820c70b52f95e12f71c7a50a37975038986ebe83cdd7769c778f6ee6d60159187d6d42ad78005ef01f045133217203540e63f99edcb7e4fcc28c913b854f76
7
+ data.tar.gz: dfd181018bf5f35d3b5c5f1f41dc8713daa8b1291f4fcd75fc2609e41796b38fa4dfd2e8c208dbaea1c731e9430fa106595816e629a4116170058a0b9408ca14
data/README.md CHANGED
@@ -2,139 +2,7 @@
2
2
 
3
3
  This gem provides command line tools for interacting with the Mode Analytics APIs.
4
4
 
5
- [![Build Status](https://magnum.travis-ci.com/mode/mode-ruby.png?token=i2TyUW8sMD41B46pRCpz&branch=master)](https://magnum.travis-ci.com/mode/mode-ruby)
5
+ [![Build Status](https://travis-ci.org/mode/mode-ruby.png?branch=v0.0.17)](https://travis-ci.org/mode/mode-ruby)
6
6
  [![Code Climate](https://codeclimate.com/repos/52a90897f3ea0044b10034de/badges/68f57393128c9c3fe2c5/gpa.png)](https://codeclimate.com/repos/52a90897f3ea0044b10034de/feed)
7
7
 
8
-
9
- ## Install Mode
10
-
11
- **Mode requires Ruby 1.9 or JRuby 1.7 or newer**
12
-
13
- For the best performance and compatibility we recommend JRuby.
14
-
15
- If you don't currently have a suitable ruby or aren't sure then follow [these directions](doc/install_ruby.md) to install it before continuing.
16
-
17
- ```
18
- gem install mode
19
- ```
20
-
21
- ## Logging In
22
-
23
- Before you use the mode gem you'll need to login.
24
-
25
- The login process allows you to authorize the machine to connect via
26
- the API with the use of an API access token. The first time you use this
27
- command the it will look as follows:
28
-
29
- ```
30
- $ mode login
31
- Enter your Mode credentials:
32
- Username: besquared
33
- Password:
34
-
35
- No API tokens found, would you like to create a new token? [y/n] y
36
-
37
- Choose a token name: Connector
38
- Updated configuration at /Users/josh/.mode/config.yml
39
- ```
40
-
41
- The token name is just a descriptive name that will help you remember what the token is used for.
42
-
43
- Tokens can be renamed or deleted at any time from your account settings page in Mode.
44
-
45
- ## Adding Data Sources
46
-
47
- Open the Mode configuration file in your favorite text editor (I'm using sublime text)
48
-
49
- ```
50
- $ subl ~/.mode/config.yml
51
- ```
52
-
53
- A sample data sources configuration is listed which you can copy to the bottom of your config file and modify:
54
-
55
- ```
56
- data_sources:
57
- development:
58
- adapter: jdbc:postgresql
59
- host: localhost
60
- database: development
61
- username: postgres
62
- password:
63
-
64
- warehouse:
65
- adapter: jdbc:redshift
66
- host: hostname.redshift.amazonaws.com
67
- port: 5439
68
- database: dev
69
- username:
70
- password:
71
- ```
72
-
73
- ## Database Drivers
74
-
75
- If you're using JRuby then you can load JDBC drivers by copying the driver's jar files into Mode's drivers directory
76
-
77
- Example for teradata:
78
-
79
- ```
80
- cp terajdbc4.jar ~/mode/drivers
81
- cp tdgssconfig.jar ~/mode/drivers
82
- ```
83
-
84
- For ruby1.9+ you need to install the correct driver gem and libraries
85
-
86
- ```
87
- # PostgreSQL
88
- gem install pg
89
-
90
- # Redshift
91
- gem install sequel_redshift
92
-
93
- # MySQL
94
- gem install mysql2
95
-
96
- # Oracle 9i+
97
- gem install oci8
98
-
99
- # SQL Server & Azure
100
- gem install tiny_tds
101
-
102
- # DB2
103
- gem install ibm_db
104
- ```
105
-
106
- ## Verifying your API and driver configuration
107
-
108
- You can verify that your data sources are correct by using the verify command:
109
-
110
- ```
111
- $ mode connect verify
112
- ```
113
-
114
- ## Controlling the connector
115
-
116
- Starting
117
-
118
- ```
119
- $ mode connect start
120
- ```
121
-
122
- Restarting
123
-
124
- ```
125
- $ mode connect restart
126
- ```
127
-
128
- Stopping
129
-
130
- ```
131
- $ mode connect stop
132
- ```
133
-
134
- ## Connector logging
135
-
136
- The connect logs all its activity and errors to a log file that rotates weekly by default.
137
-
138
- ```
139
- tail -f ~/.mode/log/mode.log
140
- ```
8
+ To learn how to install and use this gem please visit [Mode Analytics Help](http://help.modeanalytics.com)
@@ -4,21 +4,21 @@ $LOAD_PATH.unshift File.dirname(__FILE__)
4
4
 
5
5
  require 'mode'
6
6
 
7
- runner = Mode::Connector::Daemon.new(:max_jobs => ARGV[0] || 4)
7
+ daemon = Mode::Connector::Daemon.new(:max_jobs => ARGV[0] || 4)
8
8
 
9
9
  trap("INT") do
10
10
  Mode::Logger.instance.info("connect.rb", "Received INT signal, shutting down.")
11
- runner.stop
11
+ daemon.stop
12
12
  end
13
13
 
14
14
  trap("HUP") do
15
15
  Mode::Logger.instance.info("connect.rb", "Received HUP signal, shutting down.")
16
- runner.stop
16
+ daemon.stop
17
17
  end
18
18
 
19
19
  trap("TERM") do
20
20
  Mode::Logger.instance.info("connect.rb", "Received TERM signal, shutting down.")
21
- runner.stop
21
+ daemon.stop
22
22
  end
23
23
 
24
- runner.start
24
+ daemon.start
@@ -30,19 +30,23 @@ require 'mode/api/request'
30
30
 
31
31
  # Core
32
32
  require 'mode/connector/type_map'
33
- require 'mode/connector/data_source'
33
+ require 'mode/connector/tables/rdbms'
34
+ require 'mode/connector/databases/rdbms'
35
+ require 'mode/connector/data_sources/base'
34
36
 
35
- # Operations
37
+ # Models
38
+ require 'mode/connector/dataset'
39
+
40
+ # Commands
41
+ require 'mode/connector/commands/select_table_metadata'
42
+ require 'mode/connector/commands/select_report_run_dataset'
43
+
44
+ # Core Operations
36
45
  require 'mode/connector/registrar'
37
46
  require 'mode/connector/scheduler'
38
47
  require 'mode/connector/poller'
39
- require 'mode/connector/processor'
40
48
  require 'mode/connector/selector'
41
- require 'mode/connector/uploader'
42
-
43
- # Models
44
- require 'mode/connector/dataset'
45
- require 'mode/connector/message'
49
+ require 'mode/connector/dispatcher'
46
50
 
47
51
  # Daemon
48
52
  require 'mode/connector/daemon'
@@ -22,32 +22,54 @@ module Mode
22
22
  def submit!(params = {})
23
23
  inputs = content['input']
24
24
  params = input_values(inputs, params)
25
- Mode::API::Request.send(method.to_sym, action, params)
25
+ Mode::API::Request.send(method.to_sym, action, params, request_opts)
26
26
  end
27
27
 
28
28
  private
29
29
 
30
+ def request_opts
31
+ {
32
+ :content_type => content_type
33
+ }.delete_if{|k, v| v.nil? }
34
+ end
35
+
36
+ def content_type
37
+ content['content_type']
38
+ end
39
+
30
40
  def input_values(inputs, params = {})
31
41
  merged = {}
32
42
  return merged if inputs.nil?
33
43
 
34
44
  inputs.each do |name, value|
35
- if value.instance_of?(Hash)
36
- if value.has_key?('value')
37
- # we reached a leaf
38
- merged[name] = params[name] || value['value']
45
+ if name =~ /\[\]$/
46
+ clean_name = name.gsub(/\[\]$/, '')
47
+ param_value = params[clean_name.to_sym]
48
+
49
+ merged[clean_name] = param_value.map do |item|
50
+ input_values(value, item)
51
+ end unless param_value.nil?
52
+
53
+ elsif value.instance_of?(Hash)
54
+ param_value = params[name.to_sym]
55
+
56
+ if is_leaf?(value)
57
+ merged[name] = param_value.nil? ? value['value'] : param_value
39
58
  else
40
- # we're at an intermediate node
41
- merged[name] = input_values(value, params[name])
59
+ merged[name] = input_values(value, param_value) unless param_value.nil?
42
60
  end
43
61
  else
44
- # non-field node
62
+ # non-field node (WHAT DO?)
45
63
  # merged[name] = params[name]
46
64
  end
47
65
  end
48
66
 
49
67
  merged
50
68
  end
69
+
70
+ def is_leaf?(value)
71
+ value.find{ |k, v| v.instance_of?(Hash) }.nil?
72
+ end
51
73
  end
52
74
  end
53
75
  end
@@ -1,6 +1,7 @@
1
1
  require 'uri'
2
2
  require 'json'
3
3
  require 'faraday'
4
+ require 'faraday_middleware'
4
5
 
5
6
  module Mode
6
7
  module API
@@ -13,11 +14,16 @@ module Mode
13
14
  @params = params
14
15
  end
15
16
 
16
- def perform(request_opts = {})
17
+ def perform(opts = {})
17
18
  response = http.send(method.to_sym) do |request|
18
19
  request.url path
19
20
  request.body = params unless params.empty?
20
- request.options[:timeout] = request_opts.fetch(:timeout, 30)
21
+
22
+ if opts[:content_type]
23
+ request.headers['Content-Type'] = opts[:content_type]
24
+ end
25
+
26
+ request.options[:timeout] = opts.fetch(:timeout, 30)
21
27
  end
22
28
 
23
29
  response.success? ? success(response) : error(response)
@@ -56,7 +62,7 @@ module Mode
56
62
  response_lines = response.body.split("\n")
57
63
 
58
64
  Mode::Logger.instance.send(level,
59
- "API::Request", "#{response.status}",
65
+ self.class.name, "#{response.status}",
60
66
  ["HOST #{self.class.base_url}", "#{method.upcase} #{path}", *response_lines])
61
67
  end
62
68
 
@@ -104,24 +110,28 @@ module Mode
104
110
  # Request Methods
105
111
  #
106
112
 
107
- def head(path)
108
- new(:head, resolve_path(path)).perform
113
+ def head(path, opts = {})
114
+ new(:head, resolve_path(path)).perform(opts)
115
+ end
116
+
117
+ def get(path, params = {}, opts = {})
118
+ new(:get, resolve_path(path), params).perform(opts)
109
119
  end
110
120
 
111
- def get(path, params = {})
112
- new(:get, resolve_path(path), params).perform
121
+ def post(path, params = {}, opts = {})
122
+ new(:post, resolve_path(path), params).perform(opts)
113
123
  end
114
124
 
115
- def post(path, params = {})
116
- new(:post, resolve_path(path), params).perform
125
+ def put(path, params = {}, opts = {})
126
+ new(:put, resolve_path(path), params).perform(opts)
117
127
  end
118
128
 
119
- def put(path, params = {})
120
- new(:put, resolve_path(path), params).perform
129
+ def patch(path, params = {}, opts = {})
130
+ new(:patch, resolve_path(path), params).perform(opts)
121
131
  end
122
132
 
123
- def delete(path, params = {})
124
- new(:delete, resolve_path(path), params).perform
133
+ def delete(path, params = {}, opts = {})
134
+ new(:delete, resolve_path(path), params).perform(opts)
125
135
  end
126
136
 
127
137
  def resolve_path(path)
@@ -140,10 +150,12 @@ module Mode
140
150
  "#{base_path}/packages"
141
151
  end
142
152
 
153
+ # user.access_tokens
143
154
  def access_tokens_path
144
155
  "#{base_path}/access_tokens"
145
156
  end
146
157
 
158
+ # access_token.data_source_connections
147
159
  def data_source_connections_path
148
160
  "#{base_path}/data_source_connections"
149
161
  end
@@ -153,6 +165,7 @@ module Mode
153
165
  [data_source_connections_path, token].join('/').strip
154
166
  end
155
167
 
168
+ # connection.links('messages').follow()
156
169
  def data_source_connection_messages_path
157
170
  [data_source_connection_path, 'messages'].join('/').strip
158
171
  end
@@ -162,10 +175,15 @@ module Mode
162
175
  #
163
176
  def http(options = {})
164
177
  @_http ||= Faraday.new(:url => base_url) do |builder|
165
- builder.request :multipart # adds small overhead to each request
178
+ builder.request :multipart # adds small overhead to each request
166
179
  builder.request :url_encoded
167
- builder.adapter Faraday.default_adapter
180
+ builder.request :json
181
+
168
182
  builder.basic_auth(username, password)
183
+
184
+ builder.use FaradayMiddleware::FollowRedirects, limit: 5
185
+
186
+ builder.adapter Faraday.default_adapter
169
187
  end
170
188
  end
171
189
 
@@ -197,7 +215,7 @@ module Mode
197
215
  when :staging
198
216
  "staging.modeanalytics.com"
199
217
  else
200
- "stealth.modeanalytics.com"
218
+ "modeanalytics.com"
201
219
  end
202
220
  end
203
221
 
@@ -14,8 +14,6 @@ module Mode
14
14
 
15
15
  def execute(options = {})
16
16
  validate_config!
17
-
18
- register!
19
17
  run_command!
20
18
  end
21
19
 
@@ -30,12 +28,6 @@ module Mode
30
28
 
31
29
  private
32
30
 
33
- def register!
34
- if ['start', 'restart'].include?(command)
35
- Mode::Connector::Registrar.new(configuration).perform!
36
- end
37
- end
38
-
39
31
  def run_command!
40
32
  if command == 'status'
41
33
  daemon.alive?
@@ -64,7 +64,7 @@ module Mode
64
64
  end
65
65
 
66
66
  def submit_import_form(resource, params)
67
- resource.forms('import').submit!('import' => params)
67
+ resource.forms('import').submit!(:import => params)
68
68
  end
69
69
 
70
70
  def parse_uploaded_response(content)
@@ -56,6 +56,14 @@ module Mode
56
56
  new(path, filename)
57
57
  end
58
58
 
59
+ def load_drivers!
60
+ if RUBY_PLATFORM == 'java'
61
+ Dir[File.join(drivers_dir, '*.jar')].each do |driver|
62
+ load driver
63
+ end
64
+ end
65
+ end
66
+
59
67
  def default_dir
60
68
  File.expand_path("~/.mode")
61
69
  end
@@ -82,7 +90,7 @@ module Mode
82
90
 
83
91
  @data_sources ||= []
84
92
  (config['data_sources'] || []).each do |name, props|
85
- @data_sources << Mode::Connector::DataSource.new(name, props)
93
+ @data_sources << Mode::Connector::DataSources::Base.build(name, props)
86
94
  end
87
95
  end
88
96