elasticsearch/spec/integration/helpers/esql_helper_spec.rb (103 lines of code) (raw):

# 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_relative File.expand_path('../../spec_helper', __dir__) require 'elasticsearch/helpers/esql_helper' require 'ipaddr' context 'Elasticsearch client helpers' do let(:index) { 'esql_helper_test' } let(:body) { { size: 12, query: { match_all: {} } } } let(:esql_helper) { Elasticsearch::Helpers::ESQLHelper } let(:query) do <<~ESQL FROM #{index} | EVAL duration_ms = ROUND(event.duration / 1000000.0, 1) ESQL end before do CLIENT.indices.create( index: index, body: { mappings: { properties: { 'client.ip' => { type: 'ip' }, message: { type: 'keyword' } } } } ) CLIENT.bulk( index: index, body: [ { 'index': {} }, { '@timestamp' => '2023-10-23T12:15:03.360Z', 'client.ip' => '172.21.2.162', message: 'Connected to 10.1.0.3', 'event.duration' => 3_450_233 }, { 'index': {} }, { '@timestamp' => '2023-10-23T12:27:28.948Z', 'client.ip' => '172.21.2.113', message: 'Connected to 10.1.0.2', 'event.duration' => 2_764_889 }, { 'index': {} }, { '@timestamp' => '2023-10-23T13:33:34.937Z', 'client.ip' => '172.21.0.5', message: 'Disconnected', 'event.duration' => 1_232_382 }, { 'index': {} }, { '@timestamp' => '2023-10-23T13:51:54.732Z', 'client.ip' => '172.21.3.15', message: 'Connection error', 'event.duration' => 725_448 }, { 'index': {} }, { '@timestamp' => '2023-10-23T13:52:55.015Z', 'client.ip' => '172.21.3.15', message: 'Connection error', 'event.duration' => 8_268_153 }, { 'index': {} }, { '@timestamp' => '2023-10-23T13:53:55.832Z', 'client.ip' => '172.21.3.15', message: 'Connection error', 'event.duration' => 5_033_755 }, { 'index': {} }, { '@timestamp' => '2023-10-23T13:55:01.543Z', 'client.ip' => '172.21.3.15', message: 'Connected to 10.1.0.1', 'event.duration' => 1_756_467 } ], refresh: true ) end after do CLIENT.indices.delete(index: index) end it 'returns an ESQL response as a relational key/value object' do response = esql_helper.query(CLIENT, query) expect(response.count).to eq 7 expect(response.first.keys).to eq ['duration_ms', 'message', 'event.duration', 'client.ip', '@timestamp'] response.each do |r| expect(r['@timestamp']).to be_a String expect(r['client.ip']).to be_a String expect(r['message']).to be_a String expect(r['event.duration']).to be_a Integer end end it 'parses iterated objects when procs are passed in' do parser = { '@timestamp' => Proc.new { |t| DateTime.parse(t) }, 'client.ip' => Proc.new { |i| IPAddr.new(i) }, 'event.duration' => Proc.new { |d| d.to_s } } response = esql_helper.query(CLIENT, query, parser: parser) response.each do |r| expect(r['@timestamp']).to be_a DateTime expect(r['client.ip']).to be_a IPAddr expect(r['message']).to be_a String expect(r['event.duration']).to be_a String end end it 'parser does not error when value is nil, leaves nil' do CLIENT.index( index: index, body: { '@timestamp' => nil, 'client.ip' => nil, message: 'Connected to 10.1.0.1', 'event.duration' => 1756465 }, refresh: true ) parser = { '@timestamp' => Proc.new { |t| DateTime.parse(t) }, 'client.ip' => Proc.new { |i| IPAddr.new(i) }, 'event.duration' => Proc.new { |d| d.to_s } } response = esql_helper.query(CLIENT, query, parser: parser) response.each do |r| expect [DateTime, NilClass].include?(r['@timestamp'].class) expect [IPAddr, NilClass].include?(r['client.ip'].class) expect(r['message']).to be_a String expect(r['event.duration']).to be_a String end end end