fluent-plugin-elasticsearch 4.0.10 → 4.1.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a12dc6596a56b7486d45129b64187021215433d2e7aa5428e96712fb63a345b5
4
- data.tar.gz: 6fe5296f4a0afa23e863399f6d1cc9eeaa8f70c55e5cb979ca8db1bbf7a8988f
3
+ metadata.gz: 6b4183d1e2afbcf9e0e5f78b6cb6ed2fff3206f495a8676d38eb1dbc1ff7267f
4
+ data.tar.gz: 2f1644d04286ae42c51e869c6aadd928ec00b678a405dce838cb1d1802ebf5b1
5
5
  SHA512:
6
- metadata.gz: 4f5d200eb1dee56f9f4fc05efc46cdbf440e0e2df7152e527985b124ac91ff74b0d263bee36f69fddec9f5ccc3730032145d51a95cc22fc00817f909fd4c2a7a
7
- data.tar.gz: 11b0453ea6cbcfaf46e71866a96daf4ceba8f3877dd23e7aa124ea214f056b1b7f56bd8082ae273883a7403a2f1752c64beb377a2a3564c1d30757a8a5f101fa
6
+ metadata.gz: bc88d00e8800e7062dff4fdb9b6bc67c509ee851f5e726321783bec8902df6b548a2533d7c278151882b6f534e5adc680ba83964885d7bb9fd520340484c8478
7
+ data.tar.gz: 07f4379b3bfee4b22bb50f60c441fa60c87ee65967fa70523c3a6fdc7d0cc80c0fced8fd92958227eb64e353c8e623293f5c1e3d17fba848cdab707969d4f3d4
data/History.md CHANGED
@@ -2,6 +2,23 @@
2
2
 
3
3
  ### [Unreleased]
4
4
 
5
+ ### 4.1.3
6
+ - Load multiple templates even if template_name and template_file given (#799)
7
+ - Handle elasticsearch-ruby 7.9.0 using HTTP method changes (#795)
8
+
9
+ ### 4.1.2
10
+ - Use Hash#dig instead of Hash#[] on retrieving version information from Elasticsearch info API (#793)
11
+
12
+ ### 4.1.1
13
+ - Correct ILM explain on logstash_format case (#786)
14
+
15
+ ### 4.1.0
16
+ - Implement Fallback selector and configurable selector class (#782)
17
+
18
+ ### 4.0.11
19
+ - Add custom and time placeholders combination testcase for ILM (#781)
20
+ - Really support ILM on `logstash_format` enabled environment (#779)
21
+
5
22
  ### 4.0.10
6
23
  - filter_elasticsearch_genid: Use entire record as hash seed (#777)
7
24
  - Suppress type in meta with suppress_type_name parameter (#774)
data/README.md CHANGED
@@ -78,6 +78,7 @@ Current maintainers: @cosmo0920
78
78
  + [Hash flattening](#hash-flattening)
79
79
  + [Generate Hash ID](#generate-hash-id)
80
80
  + [sniffer_class_name](#sniffer-class-name)
81
+ + [selector_class_name](#selector-class-name)
81
82
  + [reload_after](#reload-after)
82
83
  + [validate_client_version](#validate-client-version)
83
84
  + [unrecoverable_error_types](#unrecoverable-error-types)
@@ -120,10 +121,12 @@ Current maintainers: @cosmo0920
120
121
 
121
122
  ## Requirements
122
123
 
123
- | fluent-plugin-elasticsearch | fluentd | ruby |
124
- |-------------------|---------|------|
125
- | >= 2.0.0 | >= v0.14.20 | >= 2.1 |
126
- | < 2.0.0 | >= v0.12.0 | >= 1.9 |
124
+ | fluent-plugin-elasticsearch | fluentd | ruby |
125
+ |:----------------------------:|:-----------:|:------:|
126
+ | >= 4.0.1 | >= v0.14.22 | >= 2.3 |
127
+ | >= 3.2.4 && < 4.0.1 | >= v0.14.22 | >= 2.1 |
128
+ | >= 2.0.0 && < 3.2.3 | >= v0.14.20 | >= 2.1 |
129
+ | < 2.0.0 | >= v0.12.0 | >= 1.9 |
127
130
 
128
131
  NOTE: For v0.12 version, you should use 1.x.y version. Please send patch into v0.12 branch if you encountered 1.x version's bug.
129
132
 
@@ -428,7 +431,7 @@ Specify index templates in form of hash. Can contain multiple templates.
428
431
  templates { "template_name_1": "path_to_template_1_file", "template_name_2": "path_to_template_2_file"}
429
432
  ```
430
433
 
431
- If `template_file` and `template_name` are set, then this parameter will be ignored.
434
+ **Note:** Before ES plugin v4.1.2, if `template_file` and `template_name` are set, then this parameter will be ignored. In 4.1.3 or later, `template_file` and `template_name` can work with `templates`.
432
435
 
433
436
  ### customize_template
434
437
 
@@ -478,6 +481,8 @@ deflector_alias test-current
478
481
 
479
482
  If [rollover_index](#rollover_index) is set, then this parameter will be in effect otherwise ignored.
480
483
 
484
+ **NOTE:** Since 4.1.1, `deflector_alias` is prohibited to use with `enable_ilm`.
485
+
481
486
  ### index_prefix
482
487
 
483
488
  This parameter is marked as obsoleted.
@@ -989,7 +994,7 @@ reload_after 100
989
994
 
990
995
  #### Tips
991
996
 
992
- The included sniffer class does not required `out_elasticsearch`.
997
+ The included sniffer class is not required `out_elasticsearch`.
993
998
  You should tell Fluentd where the sniffer class exists.
994
999
 
995
1000
  If you use td-agent, you must put the following lines into `TD_AGENT_DEFAULT` file:
@@ -1006,6 +1011,38 @@ sniffer=$(td-agent-gem contents fluent-plugin-elasticsearch|grep elasticsearch_s
1006
1011
  $ fluentd -r $sniffer [AND YOUR OTHER OPTIONS]
1007
1012
  ```
1008
1013
 
1014
+ ### Selector Class Name
1015
+
1016
+ The default selector used by the `Elasticsearch::Transport` class works well when Fluentd should behave round robin and random selector cases. This doesn't work well when Fluentd should behave fallbacking from exhausted ES cluster to normal ES cluster.
1017
+ The parameter `selector_class_name` gives you the ability to provide your own Selector class to implement whatever selection nodes logic you require.
1018
+
1019
+ The below configuration is using plugin built-in `ElasticseatchFallbackSelector`:
1020
+
1021
+ ```
1022
+ hosts exhausted-host:9201,normal-host:9200
1023
+ selector_class_name "Fluent::Plugin::ElasticseatchFallbackSelector"
1024
+ ```
1025
+
1026
+ #### Tips
1027
+
1028
+ The included selector class is required in `out_elasticsearch` by default.
1029
+ But, your custom selector class is not required in `out_elasticsearch`.
1030
+ You should tell Fluentd where the selector class exists.
1031
+
1032
+ If you use td-agent, you must put the following lines into `TD_AGENT_DEFAULT` file:
1033
+
1034
+ ```
1035
+ selector=/path/to/your_awesome_selector.rb
1036
+ TD_AGENT_OPTIONS="--use-v1-config -r $selector"
1037
+ ```
1038
+
1039
+ If you use Fluentd directly, you must pass the following lines as Fluentd command line option:
1040
+
1041
+ ```
1042
+ selector=/path/to/your_awesome_selector.rb
1043
+ $ fluentd -r $selector [AND YOUR OTHER OPTIONS]
1044
+ ```
1045
+
1009
1046
  ### Reload After
1010
1047
 
1011
1048
  When `reload_connections true`, this is the integer number of operations after which the plugin will
@@ -1720,7 +1757,7 @@ ILM target index alias is created with `index_name` or an index which is calcula
1720
1757
 
1721
1758
  From Elasticsearch plugin v4.0.0, ILM target index will be calculated from `index_name` (normal mode) or `logstash_prefix` (using with `logstash_format`as true).
1722
1759
 
1723
- When using `deflector_alias` parameter, Elasticsearch plugin will create ILM target indices alias with `deflector_alias` instead of `index_name` or an index which is calculated from `logstash_prefix`. This behavior should be kept due to backward ILM feature compatibility.
1760
+ **NOTE:** Before Elasticsearch plugin v4.1.0, using `deflector_alias` parameter when ILM is enabled is permitted and handled, but, in the later releases such that 4.1.1 or later, it cannot use with when ILM is enabled.
1724
1761
 
1725
1762
  And also, ILM feature users should specify their Elasticsearch template for ILM enabled indices.
1726
1763
  Because ILM settings are injected into their Elasticsearch templates.
@@ -1733,7 +1770,13 @@ It usually should be used with default value which is `default`.
1733
1770
 
1734
1771
  Then, ILM parameters are used in alias index like as:
1735
1772
 
1736
- `<index_name/logstash_prefix><index_separator><application_name>-000001`.
1773
+ ##### Simple `index_name` case:
1774
+
1775
+ `<index_name><index_separator><application_name>-000001`.
1776
+
1777
+ ##### `logstash_format` as `true` case:
1778
+
1779
+ `<logstash_prefix><logstash_prefix_separator><application_name><logstash_prefix_separator><logstash_dateformat>-000001`.
1737
1780
 
1738
1781
  #### Example ILM settings
1739
1782
 
@@ -3,7 +3,7 @@ $:.push File.expand_path('../lib', __FILE__)
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = 'fluent-plugin-elasticsearch'
6
- s.version = '4.0.10'
6
+ s.version = '4.1.3'
7
7
  s.authors = ['diogo', 'pitr', 'Hiroshi Hatake']
8
8
  s.email = ['pitr.vern@gmail.com', 'me@diogoterror.com', 'cosmo0920.wp@gmail.com']
9
9
  s.description = %q{Elasticsearch output plugin for Fluent event collector}
@@ -0,0 +1,9 @@
1
+ require 'elasticsearch/transport/transport/connections/selector'
2
+
3
+ class Fluent::Plugin::ElasticseatchFallbackSelector
4
+ include Elasticsearch::Transport::Transport::Connections::Selector::Base
5
+
6
+ def select(options={})
7
+ connections.first
8
+ end
9
+ end
@@ -65,11 +65,12 @@ module Fluent::ElasticsearchIndexTemplate
65
65
  end
66
66
  end
67
67
 
68
- def template_install(name, template_file, overwrite, enable_ilm = false, deflector_alias_name = nil, ilm_policy_id = nil, host = nil)
68
+ def template_install(name, template_file, overwrite, enable_ilm = false, deflector_alias_name = nil, ilm_policy_id = nil, host = nil, target_index = nil)
69
69
  inject_template_name = get_template_name(enable_ilm, name, deflector_alias_name)
70
70
  if overwrite
71
71
  template_put(inject_template_name,
72
72
  enable_ilm ? inject_ilm_settings_to_template(deflector_alias_name,
73
+ target_index,
73
74
  ilm_policy_id,
74
75
  get_template(template_file)) :
75
76
  get_template(template_file), host)
@@ -80,6 +81,7 @@ module Fluent::ElasticsearchIndexTemplate
80
81
  if !template_exists?(inject_template_name, host)
81
82
  template_put(inject_template_name,
82
83
  enable_ilm ? inject_ilm_settings_to_template(deflector_alias_name,
84
+ target_index,
83
85
  ilm_policy_id,
84
86
  get_template(template_file)) :
85
87
  get_template(template_file), host)
@@ -89,10 +91,12 @@ module Fluent::ElasticsearchIndexTemplate
89
91
  end
90
92
  end
91
93
 
92
- def template_custom_install(template_name, template_file, overwrite, customize_template, enable_ilm, deflector_alias_name, ilm_policy_id, host)
94
+ def template_custom_install(template_name, template_file, overwrite, customize_template, enable_ilm, deflector_alias_name, ilm_policy_id, host, target_index)
93
95
  template_custom_name = get_template_name(enable_ilm, template_name, deflector_alias_name)
94
96
  custom_template = if enable_ilm
95
- inject_ilm_settings_to_template(deflector_alias_name, ilm_policy_id,
97
+ inject_ilm_settings_to_template(deflector_alias_name,
98
+ target_index,
99
+ ilm_policy_id,
96
100
  get_custom_template(template_file,
97
101
  customize_template))
98
102
  else
@@ -115,26 +119,30 @@ module Fluent::ElasticsearchIndexTemplate
115
119
  enable_ilm ? deflector_alias_name : template_name
116
120
  end
117
121
 
118
- def inject_ilm_settings_to_template(deflector_alias_name, ilm_policy_id, template)
122
+ def inject_ilm_settings_to_template(deflector_alias, target_index, ilm_policy_id, template)
119
123
  log.debug("Overwriting index patterns when Index Lifecycle Management is enabled.")
120
124
  template.delete('template') if template.include?('template')
121
- template['index_patterns'] = "#{deflector_alias_name}-*"
122
- template['order'] = template['order'] ? template['order'] + deflector_alias_name.split('-').length : 50 + deflector_alias_name.split('-').length
125
+ template['index_patterns'] = "#{target_index}-*"
126
+ template['order'] = template['order'] ? template['order'] + target_index.split('-').length : 50 + target_index.split('-').length
123
127
  if template['settings'] && (template['settings']['index.lifecycle.name'] || template['settings']['index.lifecycle.rollover_alias'])
124
128
  log.debug("Overwriting index lifecycle name and rollover alias when Index Lifecycle Management is enabled.")
125
129
  end
126
- template['settings'].update({ 'index.lifecycle.name' => ilm_policy_id, 'index.lifecycle.rollover_alias' => deflector_alias_name})
130
+ template['settings'].update({ 'index.lifecycle.name' => ilm_policy_id, 'index.lifecycle.rollover_alias' => deflector_alias})
127
131
  template
128
132
  end
129
133
 
130
- def create_rollover_alias(index_prefix, rollover_index, deflector_alias_name, app_name, index_date_pattern, index_separator, enable_ilm, ilm_policy_id, ilm_policy, ilm_policy_overwrite, host)
134
+ def create_rollover_alias(target_index, rollover_index, deflector_alias_name, app_name, index_date_pattern, index_separator, enable_ilm, ilm_policy_id, ilm_policy, ilm_policy_overwrite, host)
131
135
  # ILM request to create alias.
132
136
  if rollover_index || enable_ilm
133
137
  if !client.indices.exists_alias(:name => deflector_alias_name)
134
- if index_date_pattern.empty?
135
- index_name_temp='<'+index_prefix.downcase+index_separator+app_name.downcase+'-000001>'
138
+ if @logstash_format
139
+ index_name_temp = '<'+target_index+'-000001>'
136
140
  else
137
- index_name_temp='<'+index_prefix.downcase+index_separator+app_name.downcase+'-{'+index_date_pattern+'}-000001>'
141
+ if index_date_pattern.empty?
142
+ index_name_temp = '<'+target_index.downcase+index_separator+app_name.downcase+'-000001>'
143
+ else
144
+ index_name_temp = '<'+target_index.downcase+index_separator+app_name.downcase+'-{'+index_date_pattern+'}-000001>'
145
+ end
138
146
  end
139
147
  indexcreation(index_name_temp, host)
140
148
  body = rollover_alias_payload(deflector_alias_name)
@@ -25,6 +25,7 @@ require_relative 'elasticsearch_error_handler'
25
25
  require_relative 'elasticsearch_index_template'
26
26
  require_relative 'elasticsearch_index_lifecycle_management'
27
27
  require_relative 'elasticsearch_tls'
28
+ require_relative 'elasticsearch_fallback_selector'
28
29
  begin
29
30
  require_relative 'oj_serializer'
30
31
  rescue LoadError
@@ -50,7 +51,7 @@ module Fluent::Plugin
50
51
  end
51
52
  end
52
53
 
53
- RequestInfo = Struct.new(:host, :index, :ilm_index)
54
+ RequestInfo = Struct.new(:host, :index, :ilm_index, :ilm_alias)
54
55
 
55
56
  attr_reader :alias_indexes
56
57
  attr_reader :template_names
@@ -137,6 +138,7 @@ EOC
137
138
  config_param :with_transporter_log, :bool, :default => false
138
139
  config_param :emit_error_for_missing_id, :bool, :default => false
139
140
  config_param :sniffer_class_name, :string, :default => nil
141
+ config_param :selector_class_name, :string, :default => nil
140
142
  config_param :reload_after, :integer, :default => DEFAULT_RELOAD_AFTER
141
143
  config_param :content_type, :enum, list: [:"application/json", :"application/x-ndjson"], :default => :"application/json",
142
144
  :deprecated => <<EOC
@@ -232,7 +234,7 @@ EOC
232
234
  if !dry_run?
233
235
  if @template_name && @template_file
234
236
  if @enable_ilm
235
- raise Fluent::ConfigError, "deflector_alias is prohibited to use with 'logstash_format at same time." if @logstash_format and @deflector_alias
237
+ raise Fluent::ConfigError, "deflector_alias is prohibited to use with enable_ilm at same time." if @deflector_alias
236
238
  end
237
239
  if @ilm_policy.empty? && @ilm_policy_overwrite
238
240
  raise Fluent::ConfigError, "ilm_policy_overwrite requires a non empty ilm_policy."
@@ -245,7 +247,8 @@ EOC
245
247
  template_installation_actual(@deflector_alias ? @deflector_alias : @index_name, @template_name, @customize_template, @application_name, @index_name, @ilm_policy_id)
246
248
  end
247
249
  verify_ilm_working if @enable_ilm
248
- elsif @templates
250
+ end
251
+ if @templates
249
252
  retry_operate(@max_retry_putting_template, @fail_on_putting_template_retry_exceed) do
250
253
  templates_hash_install(@templates, @template_overwrite)
251
254
  end
@@ -300,6 +303,13 @@ EOC
300
303
  raise Fluent::ConfigError, "Could not load sniffer class #{@sniffer_class_name}: #{ex}"
301
304
  end
302
305
 
306
+ @selector_class = nil
307
+ begin
308
+ @selector_class = Object.const_get(@selector_class_name) if @selector_class_name
309
+ rescue Exception => ex
310
+ raise Fluent::ConfigError, "Could not load selector class #{@selector_class_name}: #{ex}"
311
+ end
312
+
303
313
  @last_seen_major_version = if major_version = handle_last_seen_es_major_version
304
314
  major_version
305
315
  else
@@ -452,7 +462,10 @@ EOC
452
462
 
453
463
  def detect_es_major_version
454
464
  @_es_info ||= client.info
455
- @_es_info["version"]["number"].to_i
465
+ unless version = @_es_info.dig("version", "number")
466
+ version = @default_elasticsearch_version
467
+ end
468
+ version.to_i
456
469
  end
457
470
 
458
471
  def client_library_version
@@ -566,6 +579,7 @@ EOC
566
579
  },
567
580
  sniffer_class: @sniffer_class,
568
581
  serializer_class: @serializer_class,
582
+ selector_class: @selector_class,
569
583
  compression: compress_connection,
570
584
  }), &adapter_conf)
571
585
  Elasticsearch::Client.new transport: transport
@@ -761,9 +775,9 @@ EOC
761
775
  begin
762
776
  meta, header, record = process_message(tag, meta, header, time, record, extracted_values)
763
777
  info = if @include_index_in_url
764
- RequestInfo.new(host, meta.delete("_index".freeze), meta["_index".freeze])
778
+ RequestInfo.new(host, meta.delete("_index".freeze), meta["_index".freeze], meta.delete("_alias".freeze))
765
779
  else
766
- RequestInfo.new(host, nil, meta["_index".freeze])
780
+ RequestInfo.new(host, nil, meta["_index".freeze], meta.delete("_alias".freeze))
767
781
  end
768
782
 
769
783
  if split_request?(bulk_message, info)
@@ -809,7 +823,7 @@ EOC
809
823
  end
810
824
 
811
825
  def process_message(tag, meta, header, time, record, extracted_values)
812
- logstash_prefix, logstash_dateformat, index_name, type_name, _template_name, _customize_template, _deflector_alias, _application_name, pipeline, _ilm_policy_id = extracted_values
826
+ logstash_prefix, logstash_dateformat, index_name, type_name, _template_name, _customize_template, _deflector_alias, application_name, pipeline, _ilm_policy_id = extracted_values
813
827
 
814
828
  if @flatten_hashes
815
829
  record = flatten_record(record)
@@ -832,17 +846,19 @@ EOC
832
846
 
833
847
  target_index_parent, target_index_child_key = @target_index_key ? get_parent_of(record, @target_index_key) : nil
834
848
  if target_index_parent && target_index_parent[target_index_child_key]
835
- target_index = target_index_parent.delete(target_index_child_key)
849
+ target_index_alias = target_index = target_index_parent.delete(target_index_child_key)
836
850
  elsif @logstash_format
837
851
  dt = dt.new_offset(0) if @utc_index
838
852
  target_index = "#{logstash_prefix}#{@logstash_prefix_separator}#{dt.strftime(logstash_dateformat)}"
853
+ target_index_alias = "#{logstash_prefix}#{@logstash_prefix_separator}#{application_name}#{@logstash_prefix_separator}#{dt.strftime(logstash_dateformat)}"
839
854
  else
840
- target_index = index_name
855
+ target_index_alias = target_index = index_name
841
856
  end
842
857
 
843
858
  # Change target_index to lower-case since Elasticsearch doesn't
844
859
  # allow upper-case characters in index names.
845
860
  target_index = target_index.downcase
861
+ target_index_alias = target_index_alias.downcase
846
862
  if @include_tag_key
847
863
  record[@tag_key] = tag
848
864
  end
@@ -877,6 +893,7 @@ EOC
877
893
  meta.clear
878
894
  meta["_index".freeze] = target_index
879
895
  meta["_type".freeze] = target_type unless @last_seen_major_version >= 8
896
+ meta["_alias".freeze] = target_index_alias
880
897
 
881
898
  if @pipeline
882
899
  meta["pipeline".freeze] = pipeline
@@ -931,16 +948,16 @@ EOC
931
948
 
932
949
  def template_installation_actual(deflector_alias, template_name, customize_template, application_name, target_index, ilm_policy_id, host=nil)
933
950
  if template_name && @template_file
934
- if @alias_indexes.include? deflector_alias
951
+ if !@logstash_format && @alias_indexes.include?(deflector_alias)
935
952
  log.debug("Index alias #{deflector_alias} already exists (cached)")
936
- elsif @template_names.include? template_name
953
+ elsif !@logstash_format && @template_names.include?(template_name)
937
954
  log.debug("Template name #{template_name} already exists (cached)")
938
955
  else
939
956
  retry_operate(@max_retry_putting_template, @fail_on_putting_template_retry_exceed) do
940
957
  if customize_template
941
- template_custom_install(template_name, @template_file, @template_overwrite, customize_template, @enable_ilm, deflector_alias, ilm_policy_id, host)
958
+ template_custom_install(template_name, @template_file, @template_overwrite, customize_template, @enable_ilm, deflector_alias, ilm_policy_id, host, target_index)
942
959
  else
943
- template_install(template_name, @template_file, @template_overwrite, @enable_ilm, deflector_alias, ilm_policy_id, host)
960
+ template_install(template_name, @template_file, @template_overwrite, @enable_ilm, deflector_alias, ilm_policy_id, host, target_index)
944
961
  end
945
962
  ilm_policy = @ilm_policies[ilm_policy_id] || {}
946
963
  create_rollover_alias(target_index, @rollover_index, deflector_alias, application_name, @index_date_pattern, @index_separator, @enable_ilm, ilm_policy_id, ilm_policy, @ilm_policy_overwrite, host)
@@ -954,11 +971,11 @@ EOC
954
971
  # send_bulk given a specific bulk request, the original tag,
955
972
  # chunk, and bulk_message_count
956
973
  def send_bulk(data, tag, chunk, bulk_message_count, extracted_values, info)
957
- logstash_prefix, _logstash_dateformat, index_name, _type_name, template_name, customize_template, deflector_alias, application_name, _pipeline, ilm_policy_id = extracted_values
974
+ _logstash_prefix, _logstash_dateformat, index_name, _type_name, template_name, customize_template, deflector_alias, application_name, _pipeline, ilm_policy_id = extracted_values
958
975
  if deflector_alias
959
976
  template_installation(deflector_alias, template_name, customize_template, application_name, index_name, ilm_policy_id, info.host)
960
977
  else
961
- template_installation(info.ilm_index, template_name, customize_template, application_name, @logstash_format ? logstash_prefix : index_name, ilm_policy_id, info.host)
978
+ template_installation(info.ilm_index, template_name, customize_template, application_name, @logstash_format ? info.ilm_alias : index_name, ilm_policy_id, info.host)
962
979
  end
963
980
 
964
981
  begin
@@ -0,0 +1,73 @@
1
+ require_relative '../helper'
2
+ require 'fluent/test/driver/output'
3
+ require 'fluent/plugin/out_elasticsearch'
4
+
5
+ class ElasticsearchFallbackSelectorTest < Test::Unit::TestCase
6
+ attr_accessor :index_cmds
7
+
8
+ def setup
9
+ Fluent::Test.setup
10
+ @driver = nil
11
+ log = Fluent::Engine.log
12
+ log.out.logs.slice!(0, log.out.logs.length)
13
+ end
14
+
15
+ def stub_elastic(url="http://localhost:9200/_bulk")
16
+ stub_request(:post, url).with do |req|
17
+ @index_cmds = req.body.split("\n").map {|r| JSON.parse(r) }
18
+ end
19
+ end
20
+
21
+ def stub_elastic_info(url="http://localhost:9200/", version="6.4.2")
22
+ body ="{\"version\":{\"number\":\"#{version}\"}}"
23
+ stub_request(:get, url).to_return({:status => 200, :body => body, :headers => { 'Content-Type' => 'json' } })
24
+ end
25
+
26
+ def stub_elastic_info_not_found(url="http://localhost:9200/", version="6.4.2")
27
+ stub_request(:get, url).to_return(:status => [404, "Not Found"])
28
+ end
29
+
30
+ def stub_elastic_info_unavailable(url="http://localhost:9200/", version="6.4.2")
31
+ stub_request(:get, url).to_return(:status => [503, "Service Unavailable"])
32
+ end
33
+
34
+ def sample_record(content={})
35
+ {'age' => 26, 'request_id' => '42', 'parent_id' => 'parent', 'routing_id' => 'routing'}.merge(content)
36
+ end
37
+
38
+ def driver(conf='')
39
+ @driver ||= Fluent::Test::Driver::Output.new(Fluent::Plugin::ElasticsearchOutput) {
40
+ # v0.12's test driver assume format definition. This simulates ObjectBufferedOutput format
41
+ if !defined?(Fluent::Plugin::Output)
42
+ def format(tag, time, record)
43
+ [time, record].to_msgpack
44
+ end
45
+ end
46
+ }.configure(conf)
47
+ end
48
+
49
+ def test_fallback_on_info
50
+ stub_elastic_info_not_found("http://localhost:9202/")
51
+ stub_elastic_info_unavailable("http://localhost:9201/")
52
+ stub_elastic_info
53
+ stub_elastic
54
+ config = %[
55
+ hosts localhost:9202,localhost:9201,localhost:9200
56
+ selector_class_name Fluent::Plugin::ElasticseatchFallbackSelector
57
+ @log_level debug
58
+ with_transporter_log true
59
+ reload_connections true
60
+ reload_after 10
61
+ ]
62
+ assert_raise(Elasticsearch::Transport::Transport::Errors::NotFound) do
63
+ driver(config)
64
+ end
65
+ driver.run(default_tag: 'test') do
66
+ driver.feed(sample_record)
67
+ end
68
+ assert_equal(2, index_cmds.length)
69
+ assert_equal("fluentd", index_cmds.first['index']['_index'])
70
+ end
71
+
72
+ # TODO: on feed phase test case
73
+ end
@@ -20,6 +20,11 @@ class ElasticsearchInputTest < Test::Unit::TestCase
20
20
  @driver = nil
21
21
  log = Fluent::Engine.log
22
22
  log.out.logs.slice!(0, log.out.logs.length)
23
+ @http_method = if Gem::Version.new(Elasticsearch::VERSION) >= Gem::Version.new("7.9.0")
24
+ :post
25
+ else
26
+ :get
27
+ end
23
28
  end
24
29
 
25
30
  def driver(conf='')
@@ -313,7 +318,7 @@ class ElasticsearchInputTest < Test::Unit::TestCase
313
318
  end
314
319
 
315
320
  def test_emit
316
- stub_request(:get, "http://localhost:9200/fluentd/_search?scroll=1m&size=1000").
321
+ stub_request(@http_method, "http://localhost:9200/fluentd/_search?scroll=1m&size=1000").
317
322
  with(body: "{\"sort\":[\"_doc\"]}").
318
323
  to_return(status: 200, body: sample_response.to_s,
319
324
  headers: {'Content-Type' => 'application/json'})
@@ -328,7 +333,7 @@ class ElasticsearchInputTest < Test::Unit::TestCase
328
333
 
329
334
  def test_emit_with_custom_index_name
330
335
  index_name = "logstash"
331
- stub_request(:get, "http://localhost:9200/#{index_name}/_search?scroll=1m&size=1000").
336
+ stub_request(@http_method, "http://localhost:9200/#{index_name}/_search?scroll=1m&size=1000").
332
337
  with(body: "{\"sort\":[\"_doc\"]}").
333
338
  to_return(status: 200, body: sample_response(index_name).to_s,
334
339
  headers: {'Content-Type' => 'application/json'})
@@ -343,7 +348,7 @@ class ElasticsearchInputTest < Test::Unit::TestCase
343
348
 
344
349
  def test_emit_with_parse_timestamp
345
350
  index_name = "fluentd"
346
- stub_request(:get, "http://localhost:9200/#{index_name}/_search?scroll=1m&size=1000").
351
+ stub_request(@http_method, "http://localhost:9200/#{index_name}/_search?scroll=1m&size=1000").
347
352
  with(body: "{\"sort\":[\"_doc\"]}").
348
353
  to_return(status: 200, body: sample_response(index_name).to_s,
349
354
  headers: {'Content-Type' => 'application/json'})
@@ -361,7 +366,7 @@ class ElasticsearchInputTest < Test::Unit::TestCase
361
366
 
362
367
  def test_emit_with_parse_timestamp_and_timstamp_format
363
368
  index_name = "fluentd"
364
- stub_request(:get, "http://localhost:9200/#{index_name}/_search?scroll=1m&size=1000").
369
+ stub_request(@http_method, "http://localhost:9200/#{index_name}/_search?scroll=1m&size=1000").
365
370
  with(body: "{\"sort\":[\"_doc\"]}").
366
371
  to_return(status: 200, body: sample_response(index_name).to_s,
367
372
  headers: {'Content-Type' => 'application/json'})
@@ -380,7 +385,7 @@ class ElasticsearchInputTest < Test::Unit::TestCase
380
385
  end
381
386
 
382
387
  def test_emit_with_docinfo
383
- stub_request(:get, "http://localhost:9200/fluentd/_search?scroll=1m&size=1000").
388
+ stub_request(@http_method, "http://localhost:9200/fluentd/_search?scroll=1m&size=1000").
384
389
  with(body: "{\"sort\":[\"_doc\"]}").
385
390
  to_return(status: 200, body: sample_response.to_s,
386
391
  headers: {'Content-Type' => 'application/json'})
@@ -399,11 +404,11 @@ class ElasticsearchInputTest < Test::Unit::TestCase
399
404
  end
400
405
 
401
406
  def test_emit_with_slices
402
- stub_request(:get, "http://localhost:9200/fluentd/_search?scroll=1m&size=1000").
407
+ stub_request(@http_method, "http://localhost:9200/fluentd/_search?scroll=1m&size=1000").
403
408
  with(body: "{\"sort\":[\"_doc\"],\"slice\":{\"id\":0,\"max\":2}}").
404
409
  to_return(status: 200, body: sample_response.to_s,
405
410
  headers: {'Content-Type' => 'application/json'})
406
- stub_request(:get, "http://localhost:9200/fluentd/_search?scroll=1m&size=1000").
411
+ stub_request(@http_method, "http://localhost:9200/fluentd/_search?scroll=1m&size=1000").
407
412
  with(body: "{\"sort\":[\"_doc\"],\"slice\":{\"id\":1,\"max\":2}}").
408
413
  to_return(status: 200, body: sample_response.to_s,
409
414
  headers: {'Content-Type' => 'application/json'})
@@ -419,12 +424,12 @@ class ElasticsearchInputTest < Test::Unit::TestCase
419
424
  end
420
425
 
421
426
  def test_emit_with_size
422
- stub_request(:get, "http://localhost:9200/fluentd/_search?scroll=1m&size=1").
427
+ stub_request(@http_method, "http://localhost:9200/fluentd/_search?scroll=1m&size=1").
423
428
  with(body: "{\"sort\":[\"_doc\"]}").
424
429
  to_return(status: 200, body: sample_scroll_response.to_s,
425
430
  headers: {'Content-Type' => 'application/json'})
426
431
  connection = 0
427
- scroll_request = stub_request(:get, "http://localhost:9200/_search/scroll?scroll=1m").
432
+ scroll_request = stub_request(@http_method, "http://localhost:9200/_search/scroll?scroll=1m").
428
433
  with(
429
434
  body: "{\"scroll_id\":\"WomkoUKG0QPB679Ulo6TqQgh3pIGRUmrl9qXXGK3EeiQh9rbYNasTkspZQcJ01uz\"}") do
430
435
  connection += 1
@@ -707,7 +707,10 @@ class ElasticsearchOutputTest < Test::Unit::TestCase
707
707
  Fluent::Plugin::ElasticsearchOutput.module_eval(<<-CODE)
708
708
  def detect_es_major_version
709
709
  @_es_info ||= client.info
710
- @_es_info["version"]["number"].to_i
710
+ unless version = @_es_info.dig("version", "number")
711
+ version = @default_elasticsearch_version
712
+ end
713
+ version.to_i
711
714
  end
712
715
  CODE
713
716
  Fluent::Plugin::ElasticsearchOutput.module_eval(<<-CODE)
@@ -753,7 +756,10 @@ class ElasticsearchOutputTest < Test::Unit::TestCase
753
756
  Fluent::Plugin::ElasticsearchOutput.module_eval(<<-CODE)
754
757
  def detect_es_major_version
755
758
  @_es_info ||= client.info
756
- @_es_info["version"]["number"].to_i
759
+ unless version = @_es_info.dig("version", "number")
760
+ version = @default_elasticsearch_version
761
+ end
762
+ version.to_i
757
763
  end
758
764
  CODE
759
765
  Fluent::Plugin::ElasticsearchOutput.module_eval(<<-CODE)
@@ -1053,7 +1059,7 @@ class ElasticsearchOutputTest < Test::Unit::TestCase
1053
1059
  assert_requested(:put, "https://logs.google.com:777/es//_template/logstash", times: 1)
1054
1060
  end
1055
1061
 
1056
- def test_template_create_with_rollover_index_and_default_ilm_and_ilm_policy_overwrite
1062
+ def test_template_create_with_rollover_index_and_default_ilm_on_logstash_format
1057
1063
  cwd = File.dirname(__FILE__)
1058
1064
  template_file = File.join(cwd, 'test_template.json')
1059
1065
 
@@ -1067,60 +1073,67 @@ class ElasticsearchOutputTest < Test::Unit::TestCase
1067
1073
  template_name logstash
1068
1074
  template_file #{template_file}
1069
1075
  index_date_pattern now/w{xxxx.ww}
1070
- index_name logstash
1071
1076
  enable_ilm true
1072
- ilm_policy_overwrite true
1073
- ilm_policy {"policy":{"phases":{"hot":{"actions":{"rollover":{"max_size":"60gb","max_age": "45d"}}}}}}
1077
+ logstash_format true
1078
+ application_name log
1074
1079
  }
1075
1080
 
1081
+ date_str = Time.now.strftime("%Y.%m.%d")
1076
1082
  # connection start
1077
1083
  stub_request(:head, "https://logs.google.com:777/es//").
1078
1084
  with(basic_auth: ['john', 'doe']).
1079
1085
  to_return(:status => 200, :body => "", :headers => {})
1080
1086
  # check if template exists
1081
- stub_request(:get, "https://logs.google.com:777/es//_template/logstash").
1087
+ stub_request(:get, "https://logs.google.com:777/es//_template/logstash-#{date_str}").
1082
1088
  with(basic_auth: ['john', 'doe']).
1083
1089
  to_return(:status => 404, :body => "", :headers => {})
1084
1090
  # creation
1085
- stub_request(:put, "https://logs.google.com:777/es//_template/logstash").
1091
+ stub_request(:put, "https://logs.google.com:777/es//_template/logstash-#{date_str}").
1086
1092
  with(basic_auth: ['john', 'doe']).
1087
1093
  to_return(:status => 200, :body => "", :headers => {})
1088
1094
  # check if alias exists
1089
- stub_request(:head, "https://logs.google.com:777/es//_alias/logstash").
1095
+ stub_request(:head, "https://logs.google.com:777/es//_alias/logstash-#{date_str}").
1090
1096
  with(basic_auth: ['john', 'doe']).
1091
1097
  to_return(:status => 404, :body => "", :headers => {})
1092
- stub_request(:get, "https://logs.google.com:777/es//_template/logstash").
1098
+ stub_request(:get, "https://logs.google.com:777/es//_template/logstash-#{date_str}").
1093
1099
  with(basic_auth: ['john', 'doe']).
1094
1100
  to_return(status: 404, body: "", headers: {})
1095
- stub_request(:put, "https://logs.google.com:777/es//_template/logstash").
1101
+ stub_request(:put, "https://logs.google.com:777/es//_template/logstash-#{date_str}").
1096
1102
  with(basic_auth: ['john', 'doe'],
1097
- body: "{\"settings\":{\"number_of_shards\":1,\"index.lifecycle.name\":\"logstash-policy\",\"index.lifecycle.rollover_alias\":\"logstash\"},\"mappings\":{\"type1\":{\"_source\":{\"enabled\":false},\"properties\":{\"host_name\":{\"type\":\"string\",\"index\":\"not_analyzed\"},\"created_at\":{\"type\":\"date\",\"format\":\"EEE MMM dd HH:mm:ss Z YYYY\"}}}},\"index_patterns\":\"logstash-*\",\"order\":51}").
1103
+ body: "{\"settings\":{\"number_of_shards\":1,\"index.lifecycle.name\":\"logstash-policy\",\"index.lifecycle.rollover_alias\":\"logstash-log-#{date_str}\"},\"mappings\":{\"type1\":{\"_source\":{\"enabled\":false},\"properties\":{\"host_name\":{\"type\":\"string\",\"index\":\"not_analyzed\"},\"created_at\":{\"type\":\"date\",\"format\":\"EEE MMM dd HH:mm:ss Z YYYY\"}}}},\"index_patterns\":\"logstash-log-#{date_str}-*\",\"order\":53}").
1098
1104
  to_return(status: 200, body: "", headers: {})
1099
1105
  # put the alias for the index
1100
- stub_request(:put, "https://logs.google.com:777/es//%3Clogstash-default-%7Bnow%2Fw%7Bxxxx.ww%7D%7D-000001%3E").
1106
+ stub_request(:put, "https://logs.google.com:777/es//%3Clogstash-log-#{date_str}-000001%3E").
1101
1107
  with(basic_auth: ['john', 'doe']).
1102
1108
  to_return(:status => 200, :body => "", :headers => {})
1103
- stub_request(:put, "https://logs.google.com:777/es//%3Clogstash-default-%7Bnow%2Fw%7Bxxxx.ww%7D%7D-000001%3E/#{alias_endpoint}/logstash").
1109
+
1110
+ stub_request(:put, "https://logs.google.com:777/es//%3Clogstash-log-#{date_str}-000001%3E/#{alias_endpoint}/logstash-#{date_str}").
1104
1111
  with(basic_auth: ['john', 'doe'],
1105
- :body => "{\"aliases\":{\"logstash\":{\"is_write_index\":true}}}").
1106
- to_return(:status => 200, :body => "", :headers => {})
1112
+ body: "{\"aliases\":{\"logstash-#{date_str}\":{\"is_write_index\":true}}}").
1113
+ to_return(status: 200, body: "", headers: {})
1107
1114
  stub_request(:get, "https://logs.google.com:777/es//_xpack").
1108
1115
  with(basic_auth: ['john', 'doe']).
1109
1116
  to_return(:status => 200, :body => '{"features":{"ilm":{"available":true,"enabled":true}}}', :headers => {"Content-Type"=> "application/json"})
1110
1117
  stub_request(:get, "https://logs.google.com:777/es//_ilm/policy/logstash-policy").
1111
1118
  with(basic_auth: ['john', 'doe']).
1112
- to_return(:status => 200, :body => "", :headers => {})
1119
+ to_return(:status => 404, :body => "", :headers => {})
1113
1120
  stub_request(:put, "https://logs.google.com:777/es//_ilm/policy/logstash-policy").
1114
1121
  with(basic_auth: ['john', 'doe'],
1115
- :body => "{\"policy\":{\"phases\":{\"hot\":{\"actions\":{\"rollover\":{\"max_size\":\"60gb\",\"max_age\":\"45d\"}}}}}}").
1122
+ :body => "{\"policy\":{\"phases\":{\"hot\":{\"actions\":{\"rollover\":{\"max_size\":\"50gb\",\"max_age\":\"30d\"}}}}}}").
1116
1123
  to_return(:status => 200, :body => "", :headers => {})
1117
1124
 
1118
1125
  driver(config)
1119
1126
 
1120
- assert_requested(:put, "https://logs.google.com:777/es//_template/logstash", times: 1)
1127
+ elastic_request = stub_elastic("https://logs.google.com:777/es//_bulk")
1128
+ driver.run(default_tag: 'test') do
1129
+ driver.feed(sample_record)
1130
+ end
1131
+ assert_requested(:put, "https://logs.google.com:777/es//_template/logstash-#{date_str}", times: 1)
1132
+
1133
+ assert_requested(elastic_request)
1121
1134
  end
1122
1135
 
1123
- def test_template_create_with_rollover_index_and_default_ilm_with_deflector_alias
1136
+ def test_template_create_with_rollover_index_and_default_ilm_and_ilm_policy_overwrite
1124
1137
  cwd = File.dirname(__FILE__)
1125
1138
  template_file = File.join(cwd, 'test_template.json')
1126
1139
 
@@ -1134,9 +1147,10 @@ class ElasticsearchOutputTest < Test::Unit::TestCase
1134
1147
  template_name logstash
1135
1148
  template_file #{template_file}
1136
1149
  index_date_pattern now/w{xxxx.ww}
1137
- deflector_alias myapp_deflector
1138
1150
  index_name logstash
1139
1151
  enable_ilm true
1152
+ ilm_policy_overwrite true
1153
+ ilm_policy {"policy":{"phases":{"hot":{"actions":{"rollover":{"max_size":"60gb","max_age": "45d"}}}}}}
1140
1154
  }
1141
1155
 
1142
1156
  # connection start
@@ -1152,38 +1166,63 @@ class ElasticsearchOutputTest < Test::Unit::TestCase
1152
1166
  with(basic_auth: ['john', 'doe']).
1153
1167
  to_return(:status => 200, :body => "", :headers => {})
1154
1168
  # check if alias exists
1155
- stub_request(:head, "https://logs.google.com:777/es//_alias/myapp_deflector").
1169
+ stub_request(:head, "https://logs.google.com:777/es//_alias/logstash").
1156
1170
  with(basic_auth: ['john', 'doe']).
1157
1171
  to_return(:status => 404, :body => "", :headers => {})
1158
- stub_request(:get, "https://logs.google.com:777/es//_template/myapp_deflector").
1172
+ stub_request(:get, "https://logs.google.com:777/es//_template/logstash").
1159
1173
  with(basic_auth: ['john', 'doe']).
1160
1174
  to_return(status: 404, body: "", headers: {})
1161
- stub_request(:put, "https://logs.google.com:777/es//_template/myapp_deflector").
1175
+ stub_request(:put, "https://logs.google.com:777/es//_template/logstash").
1162
1176
  with(basic_auth: ['john', 'doe'],
1163
- body: "{\"settings\":{\"number_of_shards\":1,\"index.lifecycle.name\":\"logstash-policy\",\"index.lifecycle.rollover_alias\":\"myapp_deflector\"},\"mappings\":{\"type1\":{\"_source\":{\"enabled\":false},\"properties\":{\"host_name\":{\"type\":\"string\",\"index\":\"not_analyzed\"},\"created_at\":{\"type\":\"date\",\"format\":\"EEE MMM dd HH:mm:ss Z YYYY\"}}}},\"index_patterns\":\"myapp_deflector-*\",\"order\":51}").
1177
+ body: "{\"settings\":{\"number_of_shards\":1,\"index.lifecycle.name\":\"logstash-policy\",\"index.lifecycle.rollover_alias\":\"logstash\"},\"mappings\":{\"type1\":{\"_source\":{\"enabled\":false},\"properties\":{\"host_name\":{\"type\":\"string\",\"index\":\"not_analyzed\"},\"created_at\":{\"type\":\"date\",\"format\":\"EEE MMM dd HH:mm:ss Z YYYY\"}}}},\"index_patterns\":\"logstash-*\",\"order\":51}").
1164
1178
  to_return(status: 200, body: "", headers: {})
1165
1179
  # put the alias for the index
1166
1180
  stub_request(:put, "https://logs.google.com:777/es//%3Clogstash-default-%7Bnow%2Fw%7Bxxxx.ww%7D%7D-000001%3E").
1167
1181
  with(basic_auth: ['john', 'doe']).
1168
1182
  to_return(:status => 200, :body => "", :headers => {})
1169
- stub_request(:put, "https://logs.google.com:777/es//%3Clogstash-default-%7Bnow%2Fw%7Bxxxx.ww%7D%7D-000001%3E/#{alias_endpoint}/myapp_deflector").
1183
+ stub_request(:put, "https://logs.google.com:777/es//%3Clogstash-default-%7Bnow%2Fw%7Bxxxx.ww%7D%7D-000001%3E/#{alias_endpoint}/logstash").
1170
1184
  with(basic_auth: ['john', 'doe'],
1171
- :body => "{\"aliases\":{\"myapp_deflector\":{\"is_write_index\":true}}}").
1185
+ :body => "{\"aliases\":{\"logstash\":{\"is_write_index\":true}}}").
1172
1186
  to_return(:status => 200, :body => "", :headers => {})
1173
1187
  stub_request(:get, "https://logs.google.com:777/es//_xpack").
1174
1188
  with(basic_auth: ['john', 'doe']).
1175
1189
  to_return(:status => 200, :body => '{"features":{"ilm":{"available":true,"enabled":true}}}', :headers => {"Content-Type"=> "application/json"})
1176
1190
  stub_request(:get, "https://logs.google.com:777/es//_ilm/policy/logstash-policy").
1177
1191
  with(basic_auth: ['john', 'doe']).
1178
- to_return(:status => 404, :body => "", :headers => {})
1192
+ to_return(:status => 200, :body => "", :headers => {})
1179
1193
  stub_request(:put, "https://logs.google.com:777/es//_ilm/policy/logstash-policy").
1180
1194
  with(basic_auth: ['john', 'doe'],
1181
- :body => "{\"policy\":{\"phases\":{\"hot\":{\"actions\":{\"rollover\":{\"max_size\":\"50gb\",\"max_age\":\"30d\"}}}}}}").
1195
+ :body => "{\"policy\":{\"phases\":{\"hot\":{\"actions\":{\"rollover\":{\"max_size\":\"60gb\",\"max_age\":\"45d\"}}}}}}").
1182
1196
  to_return(:status => 200, :body => "", :headers => {})
1183
1197
 
1184
1198
  driver(config)
1185
1199
 
1186
- assert_requested(:put, "https://logs.google.com:777/es//_template/myapp_deflector", times: 1)
1200
+ assert_requested(:put, "https://logs.google.com:777/es//_template/logstash", times: 1)
1201
+ end
1202
+
1203
+ def test_template_create_with_rollover_index_and_default_ilm_with_deflector_alias
1204
+ cwd = File.dirname(__FILE__)
1205
+ template_file = File.join(cwd, 'test_template.json')
1206
+
1207
+ config = %{
1208
+ host logs.google.com
1209
+ port 777
1210
+ scheme https
1211
+ path /es/
1212
+ user john
1213
+ password doe
1214
+ template_name logstash
1215
+ template_file #{template_file}
1216
+ index_date_pattern now/w{xxxx.ww}
1217
+ deflector_alias myapp_deflector
1218
+ index_name logstash
1219
+ enable_ilm true
1220
+ }
1221
+
1222
+ # Should raise error because multiple alias indices IllegalArgument Error on executing ILM feature
1223
+ assert_raise(Fluent::ConfigError) do
1224
+ driver(config)
1225
+ end
1187
1226
  end
1188
1227
 
1189
1228
  def test_template_create_with_rollover_index_and_default_ilm_with_empty_index_date_pattern
@@ -1607,6 +1646,83 @@ class ElasticsearchOutputTest < Test::Unit::TestCase
1607
1646
 
1608
1647
  assert_requested(elastic_request)
1609
1648
  end
1649
+
1650
+ def test_template_create_with_rollover_index_and_default_ilm_and_custom_and_time_placeholders
1651
+ cwd = File.dirname(__FILE__)
1652
+ template_file = File.join(cwd, 'test_template.json')
1653
+
1654
+ config = Fluent::Config::Element.new(
1655
+ 'ROOT', '', {
1656
+ '@type' => 'elasticsearch',
1657
+ 'host' => 'logs.google.com',
1658
+ 'port' => 777,
1659
+ 'scheme' => "https",
1660
+ 'path' => "/es/",
1661
+ 'user' => 'john',
1662
+ 'password' => 'doe',
1663
+ 'template_name' => 'logstash',
1664
+ 'template_file' => "#{template_file}",
1665
+ 'index_date_pattern' => 'now/w{xxxx.ww}',
1666
+ 'index_name' => "${taskDef}-%Y.%m",
1667
+ 'enable_ilm' => true,
1668
+ }, [
1669
+ Fluent::Config::Element.new('buffer', 'tag, time, taskDef', {
1670
+ 'chunk_keys' => ['tag', 'time', 'taskDef'],
1671
+ 'timekey' => 3600,
1672
+ }, [])
1673
+ ]
1674
+ )
1675
+
1676
+ task_def_value = "task_definition"
1677
+ date_str = Time.now.strftime("%Y.%m")
1678
+ # connection start
1679
+ stub_request(:head, "https://logs.google.com:777/es//").
1680
+ with(basic_auth: ['john', 'doe']).
1681
+ to_return(:status => 200, :body => "", :headers => {})
1682
+ # check if template exists
1683
+ stub_request(:get, "https://logs.google.com:777/es//_template/#{task_def_value}-#{date_str}").
1684
+ with(basic_auth: ['john', 'doe']).
1685
+ to_return(:status => 404, :body => "", :headers => {})
1686
+ # creation
1687
+ stub_request(:put, "https://logs.google.com:777/es//_template/#{task_def_value}-#{date_str}").
1688
+ with(basic_auth: ['john', 'doe'],
1689
+ body: "{\"settings\":{\"number_of_shards\":1,\"index.lifecycle.name\":\"logstash-policy\",\"index.lifecycle.rollover_alias\":\"#{task_def_value}-#{date_str}\"},\"mappings\":{\"type1\":{\"_source\":{\"enabled\":false},\"properties\":{\"host_name\":{\"type\":\"string\",\"index\":\"not_analyzed\"},\"created_at\":{\"type\":\"date\",\"format\":\"EEE MMM dd HH:mm:ss Z YYYY\"}}}},\"index_patterns\":\"#{task_def_value}-#{date_str}-*\",\"order\":52}").
1690
+ to_return(:status => 200, :body => "", :headers => {})
1691
+ # check if alias exists
1692
+ stub_request(:head, "https://logs.google.com:777/es//_alias/#{task_def_value}-#{date_str}").
1693
+ with(basic_auth: ['john', 'doe']).
1694
+ to_return(:status => 404, :body => "", :headers => {})
1695
+ # put the alias for the index
1696
+ stub_request(:put, "https://logs.google.com:777/es//%3C#{task_def_value}-#{date_str}-default-%7Bnow%2Fw%7Bxxxx.ww%7D%7D-000001%3E").
1697
+ with(basic_auth: ['john', 'doe']).
1698
+ to_return(:status => 200, :body => "", :headers => {})
1699
+ stub_request(:put, "https://logs.google.com:777/es//%3C#{task_def_value}-#{date_str}-default-%7Bnow%2Fw%7Bxxxx.ww%7D%7D-000001%3E/#{alias_endpoint}/#{task_def_value}-#{date_str}").
1700
+ with(basic_auth: ['john', 'doe'],
1701
+ :body => "{\"aliases\":{\"#{task_def_value}-#{date_str}\":{\"is_write_index\":true}}}").
1702
+ to_return(:status => 200, :body => "", :headers => {})
1703
+ stub_request(:get, "https://logs.google.com:777/es//_xpack").
1704
+ with(basic_auth: ['john', 'doe']).
1705
+ to_return(:status => 200, :body => '{"features":{"ilm":{"available":true,"enabled":true}}}', :headers => {"Content-Type"=> "application/json"})
1706
+ stub_request(:get, "https://logs.google.com:777/es//_ilm/policy/logstash-policy").
1707
+ with(basic_auth: ['john', 'doe']).
1708
+ to_return(:status => 404, :body => "", :headers => {})
1709
+ stub_request(:put, "https://logs.google.com:777/es//_ilm/policy/logstash-policy").
1710
+ with(basic_auth: ['john', 'doe'],
1711
+ :body => "{\"policy\":{\"phases\":{\"hot\":{\"actions\":{\"rollover\":{\"max_size\":\"50gb\",\"max_age\":\"30d\"}}}}}}").
1712
+ to_return(:status => 200, :body => "", :headers => {})
1713
+
1714
+ driver(config)
1715
+
1716
+ elastic_request = stub_elastic("https://logs.google.com:777/es//_bulk")
1717
+ driver.run(default_tag: 'test') do
1718
+ driver.feed(sample_record.merge("taskDef" => task_def_value))
1719
+ end
1720
+ assert_equal("#{task_def_value}-#{date_str}", index_cmds.first['index']['_index'])
1721
+
1722
+ assert_equal ["#{task_def_value}-#{date_str}"], driver.instance.alias_indexes
1723
+
1724
+ assert_requested(elastic_request)
1725
+ end
1610
1726
  end
1611
1727
 
1612
1728
  def test_custom_template_create
@@ -1845,6 +1961,7 @@ class ElasticsearchOutputTest < Test::Unit::TestCase
1845
1961
  application_name myapp
1846
1962
  }
1847
1963
 
1964
+ timestr = Time.now.strftime("%Y.%m.%d")
1848
1965
  # connection start
1849
1966
  stub_request(:head, "https://logs.google.com:777/es//").
1850
1967
  with(basic_auth: ['john', 'doe']).
@@ -1858,17 +1975,17 @@ class ElasticsearchOutputTest < Test::Unit::TestCase
1858
1975
  with(basic_auth: ['john', 'doe']).
1859
1976
  to_return(:status => 200, :body => "", :headers => {})
1860
1977
  # creation of index which can rollover
1861
- stub_request(:put, "https://logs.google.com:777/es//%3Cmylogs-myapp-%7Bnow%2Fw%7Bxxxx.ww%7D%7D-000001%3E").
1978
+ stub_request(:put, "https://logs.google.com:777/es//%3Cmylogs-myapp-#{timestr}-000001%3E").
1862
1979
  with(basic_auth: ['john', 'doe']).
1863
1980
  to_return(:status => 200, :body => "", :headers => {})
1864
1981
  # check if alias exists
1865
- timestr = Time.now.strftime("%Y.%m.%d")
1866
1982
  stub_request(:head, "https://logs.google.com:777/es//_alias/mylogs-#{timestr}").
1867
1983
  with(basic_auth: ['john', 'doe']).
1868
1984
  to_return(:status => 404, :body => "", :headers => {})
1869
1985
  # put the alias for the index
1870
- stub_request(:put, "https://logs.google.com:777/es//%3Cmylogs-myapp-%7Bnow%2Fw%7Bxxxx.ww%7D%7D-000001%3E/#{alias_endpoint}/mylogs-#{timestr}").
1871
- with(basic_auth: ['john', 'doe']).
1986
+ stub_request(:put, "https://logs.google.com:777/es//%3Cmylogs-myapp-#{timestr}-000001%3E/#{alias_endpoint}/mylogs-#{timestr}").
1987
+ with(basic_auth: ['john', 'doe'],
1988
+ body: "{\"aliases\":{\"mylogs-#{timestr}\":{\"is_write_index\":true}}}").
1872
1989
  to_return(:status => 200, :body => "", :headers => {})
1873
1990
 
1874
1991
  driver(config)
@@ -2051,52 +2168,10 @@ class ElasticsearchOutputTest < Test::Unit::TestCase
2051
2168
  enable_ilm true
2052
2169
  }
2053
2170
 
2054
- # connection start
2055
- stub_request(:head, "https://logs.google.com:777/es//").
2056
- with(basic_auth: ['john', 'doe']).
2057
- to_return(:status => 200, :body => "", :headers => {})
2058
- # check if template exists
2059
- stub_request(:get, "https://logs.google.com:777/es//_template/myapp_alias_template").
2060
- with(basic_auth: ['john', 'doe']).
2061
- to_return(:status => 404, :body => "", :headers => {})
2062
- # creation
2063
- stub_request(:put, "https://logs.google.com:777/es//_template/myapp_alias_template").
2064
- with(basic_auth: ['john', 'doe']).
2065
- to_return(:status => 200, :body => "", :headers => {})
2066
- # creation of index which can rollover
2067
- stub_request(:put, "https://logs.google.com:777/es//%3Cmylogs-myapp-%7Bnow%2Fw%7Bxxxx.ww%7D%7D-000001%3E").
2068
- with(basic_auth: ['john', 'doe']).
2069
- to_return(:status => 200, :body => "", :headers => {})
2070
- # check if alias exists
2071
- stub_request(:head, "https://logs.google.com:777/es//_alias/myapp_deflector").
2072
- with(basic_auth: ['john', 'doe']).
2073
- to_return(:status => 404, :body => "", :headers => {})
2074
- stub_request(:get, "https://logs.google.com:777/es//_template/myapp_deflector").
2075
- with(basic_auth: ['john', 'doe']).
2076
- to_return(status: 404, body: "", headers: {})
2077
- stub_request(:put, "https://logs.google.com:777/es//_template/myapp_deflector").
2078
- with(basic_auth: ['john', 'doe'],
2079
- body: "{\"order\":6,\"settings\":{\"index.lifecycle.name\":\"fluentd-policy\",\"index.lifecycle.rollover_alias\":\"myapp_deflector\"},\"mappings\":{},\"aliases\":{\"myapp-logs-alias\":{}},\"index_patterns\":\"myapp_deflector-*\"}").
2080
- to_return(status: 200, body: "", headers: {})
2081
- # put the alias for the index
2082
- stub_request(:put, "https://logs.google.com:777/es//%3Cmylogs-myapp-%7Bnow%2Fw%7Bxxxx.ww%7D%7D-000001%3E/#{alias_endpoint}/myapp_deflector").
2083
- with(basic_auth: ['john', 'doe'],
2084
- :body => "{\"aliases\":{\"myapp_deflector\":{\"is_write_index\":true}}}").
2085
- to_return(:status => 200, :body => "", :headers => {})
2086
- stub_request(:get, "https://logs.google.com:777/es//_xpack").
2087
- with(basic_auth: ['john', 'doe']).
2088
- to_return(:status => 200, :body => '{"features":{"ilm":{"available":true,"enabled":true}}}', :headers => {"Content-Type"=> "application/json"})
2089
- stub_request(:get, "https://logs.google.com:777/es//_ilm/policy/fluentd-policy").
2090
- with(basic_auth: ['john', 'doe']).
2091
- to_return(:status => 404, :body => "", :headers => {})
2092
- stub_request(:put, "https://logs.google.com:777/es//_ilm/policy/fluentd-policy").
2093
- with(basic_auth: ['john', 'doe'],
2094
- :body => "{\"policy\":{\"phases\":{\"hot\":{\"actions\":{\"rollover\":{\"max_size\":\"50gb\",\"max_age\":\"30d\"}}}}}}").
2095
- to_return(:status => 200, :body => "", :headers => {})
2096
-
2097
- driver(config)
2098
-
2099
- assert_requested(:put, "https://logs.google.com:777/es//_template/myapp_deflector", times: 1)
2171
+ # Should raise error because multiple alias indices IllegalArgument Error on executing ILM feature
2172
+ assert_raise(Fluent::ConfigError) do
2173
+ driver(config)
2174
+ end
2100
2175
  end
2101
2176
 
2102
2177
  def test_custom_template_with_rollover_index_create_and_default_ilm_and_placeholders
@@ -2584,7 +2659,7 @@ class ElasticsearchOutputTest < Test::Unit::TestCase
2584
2659
  assert_requested(:put, "https://logs.google.com:777/es//_template/logstash3", times: 1)
2585
2660
  end
2586
2661
 
2587
- def test_templates_not_used
2662
+ def test_templates_are_also_used
2588
2663
  cwd = File.dirname(__FILE__)
2589
2664
  template_file = File.join(cwd, 'test_template.json')
2590
2665
 
@@ -2628,8 +2703,8 @@ class ElasticsearchOutputTest < Test::Unit::TestCase
2628
2703
 
2629
2704
  assert_requested(:put, "https://logs.google.com:777/es//_template/logstash", times: 1)
2630
2705
 
2631
- assert_not_requested(:put, "https://logs.google.com:777/es//_template/logstash1")
2632
- assert_not_requested(:put, "https://logs.google.com:777/es//_template/logstash2")
2706
+ assert_requested(:put, "https://logs.google.com:777/es//_template/logstash1")
2707
+ assert_requested(:put, "https://logs.google.com:777/es//_template/logstash2")
2633
2708
  end
2634
2709
 
2635
2710
  def test_templates_can_be_partially_created_if_error_occurs
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-elasticsearch
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.10
4
+ version: 4.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - diogo
8
8
  - pitr
9
9
  - Hiroshi Hatake
10
- autorequire:
10
+ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2020-07-06 00:00:00.000000000 Z
13
+ date: 2020-09-08 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: fluentd
@@ -160,6 +160,7 @@ files:
160
160
  - lib/fluent/plugin/elasticsearch_constants.rb
161
161
  - lib/fluent/plugin/elasticsearch_error.rb
162
162
  - lib/fluent/plugin/elasticsearch_error_handler.rb
163
+ - lib/fluent/plugin/elasticsearch_fallback_selector.rb
163
164
  - lib/fluent/plugin/elasticsearch_index_lifecycle_management.rb
164
165
  - lib/fluent/plugin/elasticsearch_index_template.rb
165
166
  - lib/fluent/plugin/elasticsearch_simple_sniffer.rb
@@ -172,6 +173,7 @@ files:
172
173
  - test/helper.rb
173
174
  - test/plugin/test_alias_template.json
174
175
  - test/plugin/test_elasticsearch_error_handler.rb
176
+ - test/plugin/test_elasticsearch_fallback_selector.rb
175
177
  - test/plugin/test_elasticsearch_index_lifecycle_management.rb
176
178
  - test/plugin/test_elasticsearch_tls.rb
177
179
  - test/plugin/test_filter_elasticsearch_genid.rb
@@ -186,7 +188,7 @@ licenses:
186
188
  - Apache-2.0
187
189
  metadata:
188
190
  changelog_uri: https://github.com/uken/fluent-plugin-elasticsearch/blob/master/History.md
189
- post_install_message:
191
+ post_install_message:
190
192
  rdoc_options: []
191
193
  require_paths:
192
194
  - lib
@@ -202,13 +204,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
202
204
  version: '0'
203
205
  requirements: []
204
206
  rubygems_version: 3.1.2
205
- signing_key:
207
+ signing_key:
206
208
  specification_version: 4
207
209
  summary: Elasticsearch output plugin for Fluent event collector
208
210
  test_files:
209
211
  - test/helper.rb
210
212
  - test/plugin/test_alias_template.json
211
213
  - test/plugin/test_elasticsearch_error_handler.rb
214
+ - test/plugin/test_elasticsearch_fallback_selector.rb
212
215
  - test/plugin/test_elasticsearch_index_lifecycle_management.rb
213
216
  - test/plugin/test_elasticsearch_tls.rb
214
217
  - test/plugin/test_filter_elasticsearch_genid.rb