logstash-output-elasticsearch 11.12.2-java → 11.12.4-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/docs/index.asciidoc +1 -1
- data/lib/logstash/outputs/elasticsearch/data_stream_support.rb +62 -47
- data/lib/logstash/outputs/elasticsearch.rb +16 -1
- data/logstash-output-elasticsearch.gemspec +1 -1
- data/spec/unit/outputs/elasticsearch/data_stream_support_spec.rb +38 -4
- data/spec/unit/outputs/elasticsearch_spec.rb +22 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a912267d383b51082d4c1b68e21d83dcb506433abc4f3f12bce0465eef84f439
|
4
|
+
data.tar.gz: dc69623c94ad47986ed07f25818eeabfbfdd49532dfd9970f8c638dfe950f615
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 99568149dc8d313460046ca2e247c43e2e505e6649441a22a365e0d5484ba493d5d91c4eedfb5700fc447f64122555db3b92d6b59513a6b42e07dcc43dda3ada
|
7
|
+
data.tar.gz: 56d2ce9c942f2dffbfc850f8feec0368dc2456ee08f7d7f46b83de94f9439fdd9047a1bae9231cc41caf45105a1abda0d1e60429a37059709f337e5ea8f8b6e4
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
## 11.12.4
|
2
|
+
- Changed the `manage_template` default value to `false` when data streams is enabled [#1111](https://github.com/logstash-plugins/logstash-output-elasticsearch/pull/1111)
|
3
|
+
- Added the `manage_template => false` as a valid data stream option
|
4
|
+
|
5
|
+
## 11.12.3
|
6
|
+
- Changed the log messages for data stream checks [#1109](https://github.com/logstash-plugins/logstash-output-elasticsearch/pull/1109)
|
7
|
+
- Added more details about incompatible data streams supplied configurations
|
8
|
+
- Changed the data stream auto-configuration log levels from `debug` to `info`
|
9
|
+
|
1
10
|
## 11.12.2
|
2
11
|
- [Doc] Fixes the broken apache http client link [#1101](https://github.com/logstash-plugins/logstash-output-elasticsearch/pull/1101)
|
3
12
|
|
data/docs/index.asciidoc
CHANGED
@@ -790,7 +790,7 @@ Set the keystore password
|
|
790
790
|
===== `manage_template`
|
791
791
|
|
792
792
|
* Value type is <<boolean,boolean>>
|
793
|
-
* Default value is `true`
|
793
|
+
* Default value is `true` for non-time series data, and `false` for data streams.
|
794
794
|
|
795
795
|
From Logstash 1.3 onwards, a template is applied to Elasticsearch during
|
796
796
|
Logstash's startup if one with the name <<plugins-{type}s-{plugin}-template_name>>
|
@@ -28,7 +28,6 @@ module LogStash module Outputs class ElasticSearch
|
|
28
28
|
base.extend(Validator)
|
29
29
|
end
|
30
30
|
|
31
|
-
# @note assumes to be running AFTER {after_successful_connection} completed, due ES version checks
|
32
31
|
def data_stream_config?
|
33
32
|
@data_stream_config.nil? ? @data_stream_config = check_data_stream_config! : @data_stream_config
|
34
33
|
end
|
@@ -45,53 +44,64 @@ module LogStash module Outputs class ElasticSearch
|
|
45
44
|
"#{type}-#{dataset}-#{namespace}"
|
46
45
|
end
|
47
46
|
|
48
|
-
|
47
|
+
DATA_STREAMS_AND_ECS_ENABLED_BY_DEFAULT_LS_VERSION = '8.0.0'
|
49
48
|
|
50
49
|
# @param params the user configuration for the ES output
|
51
50
|
# @note LS initialized configuration (with filled defaults) won't detect as data-stream
|
52
51
|
# compatible, only explicit (`original_params`) config should be tested.
|
53
|
-
# @return [
|
52
|
+
# @return [Boolean] whether given configuration is data-stream compatible
|
54
53
|
def check_data_stream_config!(params = original_params)
|
55
|
-
data_stream_params = params.select { |name, _| name.start_with?('data_stream_') } # exclude data_stream =>
|
56
|
-
invalid_data_stream_params = invalid_data_stream_params(params)
|
57
|
-
|
58
54
|
case data_stream_explicit_value
|
59
55
|
when false
|
60
|
-
|
61
|
-
@logger.error "Ambiguous configuration; data stream settings must not be present when data streams is disabled (caused by: `data_stream => false`)", data_stream_params
|
62
|
-
raise LogStash::ConfigurationError, "Ambiguous configuration, please remove data stream specific settings: #{data_stream_params.keys}"
|
63
|
-
end
|
56
|
+
check_disabled_data_stream_config!(params)
|
64
57
|
return false
|
65
58
|
when true
|
66
|
-
|
67
|
-
@logger.error "Invalid data stream configuration, following parameters are not supported:", invalid_data_stream_params
|
68
|
-
raise LogStash::ConfigurationError, "Invalid data stream configuration: #{invalid_data_stream_params.keys}"
|
69
|
-
end
|
70
|
-
if ecs_compatibility == :disabled
|
71
|
-
if ::Gem::Version.create(LOGSTASH_VERSION) < ::Gem::Version.create(DATA_STREAMS_REQUIRES_ECS_LS_VERSION)
|
72
|
-
@deprecation_logger.deprecated "In a future release of Logstash, the Elasticsearch output plugin's `data_stream => true` will require the plugin to be run in ECS compatibility mode. " + ENABLING_ECS_GUIDANCE
|
73
|
-
else
|
74
|
-
@logger.error "Invalid data stream configuration; `ecs_compatibility` must not be `disabled`. " + ENABLING_ECS_GUIDANCE
|
75
|
-
raise LogStash::ConfigurationError, "Invalid data stream configuration: `ecs_compatibility => disabled`"
|
76
|
-
end
|
77
|
-
end
|
59
|
+
check_enabled_data_stream_config!(params)
|
78
60
|
return true
|
79
|
-
else
|
80
|
-
use_data_stream = data_stream_default(
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
61
|
+
else # data_stream => auto or not set
|
62
|
+
use_data_stream = data_stream_default(params)
|
63
|
+
|
64
|
+
check_disabled_data_stream_config!(params) unless use_data_stream
|
65
|
+
|
66
|
+
@logger.info("Data streams auto configuration (`data_stream => auto` or unset) resolved to `#{use_data_stream}`")
|
67
|
+
return use_data_stream
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def check_enabled_data_stream_config!(params)
|
72
|
+
invalid_data_stream_params = invalid_data_stream_params(params)
|
73
|
+
|
74
|
+
if invalid_data_stream_params.any?
|
75
|
+
@logger.error "Invalid data stream configuration, the following parameters are not supported:", invalid_data_stream_params
|
76
|
+
raise LogStash::ConfigurationError, "Invalid data stream configuration: #{invalid_data_stream_params.keys}"
|
77
|
+
end
|
78
|
+
|
79
|
+
if ecs_compatibility == :disabled
|
80
|
+
if ecs_compatibility_required?
|
81
|
+
@logger.error "Invalid data stream configuration; `ecs_compatibility` must not be `disabled`. " + ENABLING_ECS_GUIDANCE
|
82
|
+
raise LogStash::ConfigurationError, "Invalid data stream configuration: `ecs_compatibility => disabled`"
|
90
83
|
end
|
91
|
-
|
84
|
+
|
85
|
+
@deprecation_logger.deprecated "In a future release of Logstash, the Elasticsearch output plugin's `data_stream => true` will require the plugin to be run in ECS compatibility mode. " + ENABLING_ECS_GUIDANCE
|
92
86
|
end
|
93
87
|
end
|
94
88
|
|
89
|
+
def check_disabled_data_stream_config!(params)
|
90
|
+
data_stream_params = data_stream_params(params)
|
91
|
+
|
92
|
+
if data_stream_params.any?
|
93
|
+
@logger.error "Ambiguous configuration; data stream settings must not be present when data streams are disabled (caused by `data_stream => false`, `data_stream => auto` or unset resolved to false). " \
|
94
|
+
"You can either manually set `data_stream => true` or remove the following specific data stream settings: ", data_stream_params
|
95
|
+
|
96
|
+
raise LogStash::ConfigurationError,
|
97
|
+
"Ambiguous configuration; data stream settings must not be present when data streams are disabled: #{data_stream_params.keys}"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def data_stream_params(params)
|
102
|
+
params.select { |name, _| name.start_with?('data_stream_') }
|
103
|
+
end
|
104
|
+
|
95
105
|
def data_stream_explicit_value
|
96
106
|
case @data_stream
|
97
107
|
when 'true'
|
@@ -108,7 +118,6 @@ module LogStash module Outputs class ElasticSearch
|
|
108
118
|
params.reject do |name, value|
|
109
119
|
# NOTE: intentionally do not support explicit DS configuration like:
|
110
120
|
# - `index => ...` identifier provided by data_stream_xxx settings
|
111
|
-
# - `manage_template => false` implied by not setting the parameter
|
112
121
|
case name
|
113
122
|
when 'action'
|
114
123
|
value == 'create'
|
@@ -116,6 +125,8 @@ module LogStash module Outputs class ElasticSearch
|
|
116
125
|
true
|
117
126
|
when 'data_stream'
|
118
127
|
value.to_s == 'true'
|
128
|
+
when 'manage_template'
|
129
|
+
value.to_s == 'false'
|
119
130
|
when 'ecs_compatibility' then true # required for LS <= 6.x
|
120
131
|
else
|
121
132
|
name.start_with?('data_stream_') ||
|
@@ -131,6 +142,7 @@ module LogStash module Outputs class ElasticSearch
|
|
131
142
|
|
132
143
|
DATA_STREAMS_ORIGIN_ES_VERSION = '7.9.0'
|
133
144
|
|
145
|
+
# @note assumes to be running AFTER {after_successful_connection} completed, due ES version checks
|
134
146
|
# @return [Gem::Version] if ES supports DS nil (or raise) otherwise
|
135
147
|
def assert_es_version_supports_data_streams
|
136
148
|
fail 'no last_es_version' unless last_es_version # assert - should not happen
|
@@ -144,31 +156,26 @@ module LogStash module Outputs class ElasticSearch
|
|
144
156
|
es_version # return truthy
|
145
157
|
end
|
146
158
|
|
147
|
-
DATA_STREAMS_ENABLED_BY_DEFAULT_LS_VERSION = '8.0.0'
|
148
|
-
|
149
159
|
# when data_stream => is either 'auto' or not set
|
150
|
-
|
151
|
-
# @param invalid_data_stream_config [#any?#inspect]
|
152
|
-
def data_stream_default(data_stream_params, invalid_data_stream_config)
|
160
|
+
def data_stream_default(params)
|
153
161
|
if ecs_compatibility == :disabled
|
154
|
-
@logger.
|
162
|
+
@logger.info("Not eligible for data streams because ecs_compatibility is not enabled. " + ENABLING_ECS_GUIDANCE)
|
155
163
|
return false
|
156
164
|
end
|
157
165
|
|
158
|
-
|
166
|
+
invalid_data_stream_params = invalid_data_stream_params(params)
|
159
167
|
|
160
|
-
if
|
161
|
-
if
|
162
|
-
@logger.
|
168
|
+
if data_stream_and_ecs_enabled_by_default?
|
169
|
+
if invalid_data_stream_params.any?
|
170
|
+
@logger.info("Not eligible for data streams because config contains one or more settings that are not compatible with data streams: #{invalid_data_stream_params.inspect}")
|
163
171
|
return false
|
164
172
|
end
|
165
173
|
|
166
|
-
@logger.debug 'Configuration is data stream compliant'
|
167
174
|
return true
|
168
175
|
end
|
169
176
|
|
170
177
|
# LS 7.x
|
171
|
-
if !
|
178
|
+
if !invalid_data_stream_params.any? && !data_stream_params(params).any?
|
172
179
|
@logger.warn "Configuration is data stream compliant but due backwards compatibility Logstash 7.x will not assume " +
|
173
180
|
"writing to a data-stream, default behavior will change on Logstash 8.0 " +
|
174
181
|
"(set `data_stream => true/false` to disable this warning)"
|
@@ -176,6 +183,14 @@ module LogStash module Outputs class ElasticSearch
|
|
176
183
|
false
|
177
184
|
end
|
178
185
|
|
186
|
+
def ecs_compatibility_required?
|
187
|
+
data_stream_and_ecs_enabled_by_default?
|
188
|
+
end
|
189
|
+
|
190
|
+
def data_stream_and_ecs_enabled_by_default?
|
191
|
+
::Gem::Version.create(LOGSTASH_VERSION) >= ::Gem::Version.create(DATA_STREAMS_AND_ECS_ENABLED_BY_DEFAULT_LS_VERSION)
|
192
|
+
end
|
193
|
+
|
179
194
|
# an {event_action_tuple} replacement when a data-stream configuration is detected
|
180
195
|
def data_stream_event_action_tuple(event)
|
181
196
|
event_data = event.to_hash
|
@@ -158,6 +158,8 @@ class LogStash::Outputs::ElasticSearch < LogStash::Outputs::Base
|
|
158
158
|
# control over template creation, (e.g. creating indices dynamically based on
|
159
159
|
# field names) you should set `manage_template` to false and use the REST
|
160
160
|
# API to apply your templates manually.
|
161
|
+
#
|
162
|
+
# Default value is `true` unless data streams is enabled
|
161
163
|
config :manage_template, :validate => :boolean, :default => true
|
162
164
|
|
163
165
|
# This configuration option defines how the template is named inside Elasticsearch.
|
@@ -300,6 +302,12 @@ class LogStash::Outputs::ElasticSearch < LogStash::Outputs::Base
|
|
300
302
|
# to build_client down to the Pool class.
|
301
303
|
@client = build_client(LicenseChecker.new(@logger))
|
302
304
|
|
305
|
+
# Avoids race conditions in the @data_stream_config initialization (invoking check_data_stream_config! twice).
|
306
|
+
# It's being concurrently invoked by this register method and by the finish_register on the @after_successful_connection_thread
|
307
|
+
data_stream_enabled = data_stream_config?
|
308
|
+
|
309
|
+
setup_template_manager_defaults(data_stream_enabled)
|
310
|
+
|
303
311
|
@after_successful_connection_thread = after_successful_connection do
|
304
312
|
begin
|
305
313
|
finish_register
|
@@ -324,7 +332,7 @@ class LogStash::Outputs::ElasticSearch < LogStash::Outputs::Base
|
|
324
332
|
raise LogStash::ConfigurationError, "DLQ feature (dlq_custom_codes) is configured while DLQ is not enabled" unless dlq_custom_codes.empty?
|
325
333
|
end
|
326
334
|
|
327
|
-
if
|
335
|
+
if data_stream_enabled
|
328
336
|
@event_mapper = -> (e) { data_stream_event_action_tuple(e) }
|
329
337
|
@event_target = -> (e) { data_stream_name(e) }
|
330
338
|
@index = "#{data_stream_type}-#{data_stream_dataset}-#{data_stream_namespace}".freeze # default name
|
@@ -604,6 +612,13 @@ class LogStash::Outputs::ElasticSearch < LogStash::Outputs::Base
|
|
604
612
|
@template_name ||= default_template_name
|
605
613
|
end
|
606
614
|
|
615
|
+
def setup_template_manager_defaults(data_stream_enabled)
|
616
|
+
if original_params["manage_template"].nil? && data_stream_enabled
|
617
|
+
logger.debug("Disabling template management since data streams are enabled")
|
618
|
+
@manage_template = false
|
619
|
+
end
|
620
|
+
end
|
621
|
+
|
607
622
|
# To be overidden by the -java version
|
608
623
|
VALID_HTTP_ACTIONS = ["index", "delete", "create", "update"]
|
609
624
|
def valid_actions
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'logstash-output-elasticsearch'
|
3
|
-
s.version = '11.12.
|
3
|
+
s.version = '11.12.4'
|
4
4
|
s.licenses = ['apache-2.0']
|
5
5
|
s.summary = "Stores logs in Elasticsearch"
|
6
6
|
s.description = "This gem is a Logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This gem is not a stand-alone program"
|
@@ -84,7 +84,8 @@ describe LogStash::Outputs::ElasticSearch::DataStreamSupport do
|
|
84
84
|
context "on LS #{ls_version_desc}" do
|
85
85
|
around(:each) { |example| change_constant(:LOGSTASH_VERSION, ls_version, &example) }
|
86
86
|
it "does not use data-streams" do
|
87
|
-
expect( subject.logger ).to receive(:
|
87
|
+
expect( subject.logger ).to receive(:info).with(a_string_including "ecs_compatibility is not enabled")
|
88
|
+
expect( subject.logger ).to receive(:info).with(a_string_including "Data streams auto configuration (`data_stream => auto` or unset) resolved to `false`")
|
88
89
|
expect( subject.data_stream_config? ).to be false
|
89
90
|
end
|
90
91
|
end
|
@@ -151,6 +152,39 @@ describe LogStash::Outputs::ElasticSearch::DataStreamSupport do
|
|
151
152
|
|
152
153
|
end
|
153
154
|
|
155
|
+
context 'ds value-dependent configuration' do
|
156
|
+
context 'with valid values' do
|
157
|
+
let(:options) { super().merge(
|
158
|
+
'action' => 'create',
|
159
|
+
'routing' => 'any',
|
160
|
+
'pipeline' => 'any',
|
161
|
+
'manage_template' => 'false',
|
162
|
+
'data_stream' => 'true',
|
163
|
+
'data_stream_type' => 'logs',
|
164
|
+
'data_stream_dataset' => 'any',
|
165
|
+
'data_stream_namespace' => 'any',
|
166
|
+
'data_stream_sync_fields' => true,
|
167
|
+
'data_stream_auto_routing' => true)
|
168
|
+
}
|
169
|
+
|
170
|
+
it 'should enable data-streams by default' do
|
171
|
+
expect( subject.data_stream_config? ).to be_truthy
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
context 'with invalid values' do
|
176
|
+
let(:options) { super().merge(
|
177
|
+
'data_stream' => 'true',
|
178
|
+
'action' => 'index',
|
179
|
+
'manage_template' => 'true')
|
180
|
+
}
|
181
|
+
|
182
|
+
it 'should raise a configuration error' do
|
183
|
+
expect { subject.data_stream_config? }.to raise_error(LogStash::ConfigurationError, 'Invalid data stream configuration: ["action", "manage_template"]')
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
154
188
|
context "default (non data-stream) configuration (on 7.x)" do
|
155
189
|
|
156
190
|
let(:options) do
|
@@ -161,7 +195,7 @@ describe LogStash::Outputs::ElasticSearch::DataStreamSupport do
|
|
161
195
|
|
162
196
|
it "does not default to data-streams" do
|
163
197
|
expect( subject.logger ).to receive(:error) do |msg|
|
164
|
-
expect(msg).to include "Ambiguous configuration; data stream settings
|
198
|
+
expect(msg).to include "Ambiguous configuration; data stream settings must not be present when data streams are disabled"
|
165
199
|
end
|
166
200
|
change_constant :LOGSTASH_VERSION, '7.10.2' do
|
167
201
|
expect { subject.data_stream_config? }.to raise_error(LogStash::ConfigurationError, /Ambiguous configuration/i)
|
@@ -173,8 +207,8 @@ describe LogStash::Outputs::ElasticSearch::DataStreamSupport do
|
|
173
207
|
let(:options) { super().merge('data_stream' => 'false') }
|
174
208
|
|
175
209
|
it "raises a configuration error (due ds specific settings)" do
|
176
|
-
expect( subject.logger ).to receive(:error).with(/Ambiguous configuration; data stream settings must not be present when data streams
|
177
|
-
|
210
|
+
expect( subject.logger ).to receive(:error).with(/Ambiguous configuration; data stream settings must not be present when data streams are disabled/,
|
211
|
+
{"data_stream_auto_routing"=>"false", "data_stream_dataset"=>"test"})
|
178
212
|
change_constant :LOGSTASH_VERSION, '7.10.2' do
|
179
213
|
expect { subject.data_stream_config? }.to raise_error(LogStash::ConfigurationError, /Ambiguous configuration/i)
|
180
214
|
end
|
@@ -606,6 +606,26 @@ describe LogStash::Outputs::ElasticSearch do
|
|
606
606
|
end
|
607
607
|
end
|
608
608
|
|
609
|
+
describe "the manage_template option" do
|
610
|
+
context "with data stream enabled" do
|
611
|
+
let(:options) { {"data_stream" => "true", "data_stream_type" => "logs" } }
|
612
|
+
let(:do_register) { true }
|
613
|
+
|
614
|
+
it "should default to false" do
|
615
|
+
expect(subject).to have_attributes(manage_template: false)
|
616
|
+
end
|
617
|
+
end
|
618
|
+
|
619
|
+
context "with data stream disabled" do
|
620
|
+
let(:options) { {"data_stream" => "false", "index" => "logs" } }
|
621
|
+
let(:do_register) { true }
|
622
|
+
|
623
|
+
it "should default to true" do
|
624
|
+
expect(subject).to have_attributes(manage_template: true)
|
625
|
+
end
|
626
|
+
end
|
627
|
+
end
|
628
|
+
|
609
629
|
describe "SSL end to end" do
|
610
630
|
let(:do_register) { false } # skip the register in the global before block, as is called here.
|
611
631
|
|
@@ -870,7 +890,7 @@ describe LogStash::Outputs::ElasticSearch do
|
|
870
890
|
end if LOGSTASH_VERSION > '6.0'
|
871
891
|
|
872
892
|
context 'handling elasticsearch document-level status meant for the DLQ' do
|
873
|
-
let(:options) { { "manage_template" => false } }
|
893
|
+
let(:options) { { "manage_template" => false, "data_stream" => 'false' } }
|
874
894
|
let(:action) { LogStash::Outputs::ElasticSearch::EventActionTuple.new(:action, :params, LogStash::Event.new("foo" => "bar")) }
|
875
895
|
|
876
896
|
context 'when @dlq_writer is nil' do
|
@@ -1140,7 +1160,7 @@ describe LogStash::Outputs::ElasticSearch do
|
|
1140
1160
|
describe "post-register ES setup" do
|
1141
1161
|
let(:do_register) { false }
|
1142
1162
|
let(:es_version) { '7.10.0' } # DS default on LS 8.x
|
1143
|
-
let(:options) { { 'hosts' => '127.0.0.1:9999' } }
|
1163
|
+
let(:options) { { 'hosts' => '127.0.0.1:9999', 'data_stream' => 'false' } }
|
1144
1164
|
let(:logger) { subject.logger }
|
1145
1165
|
|
1146
1166
|
before do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logstash-output-elasticsearch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 11.12.
|
4
|
+
version: 11.12.4
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- Elastic
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-01
|
11
|
+
date: 2023-02-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|