impala 0.4.3 → 0.5.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 +7 -0
- data/.travis.yml +2 -2
- data/README.md +1 -1
- data/impala.gemspec +2 -3
- data/lib/impala.rb +15 -3
- data/lib/impala/connection.rb +11 -3
- data/lib/impala/sasl_transport.rb +117 -0
- data/lib/impala/version.rb +1 -1
- data/test/test_impala.rb +1 -1
- metadata +33 -69
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 488007beb7a8a2ecc5e1663356305ea2d2a705d1
|
4
|
+
data.tar.gz: 4e7276e73ee5d17e790116fc38f59938e00d5e15
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6e903365b98beb2a78e2a2a4bea721035ca58344b54e196ba67ae15ac814a20024ef79565d019dc390a58529ff80cc760f254d67080833e21fdb44f90f164eeb
|
7
|
+
data.tar.gz: 0d43d9e6442237bd7ecc27ff9770bc3e51058d166a847200c1830b5466bb3c51250be848b8563922618dc10199c716f487bd01d3e5c40ba97188205d137375e4
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# impala-ruby
|
2
2
|
|
3
|
-
 [](http://rubygems.org/gems/impala)
|
3
|
+
[](https://travis-ci.org/colinmarc/impala-ruby) [](http://rubygems.org/gems/impala)
|
4
4
|
|
5
5
|
This is a ruby client for [Cloudera Impala][1]. You use it like this:
|
6
6
|
|
data/impala.gemspec
CHANGED
@@ -13,9 +13,8 @@ Gem::Specification.new do |gem|
|
|
13
13
|
gem.homepage = "https://github.com/colinmarc/impala-ruby"
|
14
14
|
gem.license = 'MIT'
|
15
15
|
|
16
|
-
gem.add_dependency('thrift', '~> 0.9
|
17
|
-
gem.add_dependency('
|
18
|
-
gem.add_dependency('thin')
|
16
|
+
gem.add_dependency('thrift', '~> 0.9')
|
17
|
+
gem.add_dependency('gssapi', '~> 1.2')
|
19
18
|
|
20
19
|
gem.add_development_dependency('rake')
|
21
20
|
gem.add_development_dependency('pry')
|
data/lib/impala.rb
CHANGED
@@ -10,6 +10,7 @@ require 'impala/version'
|
|
10
10
|
require 'thrift'
|
11
11
|
require 'time'
|
12
12
|
require 'impala/protocol'
|
13
|
+
require 'impala/sasl_transport'
|
13
14
|
require 'impala/cursor'
|
14
15
|
require 'impala/connection'
|
15
16
|
|
@@ -22,15 +23,26 @@ module Impala
|
|
22
23
|
class ParsingError < StandardError; end
|
23
24
|
|
24
25
|
# Connect to an Impala server. If a block is given, it will close the
|
25
|
-
#
|
26
|
+
# connection after yielding the connection to the block.
|
26
27
|
# @param [String] host the hostname or IP address of the Impala server
|
27
28
|
# @param [int] port the port that the Impala server is listening on
|
29
|
+
# @param [Hash] options connection options
|
30
|
+
# @option options [int] :timeout the timeout in seconds to use when connecting
|
31
|
+
# @option options [Hash] :sasl if present, used to connect with SASL PLAIN
|
32
|
+
# authentication. Should have two properties:
|
33
|
+
# - *:username* (String)
|
34
|
+
# - *:password* (String)
|
35
|
+
# @option options [Hash] :kerberos if present, used to connect with SASL
|
36
|
+
# GSSAPI authentication using whatever context is available. Should have two
|
37
|
+
# properties:
|
38
|
+
# - *:host* (String)
|
39
|
+
# - *:provider* (String)
|
28
40
|
# @yieldparam [Connection] conn the open connection. Will be closed once the block
|
29
41
|
# finishes
|
30
42
|
# @return [Connection] the open connection, or, if a block is
|
31
43
|
# passed, the return value of the block
|
32
|
-
def self.connect(host=DEFAULT_HOST, port=DEFAULT_PORT)
|
33
|
-
connection = Connection.new(host, port)
|
44
|
+
def self.connect(host=DEFAULT_HOST, port=DEFAULT_PORT, options={})
|
45
|
+
connection = Connection.new(host, port, options)
|
34
46
|
|
35
47
|
if block_given?
|
36
48
|
begin
|
data/lib/impala/connection.rb
CHANGED
@@ -5,9 +5,10 @@ module Impala
|
|
5
5
|
LOG_CONTEXT_ID = "impala-ruby"
|
6
6
|
|
7
7
|
# Don't instantiate Connections directly; instead, use {Impala.connect}.
|
8
|
-
def initialize(host, port)
|
8
|
+
def initialize(host, port, options={})
|
9
9
|
@host = host
|
10
10
|
@port = port
|
11
|
+
@options = options
|
11
12
|
@connected = false
|
12
13
|
open
|
13
14
|
end
|
@@ -20,9 +21,16 @@ module Impala
|
|
20
21
|
def open
|
21
22
|
return if @connected
|
22
23
|
|
23
|
-
socket = Thrift::Socket.new(@host, @port)
|
24
|
+
socket = Thrift::Socket.new(@host, @port, @options[:timeout])
|
25
|
+
|
26
|
+
if @options[:kerberos]
|
27
|
+
@transport = SASLTransport.new(socket, :GSSAPI, @options[:kerberos])
|
28
|
+
elsif @options[:sasl]
|
29
|
+
@transport = SASLTransport.new(socket, :PLAIN, @options[:sasl])
|
30
|
+
else
|
31
|
+
@transport = Thrift::BufferedTransport.new(socket)
|
32
|
+
end
|
24
33
|
|
25
|
-
@transport = Thrift::BufferedTransport.new(socket)
|
26
34
|
@transport.open
|
27
35
|
|
28
36
|
proto = Thrift::BinaryProtocol.new(@transport)
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'gssapi'
|
2
|
+
|
3
|
+
module Impala
|
4
|
+
class SASLTransport < Thrift::FramedTransport
|
5
|
+
STATUS_BYTES = 1
|
6
|
+
PAYLOAD_LENGTH_BYTES = 4
|
7
|
+
NEGOTIATION_STATUS = {
|
8
|
+
START: 0x01,
|
9
|
+
OK: 0x02,
|
10
|
+
BAD: 0x03,
|
11
|
+
ERROR: 0x04,
|
12
|
+
COMPLETE: 0x05
|
13
|
+
}
|
14
|
+
|
15
|
+
def initialize(transport, mechanism, options={})
|
16
|
+
super(transport)
|
17
|
+
@mechanism = mechanism.to_sym
|
18
|
+
@options = options
|
19
|
+
|
20
|
+
unless [:PLAIN, :GSSAPI].include? @mechanism
|
21
|
+
raise "Unknown SASL mechanism: #{@mechanism}"
|
22
|
+
end
|
23
|
+
|
24
|
+
if @mechanism == :GSSAPI
|
25
|
+
@gsscli = GSSAPI::Simple.new(@options[:host], @options[:principal])
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def open
|
30
|
+
super
|
31
|
+
|
32
|
+
case @mechanism
|
33
|
+
when :PLAIN
|
34
|
+
handshake_plain!
|
35
|
+
when :GSSAPI
|
36
|
+
handshake_gssapi!
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def handshake_plain!
|
43
|
+
username = @options.fetch(:username, 'anonymous')
|
44
|
+
password = @options.fetch(:password, 'anonymous')
|
45
|
+
|
46
|
+
token = "[PLAIN]\u0000#{username}\u0000#{password}"
|
47
|
+
write_handshake_message(NEGOTIATION_STATUS[:START], 'PLAIN')
|
48
|
+
write_handshake_message(NEGOTIATION_STATUS[:OK], token)
|
49
|
+
|
50
|
+
status, _ = read_handshake_message
|
51
|
+
case status
|
52
|
+
when NEGOTIATION_STATUS[:COMPLETE]
|
53
|
+
@open = true
|
54
|
+
when NEGOTIATION_STATUS[:OK]
|
55
|
+
raise "Failed to complete challenge exchange: only NONE supported currently"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def handshake_gssapi!
|
60
|
+
token = @gsscli.init_context
|
61
|
+
write_handshake_message(NEGOTIATION_STATUS[:START], 'GSSAPI')
|
62
|
+
write_handshake_message(NEGOTIATION_STATUS[:OK], token)
|
63
|
+
|
64
|
+
status, msg = read_handshake_message
|
65
|
+
case status
|
66
|
+
when NEGOTIATION_STATUS[:COMPLETE]
|
67
|
+
raise "Unexpected COMPLETE from server"
|
68
|
+
when NEGOTIATION_STATUS[:OK]
|
69
|
+
unless @gsscli.init_context(msg)
|
70
|
+
raise "GSSAPI: challenge provided by server could not be verified"
|
71
|
+
end
|
72
|
+
|
73
|
+
write_handshake_message(NEGOTIATION_STATUS[:OK], "")
|
74
|
+
|
75
|
+
status, msg = read_handshake_message
|
76
|
+
case status
|
77
|
+
when NEGOTIATION_STATUS[:COMPLETE]
|
78
|
+
raise "Unexpected COMPLETE from server"
|
79
|
+
when NEGOTIATION_STATUS[:OK]
|
80
|
+
unwrapped = @gsscli.unwrap_message(msg)
|
81
|
+
rewrapped = @gsscli.wrap_message(unwrapped)
|
82
|
+
|
83
|
+
write_handshake_message(NEGOTIATION_STATUS[:COMPLETE], rewrapped)
|
84
|
+
|
85
|
+
status, msg = read_handshake_message
|
86
|
+
case status
|
87
|
+
when NEGOTIATION_STATUS[:COMPLETE]
|
88
|
+
@open = true
|
89
|
+
when NEGOTIATION_STATUS[:OK]
|
90
|
+
raise "Failed to complete GSS challenge exchange"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def read_handshake_message
|
97
|
+
status, len = @transport.read(STATUS_BYTES + PAYLOAD_LENGTH_BYTES).unpack('cl>')
|
98
|
+
body = @transport.to_io.read(len)
|
99
|
+
if [NEGOTIATION_STATUS[:BAD], NEGOTIATION_STATUS[:ERROR]].include?(status)
|
100
|
+
raise "Exception from server: #{body}"
|
101
|
+
end
|
102
|
+
|
103
|
+
[status, body]
|
104
|
+
end
|
105
|
+
|
106
|
+
def write_handshake_message(status, message)
|
107
|
+
header = [status, message.length].pack('cl>')
|
108
|
+
@transport.write(header + message)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
class SASLTransportFactory < Thrift::BaseTransportFactory
|
113
|
+
def get_transport(transport)
|
114
|
+
return SASLTransport.new(transport)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
data/lib/impala/version.rb
CHANGED
data/test/test_impala.rb
CHANGED
@@ -4,7 +4,7 @@ require 'mocha/setup'
|
|
4
4
|
|
5
5
|
describe 'Impala.connect' do
|
6
6
|
before do
|
7
|
-
Thrift::Socket.expects(:new).with('host', 12345)
|
7
|
+
Thrift::Socket.expects(:new).with('host', 12345, nil)
|
8
8
|
Thrift::BufferedTransport.expects(:new).once.returns(stub(:open => nil))
|
9
9
|
Thrift::BinaryProtocol.expects(:new).once
|
10
10
|
Impala::Protocol::ImpalaService::Client.expects(:new).once
|
metadata
CHANGED
@@ -1,174 +1,139 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: impala
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.5.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Colin Marc
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2016-09-25 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: thrift
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- - ~>
|
17
|
+
- - "~>"
|
20
18
|
- !ruby/object:Gem::Version
|
21
|
-
version: 0.9
|
19
|
+
version: '0.9'
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- - ~>
|
24
|
+
- - "~>"
|
28
25
|
- !ruby/object:Gem::Version
|
29
|
-
version: 0.9
|
26
|
+
version: '0.9'
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
|
-
name:
|
28
|
+
name: gssapi
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - "~>"
|
36
32
|
- !ruby/object:Gem::Version
|
37
|
-
version: '
|
33
|
+
version: '1.2'
|
38
34
|
type: :runtime
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - "~>"
|
44
39
|
- !ruby/object:Gem::Version
|
45
|
-
version: '
|
46
|
-
- !ruby/object:Gem::Dependency
|
47
|
-
name: thin
|
48
|
-
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
|
-
requirements:
|
51
|
-
- - ! '>='
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: '0'
|
54
|
-
type: :runtime
|
55
|
-
prerelease: false
|
56
|
-
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
|
-
requirements:
|
59
|
-
- - ! '>='
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
40
|
+
version: '1.2'
|
62
41
|
- !ruby/object:Gem::Dependency
|
63
42
|
name: rake
|
64
43
|
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
44
|
requirements:
|
67
|
-
- -
|
45
|
+
- - ">="
|
68
46
|
- !ruby/object:Gem::Version
|
69
47
|
version: '0'
|
70
48
|
type: :development
|
71
49
|
prerelease: false
|
72
50
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
51
|
requirements:
|
75
|
-
- -
|
52
|
+
- - ">="
|
76
53
|
- !ruby/object:Gem::Version
|
77
54
|
version: '0'
|
78
55
|
- !ruby/object:Gem::Dependency
|
79
56
|
name: pry
|
80
57
|
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
58
|
requirements:
|
83
|
-
- -
|
59
|
+
- - ">="
|
84
60
|
- !ruby/object:Gem::Version
|
85
61
|
version: '0'
|
86
62
|
type: :development
|
87
63
|
prerelease: false
|
88
64
|
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
65
|
requirements:
|
91
|
-
- -
|
66
|
+
- - ">="
|
92
67
|
- !ruby/object:Gem::Version
|
93
68
|
version: '0'
|
94
69
|
- !ruby/object:Gem::Dependency
|
95
70
|
name: minitest
|
96
71
|
requirement: !ruby/object:Gem::Requirement
|
97
|
-
none: false
|
98
72
|
requirements:
|
99
|
-
- -
|
73
|
+
- - ">="
|
100
74
|
- !ruby/object:Gem::Version
|
101
75
|
version: '0'
|
102
76
|
type: :development
|
103
77
|
prerelease: false
|
104
78
|
version_requirements: !ruby/object:Gem::Requirement
|
105
|
-
none: false
|
106
79
|
requirements:
|
107
|
-
- -
|
80
|
+
- - ">="
|
108
81
|
- !ruby/object:Gem::Version
|
109
82
|
version: '0'
|
110
83
|
- !ruby/object:Gem::Dependency
|
111
84
|
name: mocha
|
112
85
|
requirement: !ruby/object:Gem::Requirement
|
113
|
-
none: false
|
114
86
|
requirements:
|
115
|
-
- -
|
87
|
+
- - ">="
|
116
88
|
- !ruby/object:Gem::Version
|
117
89
|
version: '0'
|
118
90
|
type: :development
|
119
91
|
prerelease: false
|
120
92
|
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
none: false
|
122
93
|
requirements:
|
123
|
-
- -
|
94
|
+
- - ">="
|
124
95
|
- !ruby/object:Gem::Version
|
125
96
|
version: '0'
|
126
97
|
- !ruby/object:Gem::Dependency
|
127
98
|
name: yard
|
128
99
|
requirement: !ruby/object:Gem::Requirement
|
129
|
-
none: false
|
130
100
|
requirements:
|
131
|
-
- -
|
101
|
+
- - ">="
|
132
102
|
- !ruby/object:Gem::Version
|
133
103
|
version: '0'
|
134
104
|
type: :development
|
135
105
|
prerelease: false
|
136
106
|
version_requirements: !ruby/object:Gem::Requirement
|
137
|
-
none: false
|
138
107
|
requirements:
|
139
|
-
- -
|
108
|
+
- - ">="
|
140
109
|
- !ruby/object:Gem::Version
|
141
110
|
version: '0'
|
142
111
|
- !ruby/object:Gem::Dependency
|
143
112
|
name: redcarpet
|
144
113
|
requirement: !ruby/object:Gem::Requirement
|
145
|
-
none: false
|
146
114
|
requirements:
|
147
|
-
- -
|
115
|
+
- - ">="
|
148
116
|
- !ruby/object:Gem::Version
|
149
117
|
version: '0'
|
150
118
|
type: :development
|
151
119
|
prerelease: false
|
152
120
|
version_requirements: !ruby/object:Gem::Requirement
|
153
|
-
none: false
|
154
121
|
requirements:
|
155
|
-
- -
|
122
|
+
- - ">="
|
156
123
|
- !ruby/object:Gem::Version
|
157
124
|
version: '0'
|
158
125
|
- !ruby/object:Gem::Dependency
|
159
126
|
name: github-markup
|
160
127
|
requirement: !ruby/object:Gem::Requirement
|
161
|
-
none: false
|
162
128
|
requirements:
|
163
|
-
- -
|
129
|
+
- - ">="
|
164
130
|
- !ruby/object:Gem::Version
|
165
131
|
version: '0'
|
166
132
|
type: :development
|
167
133
|
prerelease: false
|
168
134
|
version_requirements: !ruby/object:Gem::Requirement
|
169
|
-
none: false
|
170
135
|
requirements:
|
171
|
-
- -
|
136
|
+
- - ">="
|
172
137
|
- !ruby/object:Gem::Version
|
173
138
|
version: '0'
|
174
139
|
description: A ruby client for Cloudera's Impala
|
@@ -178,8 +143,8 @@ executables: []
|
|
178
143
|
extensions: []
|
179
144
|
extra_rdoc_files: []
|
180
145
|
files:
|
181
|
-
- .gitignore
|
182
|
-
- .travis.yml
|
146
|
+
- ".gitignore"
|
147
|
+
- ".travis.yml"
|
183
148
|
- Gemfile
|
184
149
|
- LICENSE.txt
|
185
150
|
- README.md
|
@@ -207,6 +172,7 @@ files:
|
|
207
172
|
- lib/impala/protocol/status_types.rb
|
208
173
|
- lib/impala/protocol/t_c_l_i_service.rb
|
209
174
|
- lib/impala/protocol/thrift_hive_metastore.rb
|
175
|
+
- lib/impala/sasl_transport.rb
|
210
176
|
- lib/impala/version.rb
|
211
177
|
- test/test_impala.rb
|
212
178
|
- test/test_impala_connected.rb
|
@@ -219,29 +185,27 @@ files:
|
|
219
185
|
homepage: https://github.com/colinmarc/impala-ruby
|
220
186
|
licenses:
|
221
187
|
- MIT
|
188
|
+
metadata: {}
|
222
189
|
post_install_message:
|
223
190
|
rdoc_options: []
|
224
191
|
require_paths:
|
225
192
|
- lib
|
226
193
|
required_ruby_version: !ruby/object:Gem::Requirement
|
227
|
-
none: false
|
228
194
|
requirements:
|
229
|
-
- -
|
195
|
+
- - ">="
|
230
196
|
- !ruby/object:Gem::Version
|
231
197
|
version: '0'
|
232
198
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
233
|
-
none: false
|
234
199
|
requirements:
|
235
|
-
- -
|
200
|
+
- - ">="
|
236
201
|
- !ruby/object:Gem::Version
|
237
202
|
version: '0'
|
238
203
|
requirements: []
|
239
204
|
rubyforge_project:
|
240
|
-
rubygems_version:
|
205
|
+
rubygems_version: 2.4.5.1
|
241
206
|
signing_key:
|
242
|
-
specification_version:
|
207
|
+
specification_version: 4
|
243
208
|
summary: A ruby client for Cloudera's Impala
|
244
209
|
test_files:
|
245
210
|
- test/test_impala.rb
|
246
211
|
- test/test_impala_connected.rb
|
247
|
-
has_rdoc:
|