drill-sergeant 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 49028dfe96747f9e9597e498c53ed2ca72ff2d7af184d4823cc73679998c91c5
4
- data.tar.gz: b0d1b5d1da91f2ee15c6f34f8a415fffe8d546e9bdf71c91cf39c38fb5905a52
3
+ metadata.gz: 4a3ea03aaaf7870b45a5fcf70d42a3dc471f8475daef5322ea988f253ed85f30
4
+ data.tar.gz: 1f1400fceea93d5a2f17c0ca39df950dc2d0db7fa4048821d9b89e9ac675e088
5
5
  SHA512:
6
- metadata.gz: 51369b3960b21262523dd62b157cf22af3d8c634c2ef235dc7f67d5ade8443e2e22a52e71945b008ec78661d4fd217900e389ab93a883b1c8e900d5b6b913bea
7
- data.tar.gz: 05feeba2d6047c508e9b6c9bb4efeb224940c779010c063bdf81e7ed76713261ccfff3d18f78eaae28af0e724a44c41ae1235a185719a7c7f734f1c8d245a06b
6
+ metadata.gz: feaa39c2ca86d34d7468a229f8371396b4f26dc560584181975d8fa28d36d8ab3d19456493d9fb92f6953b8f8c4741a66e4922472f62f94c30188017c57ab417
7
+ data.tar.gz: 486ea96149e0b3cfe321797fd1f0083e6ba83f19afed099476d1eae4d1f54e053c985b6c0963f66d932aad90cfaef2070ef4eb71d1a6ea255cce631352da8ce9
data/CHANGELOG.md CHANGED
@@ -1,12 +1,29 @@
1
- ## 0.1.2
1
+ ## 0.2.0 (2022-08-28)
2
+
3
+ - Added support for basic authentication
4
+ - Added `update_storage` and `delete_storage` methods
5
+ - Added `enable_storage` and `disable_storage` methods
6
+ - Added `cancel_query` method
7
+ - Dropped support for Ruby < 2.7
8
+
9
+ ## 0.1.4 (2022-01-16)
10
+
11
+ - Added `server_version` method
12
+ - Fixed error with failed queries with Drill 1.19+
13
+
14
+ ## 0.1.3 (2019-08-10)
15
+
16
+ - Added more endpoints
17
+
18
+ ## 0.1.2 (2018-07-22)
2
19
 
3
20
  - Added support for HTTPS
4
21
  - Added `open_timeout` and `read_timeout` options
5
22
 
6
- ## 0.1.1
23
+ ## 0.1.1 (2017-03-24)
7
24
 
8
25
  - Return columns in correct order
9
26
 
10
- ## 0.1.0
27
+ ## 0.1.0 (2017-03-24)
11
28
 
12
29
  - First release
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2017-2022 Andrew Kane
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,27 +1,30 @@
1
- # Drill Sergeant
1
+ # Drill Ruby
2
2
 
3
3
  Ruby client for Apache Drill
4
4
 
5
+ [![Build Status](https://github.com/ankane/drill-ruby/workflows/build/badge.svg?branch=master)](https://github.com/ankane/drill-ruby/actions)
6
+
5
7
  ## Installation
6
8
 
7
- First, [download Apache Drill](https://drill.apache.org/docs/installing-drill-on-linux-and-mac-os-x/). Start it with:
9
+ First, [install Apache Drill](https://drill.apache.org/docs/install-drill-introduction/). For Homebrew, use:
8
10
 
9
11
  ```sh
10
- bin/drill-embedded
12
+ brew install apache-drill
13
+ drill-embedded
11
14
  ```
12
15
 
13
- Then add this line to your application’s Gemfile:
16
+ And add this line to your application’s Gemfile:
14
17
 
15
18
  ```ruby
16
- gem 'drill-sergeant'
19
+ gem "drill-sergeant"
17
20
  ```
18
21
 
19
- ## How to Use
22
+ ## Getting Started
20
23
 
21
24
  Create a client
22
25
 
23
26
  ```ruby
24
- drill = Drill.new(url: "http://localhost:8047")
27
+ drill = Drill::Client.new(url: "http://localhost:8047")
25
28
  ```
26
29
 
27
30
  And query away
@@ -30,23 +33,134 @@ And query away
30
33
  drill.query("SELECT * FROM dfs.`/path/to/some/file.csvh`")
31
34
  ```
32
35
 
36
+ ## Endpoints
37
+
38
+ [API docs](https://drill.apache.org/docs/rest-api-introduction/)
39
+
40
+ ### Query
41
+
42
+ Run a query
43
+
44
+ ```ruby
45
+ drill.query(
46
+ query,
47
+ limit: nil,
48
+ default_schema: nil,
49
+ username: nil
50
+ )
51
+ ```
52
+
53
+ ### Profiles
54
+
55
+ Get profiles of running and completed queries
56
+
57
+ ```ruby
58
+ drill.profiles
59
+ ```
60
+
61
+ Get the profile of a query
62
+
63
+ ```ruby
64
+ drill.profiles(query_id)
65
+ ```
66
+
67
+ Cancel a query
68
+
69
+ ```ruby
70
+ drill.cancel_query(query_id)
71
+ ```
72
+
73
+ ### Storage
74
+
75
+ List storage plugins
76
+
77
+ ```ruby
78
+ drill.storage
79
+ ```
80
+
81
+ Get a storage plugin by name
82
+
83
+ ```ruby
84
+ drill.storage(name)
85
+ ```
86
+
87
+ Enable a storage plugin
88
+
89
+ ```ruby
90
+ drill.enable_storage(name)
91
+ ```
92
+
93
+ Disable a storage plugin
94
+
95
+ ```ruby
96
+ drill.disable_storage(name)
97
+ ```
98
+
99
+ Create or update a storage plugin
100
+
101
+ ```ruby
102
+ drill.update_storage(
103
+ name,
104
+ type: nil,
105
+ enabled: nil,
106
+ connection: nil,
107
+ workspaces: nil,
108
+ formats: nil
109
+ )
110
+ ```
111
+
112
+ Delete a storage plugin
113
+
114
+ ```ruby
115
+ drill.delete_storage(name)
116
+ ```
117
+
118
+ ### Info
119
+
120
+ Get cluster info
121
+
122
+ ```ruby
123
+ drill.cluster
124
+ ```
125
+
126
+ Get metrics
127
+
128
+ ```ruby
129
+ drill.metrics
130
+ ```
131
+
132
+ Get options
133
+
134
+ ```ruby
135
+ drill.options
136
+ ```
137
+
33
138
  ## Reference
34
139
 
35
140
  Set timeouts
36
141
 
37
142
  ```ruby
38
- Drill.new(open_timeout: 5, read_timeout: 120)
143
+ Drill::Client.new(open_timeout: 5, read_timeout: 120)
39
144
  ```
40
145
 
41
146
  ## History
42
147
 
43
- View the [changelog](https://github.com/ankane/drill-sergeant/blob/master/CHANGELOG.md)
148
+ View the [changelog](CHANGELOG.md)
44
149
 
45
150
  ## Contributing
46
151
 
47
152
  Everyone is encouraged to help improve this project. Here are a few ways you can help:
48
153
 
49
- - [Report bugs](https://github.com/ankane/drill-sergeant/issues)
50
- - Fix bugs and [submit pull requests](https://github.com/ankane/drill-sergeant/pulls)
154
+ - [Report bugs](https://github.com/ankane/drill-ruby/issues)
155
+ - Fix bugs and [submit pull requests](https://github.com/ankane/drill-ruby/pulls)
51
156
  - Write, clarify, or fix documentation
52
157
  - Suggest or add new features
158
+
159
+ To get started with development:
160
+
161
+ ```sh
162
+ git clone https://github.com/ankane/drill-ruby.git
163
+ cd drill-ruby
164
+ bundle install
165
+ bundle exec rake test
166
+ ```
@@ -0,0 +1,164 @@
1
+ module Drill
2
+ class Client
3
+ HEADERS = {
4
+ "Content-Type" => "application/json",
5
+ "Accept" => "application/json"
6
+ }
7
+
8
+ def initialize(url: nil, open_timeout: 3, read_timeout: nil)
9
+ url ||= ENV["DRILL_URL"] || "http://localhost:8047"
10
+ # remove trailing slash
11
+ @uri = URI.parse(url.chomp("/"))
12
+ @http = Net::HTTP.new(@uri.host, @uri.port)
13
+ @http.use_ssl = true if @uri.scheme == "https"
14
+ @http.open_timeout = open_timeout if open_timeout
15
+ @http.read_timeout = read_timeout if read_timeout
16
+ end
17
+
18
+ def query(statement, limit: nil, default_schema: nil, username: nil)
19
+ options = {}
20
+ if Gem::Version.new(server_version) >= Gem::Version.new("1.19.0")
21
+ options["drill.exec.http.rest.errors.verbose"] = true
22
+ end
23
+
24
+ data = {
25
+ query: statement,
26
+ options: options
27
+ }
28
+ data[:autoLimit] = limit if limit
29
+ data[:defaultSchema] = default_schema if default_schema
30
+ data[:userName] = username if username
31
+
32
+ run_query(data)
33
+ end
34
+
35
+ def profiles(query_id = nil)
36
+ path = query_id ? "profiles/#{escape_path(query_id)}.json" : "profiles.json"
37
+ get(path)
38
+ end
39
+
40
+ def cancel_query(query_id)
41
+ get("profiles/cancel/#{escape_path(query_id)}")
42
+ end
43
+
44
+ def storage(name = nil)
45
+ path = name ? "storage/#{escape_path(name)}.json" : "storage.json"
46
+ get(path)
47
+ end
48
+
49
+ def enable_storage(name)
50
+ get("storage/#{escape_path(name)}/enable/true")
51
+ end
52
+
53
+ def disable_storage(name)
54
+ get("storage/#{escape_path(name)}/enable/false")
55
+ end
56
+
57
+ def update_storage(name, type:, enabled:, connection:, workspaces:, formats:)
58
+ data = {
59
+ name: name,
60
+ config: {
61
+ type: type,
62
+ enabled: enabled,
63
+ connection: connection,
64
+ workspaces: workspaces,
65
+ formats: formats
66
+ }
67
+ }
68
+ post("storage/#{escape_path(name)}.json", data)
69
+ end
70
+
71
+ def delete_storage(name)
72
+ delete("storage/#{escape_path(name)}.json")
73
+ end
74
+
75
+ def cluster
76
+ get("cluster.json")
77
+ end
78
+
79
+ # status does not return json
80
+
81
+ def metrics
82
+ # no .json suffix
83
+ get("status/metrics")
84
+ end
85
+
86
+ # threads does not return json
87
+
88
+ def options
89
+ get("options.json")
90
+ end
91
+
92
+ def server_version
93
+ @server_version ||= run_query({query: "SELECT version FROM sys.version"})[0]["version"]
94
+ end
95
+
96
+ # @uri may contain sensitive info
97
+ def inspect
98
+ to_s
99
+ end
100
+
101
+ private
102
+
103
+ def run_query(data)
104
+ data[:queryType] ||= "sql"
105
+
106
+ body = post("query.json", data)
107
+
108
+ # errors return 200 with Drill 1.19+
109
+ if body["queryState"] != "COMPLETED"
110
+ raise Error, body["errorMessage"] || "Bad state: #{body["queryState"]}"
111
+ end
112
+
113
+ # return columns in order
114
+ result = []
115
+ columns = body["columns"]
116
+ body["rows"].each do |row|
117
+ result << columns.each_with_object({}) { |c, memo| memo[c] = row[c] }
118
+ end
119
+ result
120
+ end
121
+
122
+ def get(path)
123
+ handle_response do
124
+ Net::HTTP::Get.new("#{@uri.request_uri}#{path}", HEADERS)
125
+ end
126
+ end
127
+
128
+ def post(path, data)
129
+ handle_response do
130
+ req = Net::HTTP::Post.new("#{@uri.request_uri}#{path}", HEADERS)
131
+ req.body = data.to_json
132
+ req
133
+ end
134
+ end
135
+
136
+ def delete(path)
137
+ handle_response do
138
+ Net::HTTP::Delete.new("#{@uri.request_uri}#{path}", HEADERS)
139
+ end
140
+ end
141
+
142
+ def handle_response
143
+ begin
144
+ req = yield
145
+ req.basic_auth(@uri.user, @uri.password) if @uri.user || @uri.password
146
+ response = @http.request(req)
147
+ rescue Errno::ECONNREFUSED => e
148
+ raise Error, e.message
149
+ end
150
+
151
+ unless response.kind_of?(Net::HTTPSuccess)
152
+ body = JSON.parse(response.body) rescue {}
153
+ message = body["errorMessage"] || "Bad response: #{response.code}"
154
+ raise Error, message
155
+ end
156
+
157
+ JSON.parse(response.body)
158
+ end
159
+
160
+ def escape_path(path)
161
+ CGI.escape(path).gsub("+", "%20")
162
+ end
163
+ end
164
+ end
data/lib/drill/version.rb CHANGED
@@ -1,3 +1,3 @@
1
- class Drill
2
- VERSION = "0.1.2"
1
+ module Drill
2
+ VERSION = "0.2.0"
3
3
  end
@@ -1,48 +1,16 @@
1
+ # stdlib
2
+ require "cgi"
1
3
  require "json"
2
4
  require "net/http"
5
+
6
+ # modules
7
+ require "drill/client"
3
8
  require "drill/version"
4
9
 
5
- class Drill
10
+ module Drill
6
11
  class Error < StandardError; end
7
12
 
8
- HEADERS = {
9
- "Content-Type" => "application/json",
10
- "Accept" => "application/json"
11
- }
12
-
13
- def initialize(url: nil, open_timeout: 3, read_timeout: nil)
14
- url ||= ENV["DRILL_URL"] || "http://localhost:8047"
15
- # strip trailing slash if exists
16
- @uri = URI.parse("#{url.sub(/\/\z/, "")}/query.json")
17
- @http = Net::HTTP.new(@uri.host, @uri.port)
18
- @http.use_ssl = true if @uri.scheme == "https"
19
- @http.open_timeout = open_timeout if open_timeout
20
- @http.read_timeout = read_timeout if read_timeout
21
- end
22
-
23
- def query(statement)
24
- data = {
25
- queryType: "sql",
26
- query: statement
27
- }
28
-
29
- begin
30
- response = @http.post(@uri.request_uri, data.to_json, HEADERS)
31
- rescue Errno::ECONNREFUSED => e
32
- raise Drill::Error, e.message
33
- end
34
-
35
- body = JSON.parse(response.body)
36
- if body["errorMessage"]
37
- raise Drill::Error, body["errorMessage"].split("\n")[0]
38
- end
39
-
40
- # return columns in order
41
- result = []
42
- columns = body["columns"]
43
- body["rows"].each do |row|
44
- result << columns.each_with_object({}) { |c, memo| memo[c] = row[c] }
45
- end
46
- result
13
+ def self.new(**options)
14
+ Client.new(**options)
47
15
  end
48
16
  end
metadata CHANGED
@@ -1,72 +1,32 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: drill-sergeant
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-07-23 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: bundler
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- version: '0'
27
- - !ruby/object:Gem::Dependency
28
- name: rake
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
- - !ruby/object:Gem::Dependency
42
- name: minitest
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '0'
55
- description:
56
- email: andrew@chartkick.com
11
+ date: 2022-08-29 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description:
14
+ email: andrew@ankane.org
57
15
  executables: []
58
16
  extensions: []
59
17
  extra_rdoc_files: []
60
18
  files:
61
19
  - CHANGELOG.md
20
+ - LICENSE.txt
62
21
  - README.md
63
22
  - lib/drill-sergeant.rb
23
+ - lib/drill/client.rb
64
24
  - lib/drill/version.rb
65
- homepage: https://github.com/ankane/drill-sergeant
25
+ homepage: https://github.com/ankane/drill-ruby
66
26
  licenses:
67
27
  - MIT
68
28
  metadata: {}
69
- post_install_message:
29
+ post_install_message:
70
30
  rdoc_options: []
71
31
  require_paths:
72
32
  - lib
@@ -74,16 +34,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
74
34
  requirements:
75
35
  - - ">="
76
36
  - !ruby/object:Gem::Version
77
- version: '2.2'
37
+ version: '2.7'
78
38
  required_rubygems_version: !ruby/object:Gem::Requirement
79
39
  requirements:
80
40
  - - ">="
81
41
  - !ruby/object:Gem::Version
82
42
  version: '0'
83
43
  requirements: []
84
- rubyforge_project:
85
- rubygems_version: 2.7.7
86
- signing_key:
44
+ rubygems_version: 3.3.7
45
+ signing_key:
87
46
  specification_version: 4
88
47
  summary: Ruby client for Apache Drill
89
48
  test_files: []