drill-sergeant 0.1.2 → 0.2.0

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 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: []