diff --git a/elasticsearch-transport/lib/elasticsearch/transport.rb b/elasticsearch-transport/lib/elasticsearch/transport.rb index 696a469973..c142d8228f 100644 --- a/elasticsearch-transport/lib/elasticsearch/transport.rb +++ b/elasticsearch-transport/lib/elasticsearch/transport.rb @@ -35,15 +35,3 @@ require "elasticsearch/transport/redacted" require "elasticsearch/transport/version" - -module Elasticsearch - module Client - - # A convenience wrapper for {::Elasticsearch::Transport::Client#initialize}. - # - def new(arguments={}, &block) - Elasticsearch::Transport::Client.new(arguments, &block) - end - extend self - end -end diff --git a/elasticsearch-transport/lib/elasticsearch/transport/client.rb b/elasticsearch-transport/lib/elasticsearch/transport/client.rb index 29a216bf56..c5e1ec2b8e 100644 --- a/elasticsearch-transport/lib/elasticsearch/transport/client.rb +++ b/elasticsearch-transport/lib/elasticsearch/transport/client.rb @@ -50,12 +50,6 @@ class Client # @since 7.0.0 DEFAULT_HOST = 'localhost:9200'.freeze - # The default port to use if connecting using a Cloud ID. - # Updated from 9243 to 443 in client version 7.10.1 - # - # @since 7.2.0 - DEFAULT_CLOUD_PORT = 443 - # The default port to use if not otherwise specified. # # @since 7.2.0 @@ -120,8 +114,6 @@ class Client # The default is false. Responses will automatically be inflated if they are compressed. # If a custom transport object is used, it must handle the request compression and response inflation. # - # @option api_key [String, Hash] :api_key Use API Key Authentication, either the base64 encoding of `id` and `api_key` - # joined by a colon as a String, or a hash with the `id` and `api_key` values. # @option opaque_id_prefix [String] :opaque_id_prefix set a prefix for X-Opaque-Id when initializing the client. # This will be prepended to the id you set before each request # if you're using X-Opaque-Id @@ -130,8 +122,8 @@ class Client # # @yield [faraday] Access and configure the `Faraday::Connection` instance directly with a block # - def initialize(arguments={}, &block) - @options = arguments.each_with_object({}){ |(k,v), args| args[k.to_sym] = v } + def initialize(arguments = {}, &block) + @options = arguments.transform_keys(&:to_sym) @arguments = @options @arguments[:logger] ||= @arguments[:log] ? DEFAULT_LOGGER.call() : nil @arguments[:tracer] ||= @arguments[:trace] ? DEFAULT_TRACER.call() : nil @@ -141,19 +133,17 @@ def initialize(arguments={}, &block) @arguments[:randomize_hosts] ||= false @arguments[:transport_options] ||= {} @arguments[:http] ||= {} - @arguments[:enable_meta_header] = arguments.fetch(:enable_meta_header) { true } + @arguments[:enable_meta_header] = arguments.fetch(:enable_meta_header, true) @options[:http] ||= {} - set_api_key if (@api_key = @arguments[:api_key]) set_compatibility_header if ENV['ELASTIC_CLIENT_APIVERSIONING'] - @seeds = extract_cloud_creds(@arguments) - @seeds ||= __extract_hosts(@arguments[:hosts] || - @arguments[:host] || - @arguments[:url] || - @arguments[:urls] || - ENV['ELASTICSEARCH_URL'] || - DEFAULT_HOST) + @hosts = __extract_hosts(@arguments[:hosts] || + @arguments[:host] || + @arguments[:url] || + @arguments[:urls] || + ENV['ELASTICSEARCH_URL'] || + DEFAULT_HOST) @send_get_body_as = @arguments[:send_get_body_as] || 'GET' @opaque_id_prefix = @arguments[:opaque_id_prefix] || nil @@ -169,17 +159,16 @@ def initialize(arguments={}, &block) @transport = if @transport_class == Transport::HTTP::Faraday @arguments[:adapter] ||= __auto_detect_adapter set_meta_header # from include MetaHeader - @transport_class.new(hosts: @seeds, options: @arguments) do |faraday| + @transport_class.new(hosts: @hosts, options: @arguments) do |faraday| faraday.adapter(@arguments[:adapter]) block&.call faraday end else set_meta_header # from include MetaHeader - @transport_class.new(hosts: @seeds, options: @arguments) + @transport_class.new(hosts: @hosts, options: @arguments) end end end - # Performs a request through delegation to {#transport}. # def perform_request(method, path, params = {}, body = nil, headers = nil) @@ -194,13 +183,6 @@ def perform_request(method, path, params = {}, body = nil, headers = nil) private - def set_api_key - @api_key = __encode(@api_key) if @api_key.is_a? Hash - add_header('Authorization' => "ApiKey #{@api_key}") - @arguments.delete(:user) - @arguments.delete(:password) - end - def set_compatibility_header return unless ['1', 'true'].include?(ENV['ELASTIC_CLIENT_APIVERSIONING']) @@ -220,30 +202,6 @@ def add_header(header) ) end - def extract_cloud_creds(arguments) - return unless arguments[:cloud_id] && !arguments[:cloud_id].empty? - - name = arguments[:cloud_id].split(':')[0] - cloud_url, elasticsearch_instance = Base64.decode64(arguments[:cloud_id].gsub("#{name}:", '')).split('$') - - if cloud_url.include?(':') - url, port = cloud_url.split(':') - host = "#{elasticsearch_instance}.#{url}" - else - host = "#{elasticsearch_instance}.#{cloud_url}" - port = arguments[:port] || DEFAULT_CLOUD_PORT - end - [ - { - scheme: 'https', - user: arguments[:user], - password: arguments[:password], - host: host, - port: port.to_i - } - ] - end - # Normalizes and returns hosts configuration. # # Arrayifies the `hosts_config` argument and extracts `host` and `port` info from strings. @@ -258,15 +216,15 @@ def extract_cloud_creds(arguments) # def __extract_hosts(hosts_config) hosts = case hosts_config - when String - hosts_config.split(',').map { |h| h.strip! || h } - when Array - hosts_config - when Hash, URI - [ hosts_config ] - else - Array(hosts_config) - end + when String + hosts_config.split(',').map { |h| h.strip! || h } + when Array + hosts_config + when Hash, URI + [ hosts_config ] + else + Array(hosts_config) + end host_list = hosts.map { |host| __parse_host(host) } @options[:randomize_hosts] ? host_list.shuffle! : host_list @@ -342,13 +300,6 @@ def __auto_detect_adapter ::Faraday.default_adapter end end - - # Encode credentials for the Authorization Header - # Credentials is the base64 encoding of id and api_key joined by a colon - # @see https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-create-api-key.html - def __encode(api_key) - Base64.strict_encode64([api_key[:id], api_key[:api_key]].join(':')) - end end end end diff --git a/elasticsearch-transport/spec/elasticsearch/transport/client_spec.rb b/elasticsearch-transport/spec/elasticsearch/transport/client_spec.rb index 0fa7124ae1..6ff812fd91 100644 --- a/elasticsearch-transport/spec/elasticsearch/transport/client_spec.rb +++ b/elasticsearch-transport/spec/elasticsearch/transport/client_spec.rb @@ -70,48 +70,6 @@ end end - context 'when an encoded api_key is provided' do - let(:client) do - described_class.new(api_key: 'an_api_key') - end - let(:authorization_header) do - client.transport.connections.first.connection.headers['Authorization'] - end - - it 'Adds the ApiKey header to the connection' do - expect(authorization_header).to eq('ApiKey an_api_key') - end - end - - context 'when an un-encoded api_key is provided' do - let(:client) do - described_class.new(api_key: { id: 'my_id', api_key: 'my_api_key' }) - end - let(:authorization_header) do - client.transport.connections.first.connection.headers['Authorization'] - end - - it 'Adds the ApiKey header to the connection' do - expect(authorization_header).to eq("ApiKey #{Base64.strict_encode64('my_id:my_api_key')}") - end - end - - context 'when basic auth and api_key are provided' do - let(:client) do - described_class.new( - api_key: { id: 'my_id', api_key: 'my_api_key' }, - host: 'http://elastic:password@localhost:9200' - ) - end - let(:authorization_header) do - client.transport.connections.first.connection.headers['Authorization'] - end - - it 'removes basic auth credentials' do - expect(authorization_header).not_to match(/^Basic/) - expect(authorization_header).to match(/^ApiKey/) - end - end context 'when a user-agent header is specified as client option in lower-case' do @@ -329,156 +287,6 @@ end end - context 'when cloud credentials are provided' do - - let(:client) do - described_class.new( - cloud_id: 'name:bG9jYWxob3N0JGFiY2QkZWZnaA==', - user: 'elastic', - password: 'changeme' - ) - end - - let(:hosts) do - client.transport.hosts - end - - it 'extracts the cloud credentials' do - expect(hosts[0][:host]).to eq('abcd.localhost') - expect(hosts[0][:protocol]).to eq('https') - expect(hosts[0][:user]).to eq('elastic') - expect(hosts[0][:password]).to eq('changeme') - expect(hosts[0][:port]).to eq(443) - end - - it 'creates the correct full url' do - expect( - client.transport.__full_url(client.transport.hosts[0]) - ).to eq('https://elastic:changeme@abcd.localhost:443') - end - - context 'when a port is specified' do - - let(:client) do - described_class.new(cloud_id: 'name:bG9jYWxob3N0JGFiY2QkZWZnaA==', user: 'elastic', password: 'changeme', port: 9250) - end - - it 'sets the specified port along with the cloud credentials' do - expect(hosts[0][:host]).to eq('abcd.localhost') - expect(hosts[0][:protocol]).to eq('https') - expect(hosts[0][:user]).to eq('elastic') - expect(hosts[0][:password]).to eq('changeme') - expect(hosts[0][:port]).to eq(9250) - end - - it 'creates the correct full url' do - expect(client.transport.__full_url(client.transport.hosts[0])).to eq('https://elastic:changeme@abcd.localhost:9250') - end - end - - context 'when the cluster has alternate names' do - - let(:client) do - described_class.new( - cloud_id: 'myCluster:bG9jYWxob3N0JGFiY2QkZWZnaA==', - user: 'elasticfantastic', - password: 'tobechanged' - ) - end - - let(:hosts) do - client.transport.hosts - end - - it 'extracts the cloud credentials' do - expect(hosts[0][:host]).to eq('abcd.localhost') - expect(hosts[0][:protocol]).to eq('https') - expect(hosts[0][:user]).to eq('elasticfantastic') - expect(hosts[0][:password]).to eq('tobechanged') - expect(hosts[0][:port]).to eq(443) - end - - it 'creates the correct full url' do - expect( - client.transport.__full_url(client.transport.hosts[0]) - ).to eq('https://elasticfantastic:tobechanged@abcd.localhost:443') - end - end - - context 'when decoded cloud id has a trailing dollar sign' do - let(:client) do - described_class.new( - cloud_id: 'a_cluster:bG9jYWxob3N0JGFiY2Qk', - user: 'elasticfantastic', - password: 'changeme' - ) - end - - let(:hosts) do - client.transport.hosts - end - - it 'extracts the cloud credentials' do - expect(hosts[0][:host]).to eq('abcd.localhost') - expect(hosts[0][:protocol]).to eq('https') - expect(hosts[0][:user]).to eq('elasticfantastic') - expect(hosts[0][:password]).to eq('changeme') - expect(hosts[0][:port]).to eq(443) - end - - it 'creates the correct full url' do - expect( - client.transport.__full_url(client.transport.hosts[0]) - ).to eq('https://elasticfantastic:changeme@abcd.localhost:443') - end - end - - context 'when the cloud host provides a port' do - let(:client) do - described_class.new( - cloud_id: 'name:ZWxhc3RpY19zZXJ2ZXI6OTI0MyRlbGFzdGljX2lk', - user: 'elastic', - password: 'changeme' - ) - end - - let(:hosts) do - client.transport.hosts - end - - it 'creates the correct full url' do - expect(hosts[0][:host]).to eq('elastic_id.elastic_server') - expect(hosts[0][:protocol]).to eq('https') - expect(hosts[0][:user]).to eq('elastic') - expect(hosts[0][:password]).to eq('changeme') - expect(hosts[0][:port]).to eq(9243) - end - end - - context 'when the cloud host provides a port and the port is also specified' do - let(:client) do - described_class.new( - cloud_id: 'name:ZWxhc3RpY19zZXJ2ZXI6OTI0MyRlbGFzdGljX2lk', - user: 'elastic', - password: 'changeme', - port: 9200 - ) - end - - let(:hosts) do - client.transport.hosts - end - - it 'creates the correct full url' do - expect(hosts[0][:host]).to eq('elastic_id.elastic_server') - expect(hosts[0][:protocol]).to eq('https') - expect(hosts[0][:user]).to eq('elastic') - expect(hosts[0][:password]).to eq('changeme') - expect(hosts[0][:port]).to eq(9243) - end - end - end - shared_examples_for 'a client that extracts hosts' do context 'when the host is a String' do diff --git a/elasticsearch/Rakefile b/elasticsearch/Rakefile index dba2c74470..7bb0a25b2c 100644 --- a/elasticsearch/Rakefile +++ b/elasticsearch/Rakefile @@ -15,7 +15,9 @@ # specific language governing permissions and limitations # under the License. -require "bundler/gem_tasks" +require 'bundler/gem_tasks' + +task(:default) { system 'rake --tasks' } desc 'Run unit tests' task test: 'test:spec' diff --git a/elasticsearch/lib/elasticsearch.rb b/elasticsearch/lib/elasticsearch.rb index 03d8f3dbd5..b2aa4dc3e6 100644 --- a/elasticsearch/lib/elasticsearch.rb +++ b/elasticsearch/lib/elasticsearch.rb @@ -21,12 +21,89 @@ require 'elasticsearch/api' module Elasticsearch - module Transport - class Client - include Elasticsearch::API + # This is the stateful Elasticsearch::Client, using an instance of elasticsearch-transport. + class Client + include Elasticsearch::API + # The default port to use if connecting using a Cloud ID. + # Updated from 9243 to 443 in client version 7.10.1 + # + # @since 7.2.0 + DEFAULT_CLOUD_PORT = 443 + + # Create a client connected to an Elasticsearch cluster. + # + # @option arguments [String] :cloud_id - The Cloud ID to connect to Elastic Cloud + # @option api_key [String, Hash] :api_key Use API Key Authentication, either the base64 encoding of `id` and `api_key` + # joined by a colon as a String, or a hash with the `id` and `api_key` values. + def initialize(arguments = {}, &block) + api_key(arguments) if arguments[:api_key] + if arguments[:cloud_id] + arguments[:hosts] = setup_cloud_host( + arguments[:cloud_id], + arguments[:user], + arguments[:password], + arguments[:port] + ) + end + @transport = Elasticsearch::Transport::Client.new(arguments, &block) + end + + def method_missing(name, *args, &block) + if methods.include?(name) + super + else + @transport.send(name, *args, &block) + end + end + + def respond_to_missing?(method_name, *args) + @transport.respond_to?(method_name) || super + end + + private + + def setup_cloud_host(cloud_id, user, password, port) + name = cloud_id.split(':')[0] + cloud_url, elasticsearch_instance = Base64.decode64(cloud_id.gsub("#{name}:", '')).split('$') + + if cloud_url.include?(':') + url, port = cloud_url.split(':') + host = "#{elasticsearch_instance}.#{url}" + else + host = "#{elasticsearch_instance}.#{cloud_url}" + port ||= DEFAULT_CLOUD_PORT + end + [{ scheme: 'https', user: user, password: password, host: host, port: port.to_i }] + end + + def api_key(arguments) + api_key = if arguments[:api_key].is_a? Hash + encode(arguments[:api_key]) + else + arguments[:api_key] + end + arguments.delete(:user) + arguments.delete(:password) + authorization = { 'Authorization' => "ApiKey #{api_key}" } + if (headers = arguments.dig(:transport_options, :headers)) + headers.merge!(authorization) + else + arguments[:transport_options] = { + headers: authorization + } + end + end + + # Encode credentials for the Authorization Header + # Credentials is the base64 encoding of id and api_key joined by a colon + # @see https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-create-api-key.html + def encode(api_key) + Base64.strict_encode64([api_key[:id], api_key[:api_key]].join(':')) end end end + +# Helper for the meta-header value for Cloud module Elastic # If the version is X.X.X.pre/alpha/beta, use X.X.Xp for the meta-header: def self.client_meta_version diff --git a/elasticsearch/spec/spec_helper.rb b/elasticsearch/spec/spec_helper.rb index 72356526c2..cf3a1b8248 100644 --- a/elasticsearch/spec/spec_helper.rb +++ b/elasticsearch/spec/spec_helper.rb @@ -14,10 +14,8 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. - require 'elasticsearch' require 'rspec' -require 'webmock/rspec' RSpec.configure do |config| config.formatter = :documentation diff --git a/elasticsearch/spec/unit/api_key_spec.rb b/elasticsearch/spec/unit/api_key_spec.rb new file mode 100644 index 0000000000..cbafdf202a --- /dev/null +++ b/elasticsearch/spec/unit/api_key_spec.rb @@ -0,0 +1,74 @@ +# Licensed to Elasticsearch B.V. under one or more contributor +# license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright +# ownership. Elasticsearch B.V. licenses this file to you under +# the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +require 'spec_helper' + +describe Elasticsearch::Client do + context 'when using API Key' do + let(:authorization_header) do + client.transport.connections.first.connection.headers['Authorization'] + end + + context 'when an encoded api_key is provided' do + let(:client) do + described_class.new(api_key: 'an_api_key') + end + + it 'Adds the ApiKey header to the connection' do + expect(authorization_header).to eq('ApiKey an_api_key') + end + end + + context 'when an un-encoded api_key is provided' do + let(:client) do + described_class.new(api_key: { id: 'my_id', api_key: 'my_api_key' }) + end + + it 'Adds the ApiKey header to the connection' do + expect(authorization_header).to eq("ApiKey #{Base64.strict_encode64('my_id:my_api_key')}") + end + end + + context 'when basic auth and api_key are provided' do + let(:client) do + described_class.new( + api_key: { id: 'my_id', api_key: 'my_api_key' }, + host: 'http://elastic:password@localhost:9200' + ) + end + + it 'removes basic auth credentials' do + expect(authorization_header).not_to match(/^Basic/) + expect(authorization_header).to match(/^ApiKey/) + end + end + + context 'when other headers where specified' do + let(:client) do + described_class.new( + api_key: 'elasticsearch_api_key', + transport_options: { headers: { 'x-test-header' => 'test' } } + ) + end + + it 'Adds the ApiKey header to the connection and keeps the header' do + header = client.transport.connections.first.connection.headers + expect(header['Authorization']).to eq('ApiKey elasticsearch_api_key') + expect(header['X-Test-Header']).to eq('test') + end + end + end +end diff --git a/elasticsearch/spec/unit/cloud_credentials_spec.rb b/elasticsearch/spec/unit/cloud_credentials_spec.rb new file mode 100644 index 0000000000..05d5832c6d --- /dev/null +++ b/elasticsearch/spec/unit/cloud_credentials_spec.rb @@ -0,0 +1,166 @@ +# Licensed to Elasticsearch B.V. under one or more contributor +# license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright +# ownership. Elasticsearch B.V. licenses this file to you under +# the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +require 'spec_helper' + +describe Elasticsearch::Client do + context 'when cloud credentials are provided' do + let(:client) do + described_class.new( + cloud_id: 'name:bG9jYWxob3N0JGFiY2QkZWZnaA==', + user: 'elastic', + password: 'changeme' + ) + end + + let(:hosts) do + client.transport.hosts + end + + it 'extracts the cloud credentials' do + expect(hosts[0][:host]).to eq('abcd.localhost') + expect(hosts[0][:protocol]).to eq('https') + expect(hosts[0][:user]).to eq('elastic') + expect(hosts[0][:password]).to eq('changeme') + expect(hosts[0][:port]).to eq(443) + end + + it 'creates the correct full url' do + expect( + client.transport.__full_url(client.transport.hosts[0]) + ).to eq('https://elastic:changeme@abcd.localhost:443') + end + + context 'when a port is specified' do + let(:client) do + described_class.new(cloud_id: 'name:bG9jYWxob3N0JGFiY2QkZWZnaA==', user: 'elastic', password: 'changeme', port: 9250) + end + + it 'sets the specified port along with the cloud credentials' do + expect(hosts[0][:host]).to eq('abcd.localhost') + expect(hosts[0][:protocol]).to eq('https') + expect(hosts[0][:user]).to eq('elastic') + expect(hosts[0][:password]).to eq('changeme') + expect(hosts[0][:port]).to eq(9250) + end + + it 'creates the correct full url' do + expect(client.transport.__full_url(client.transport.hosts[0])).to eq('https://elastic:changeme@abcd.localhost:9250') + end + end + + context 'when the cluster has alternate names' do + let(:client) do + described_class.new( + cloud_id: 'myCluster:bG9jYWxob3N0JGFiY2QkZWZnaA==', + user: 'elasticfantastic', + password: 'tobechanged' + ) + end + + let(:hosts) do + client.transport.hosts + end + + it 'extracts the cloud credentials' do + expect(hosts[0][:host]).to eq('abcd.localhost') + expect(hosts[0][:protocol]).to eq('https') + expect(hosts[0][:user]).to eq('elasticfantastic') + expect(hosts[0][:password]).to eq('tobechanged') + expect(hosts[0][:port]).to eq(443) + end + + it 'creates the correct full url' do + expect( + client.transport.__full_url(client.transport.hosts[0]) + ).to eq('https://elasticfantastic:tobechanged@abcd.localhost:443') + end + end + + context 'when decoded cloud id has a trailing dollar sign' do + let(:client) do + described_class.new( + cloud_id: 'a_cluster:bG9jYWxob3N0JGFiY2Qk', + user: 'elasticfantastic', + password: 'changeme' + ) + end + + let(:hosts) do + client.transport.hosts + end + + it 'extracts the cloud credentials' do + expect(hosts[0][:host]).to eq('abcd.localhost') + expect(hosts[0][:protocol]).to eq('https') + expect(hosts[0][:user]).to eq('elasticfantastic') + expect(hosts[0][:password]).to eq('changeme') + expect(hosts[0][:port]).to eq(443) + end + + it 'creates the correct full url' do + expect( + client.transport.__full_url(client.transport.hosts[0]) + ).to eq('https://elasticfantastic:changeme@abcd.localhost:443') + end + end + + context 'when the cloud host provides a port' do + let(:client) do + described_class.new( + cloud_id: 'name:ZWxhc3RpY19zZXJ2ZXI6OTI0MyRlbGFzdGljX2lk', + user: 'elastic', + password: 'changeme' + ) + end + + let(:hosts) do + client.transport.hosts + end + + it 'creates the correct full url' do + expect(hosts[0][:host]).to eq('elastic_id.elastic_server') + expect(hosts[0][:protocol]).to eq('https') + expect(hosts[0][:user]).to eq('elastic') + expect(hosts[0][:password]).to eq('changeme') + expect(hosts[0][:port]).to eq(9243) + end + end + + context 'when the cloud host provides a port and the port is also specified' do + let(:client) do + described_class.new( + cloud_id: 'name:ZWxhc3RpY19zZXJ2ZXI6OTI0MyRlbGFzdGljX2lk', + user: 'elastic', + password: 'changeme', + port: 9200 + ) + end + + let(:hosts) do + client.transport.hosts + end + + it 'creates the correct full url' do + expect(hosts[0][:host]).to eq('elastic_id.elastic_server') + expect(hosts[0][:protocol]).to eq('https') + expect(hosts[0][:user]).to eq('elastic') + expect(hosts[0][:password]).to eq('changeme') + expect(hosts[0][:port]).to eq(9243) + end + end + end +end diff --git a/elasticsearch/spec/unit/wrapper_gem_spec.rb b/elasticsearch/spec/unit/wrapper_gem_spec.rb index 149c3a5c00..d5a2a38404 100644 --- a/elasticsearch/spec/unit/wrapper_gem_spec.rb +++ b/elasticsearch/spec/unit/wrapper_gem_spec.rb @@ -14,7 +14,7 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -require 'elasticsearch' +require 'spec_helper' describe 'Elasticsearch: wrapper gem' do it 'requires all neccessary subgems' do