class Elasticsearch::Client

This is the stateful Elasticsearch::Client, using an instance of elastic-transport.

Constants

DEFAULT_CLOUD_PORT

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

Public Class Methods

new(arguments = {}, &block) click to toggle source

Create a client connected to an Elasticsearch cluster.

@param [Hash] arguments - initializer arguments @option arguments [String] :cloud_id - The Cloud ID to connect to Elastic Cloud @option arguments [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 arguments [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

@option arguments [Hash] :headers Custom HTTP Request Headers

# File lib/elasticsearch.rb, line 47
def initialize(arguments = {}, &block)
  @verified = false
  @warned = false
  @opaque_id_prefix = arguments[:opaque_id_prefix] || nil
  api_key(arguments) if arguments[:api_key]
  setup_cloud(arguments) if arguments[:cloud_id]
  set_user_agent!(arguments) unless sent_user_agent?(arguments)
  @transport = Elastic::Transport::Client.new(arguments, &block)
end

Public Instance Methods

method_missing(name, *args, &block) click to toggle source
Calls superclass method
# File lib/elasticsearch.rb, line 57
def method_missing(name, *args, &block)
  if methods.include?(name)
    super
  elsif name == :perform_request
    # The signature for perform_request is:
    # method, path, params, body, headers, opts
    if (opaque_id = args[2]&.delete(:opaque_id))
      headers = args[4] || {}
      opaque_id = @opaque_id_prefix ? "#{@opaque_id_prefix}#{opaque_id}" : opaque_id
      args[4] = headers.merge('X-Opaque-Id' => opaque_id)
    end
    unless @verified
      verify_elasticsearch(*args, &block)
    else
      @transport.perform_request(*args, &block)
    end
  else
    @transport.send(name, *args, &block)
  end
end
respond_to_missing?(method_name, *args) click to toggle source
Calls superclass method
# File lib/elasticsearch.rb, line 78
def respond_to_missing?(method_name, *args)
  @transport.respond_to?(method_name) || super
end

Private Instance Methods

api_key(arguments) click to toggle source
# File lib/elasticsearch.rb, line 123
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] ||= {}
    arguments[:transport_options].merge!({ headers: authorization })
  end
end
elasticsearch_validation_request() click to toggle source
# File lib/elasticsearch.rb, line 157
def elasticsearch_validation_request
  @transport.perform_request('GET', '/')
end
encode(api_key) click to toggle source

Encode credentials for the Authorization Header Credentials is the base64 encoding of id and api_key joined by a colon @see www.elastic.co/guide/en/elasticsearch/reference/current/security-api-create-api-key.html

# File lib/elasticsearch.rb, line 152
def encode(api_key)
  credentials = [api_key[:id], api_key[:api_key]].join(':')
  [credentials].pack('m0')
end
sent_user_agent?(arguments) click to toggle source
# File lib/elasticsearch.rb, line 161
def sent_user_agent?(arguments)
  return unless (headers = arguments&.[](:transport_options)&.[](:headers))

  !!headers.keys.detect { |h| h =~ /user-?_?agent/ }
end
set_user_agent!(arguments) click to toggle source
# File lib/elasticsearch.rb, line 167
def set_user_agent!(arguments)
  user_agent = [
    "elasticsearch-ruby/#{Elasticsearch::VERSION}",
    "elastic-transport-ruby/#{Elastic::Transport::VERSION}",
    "RUBY_VERSION: #{RUBY_VERSION}"
  ]
  if RbConfig::CONFIG && RbConfig::CONFIG['host_os']
    user_agent << "#{RbConfig::CONFIG['host_os'].split('_').first[/[a-z]+/i].downcase} #{RbConfig::CONFIG['target_cpu']}"
  end
  arguments[:transport_options] ||= {}
  arguments[:transport_options][:headers] ||= {}
  arguments[:transport_options][:headers].merge!({ user_agent: user_agent.join('; ')})
end
setup_cloud(arguments) click to toggle source
# File lib/elasticsearch.rb, line 140
def setup_cloud(arguments)
  arguments[:hosts] = setup_cloud_host(
    arguments[:cloud_id],
    arguments[:user],
    arguments[:password],
    arguments[:port]
  )
end
setup_cloud_host(cloud_id, user, password, port) click to toggle source
# File lib/elasticsearch.rb, line 108
def setup_cloud_host(cloud_id, user, password, port)
  name = cloud_id.split(':')[0]
  base64_decoded = cloud_id.gsub("#{name}:", '').unpack1('m')
  cloud_url, elasticsearch_instance = base64_decoded.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
verify_elasticsearch(*args, &block) click to toggle source
# File lib/elasticsearch.rb, line 84
def verify_elasticsearch(*args, &block)
  begin
    response = @transport.perform_request(*args, &block)
  rescue Elastic::Transport::Transport::Errors::Unauthorized,
         Elastic::Transport::Transport::Errors::Forbidden,
         Elastic::Transport::Transport::Errors::RequestEntityTooLarge => e
    warn(SECURITY_PRIVILEGES_VALIDATION_WARNING)
    @verified = true
    raise e
  rescue Elastic::Transport::Transport::Error => e
    unless @warned
      warn(VALIDATION_WARNING)
      @warned = true
    end
    raise e
  rescue StandardError => e
    warn(VALIDATION_WARNING)
    raise e
  end
  raise Elasticsearch::UnsupportedProductError unless response.headers['x-elastic-product'] == 'Elasticsearch'
  @verified = true
  response
end