impala 0.4.3 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -1,4 +1,4 @@
1
+ sudo: false
1
2
  language: ruby
2
3
  rvm:
3
- - 1.9.3
4
- - 2.1.2
4
+ - 2.2
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # impala-ruby
2
2
 
3
- ![build](https://travis-ci.org/colinmarc/impala-ruby.svg?branch=master)   [![rubygems](https://badge.fury.io/rb/impala.svg)](http://rubygems.org/gems/impala)
3
+ [![build](https://travis-ci.org/colinmarc/impala-ruby.svg?branch=master)](https://travis-ci.org/colinmarc/impala-ruby)   [![rubygems](https://badge.fury.io/rb/impala.svg)](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
 
@@ -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.1')
17
- gem.add_dependency('rack')
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')
@@ -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
- # connection after yielding the connection to the block.
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
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Impala
2
- VERSION = "0.4.3"
2
+ VERSION = "0.5.0"
3
3
  end
@@ -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.4.3
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: 2014-09-04 00:00:00.000000000 Z
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.1
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.1
26
+ version: '0.9'
30
27
  - !ruby/object:Gem::Dependency
31
- name: rack
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: '0'
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: '0'
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: 1.8.23
205
+ rubygems_version: 2.4.5.1
241
206
  signing_key:
242
- specification_version: 3
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: