fluent-plugin-s3 1.7.1 → 1.8.0

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: fe9afa0a2351dfffc6ea9afa0c2f3598a29b19a55fbfa22f58f3d17b606a3113
4
- data.tar.gz: e5813910a178d16ed61c2a8782e2adeb394d0d256acfbcfdbead05069d789163
3
+ metadata.gz: 8c72b8fcce805d79141dededa99e19fe802a27b169f4f39b6f842dfc2829daab
4
+ data.tar.gz: eb62e090ec39010bf6f2598c827d875ae0032dccc14b71607dcd92fa80082d0e
5
5
  SHA512:
6
- metadata.gz: e3ca35df25975b7b57244c88d3145ab8fb5521054b863e030846a867bae6cbc9a69343f586f01b3a29d233eea787cf0ab540ff77edc0423d583394e29a192a7c
7
- data.tar.gz: d46deabb1425e03250c9bc24578ad8dacef71cc445335ac9e4122b11c6ad91cf7a73f92b63d3688848ff35d427cb6371777f0011c94c45a898a6063edc1e3d9c
6
+ metadata.gz: 53e0911c336861aa4dddb73e9f0f5f58fa78d8d8434a217e55f2532fbb264c7ec7e894cc9f1cfd1abc0452f065954099658420bf435dd5bfe7a8a402ecab0e25
7
+ data.tar.gz: 3916876756d629413c80a6a24f428ff6a453e284a235d0805853b4b01b7bfb6f7866426342c5a598d00a53fe3ee2daf46ac90f4ba04577f762bc3fbabfef1e7f
@@ -1,5 +1,6 @@
1
1
  name: Bug Report
2
2
  description: Create a report with a procedure for reproducing the bug
3
+ labels: "waiting-for-triage"
3
4
  body:
4
5
  - type: markdown
5
6
  attributes:
@@ -1,5 +1,6 @@
1
1
  name: Feature request
2
2
  description: Suggest an idea for this project
3
+ labels: "waiting-for-triage"
3
4
  body:
4
5
  - type: markdown
5
6
  attributes:
@@ -0,0 +1,6 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: 'github-actions'
4
+ directory: '/'
5
+ schedule:
6
+ interval: 'monthly'
@@ -10,12 +10,12 @@ jobs:
10
10
  strategy:
11
11
  fail-fast: false
12
12
  matrix:
13
- ruby: [ '3.1', '3.0', '2.7' ]
13
+ ruby: [ '3.2', '3.1', '3.0', '2.7' ]
14
14
  os:
15
15
  - ubuntu-latest
16
16
  name: Ruby ${{ matrix.ruby }} unit testing on ${{ matrix.os }}
17
17
  steps:
18
- - uses: actions/checkout@v2
18
+ - uses: actions/checkout@v4
19
19
  - uses: ruby/setup-ruby@v1
20
20
  with:
21
21
  ruby-version: ${{ matrix.ruby }}
@@ -23,6 +23,6 @@ jobs:
23
23
  env:
24
24
  CI: true
25
25
  run: |
26
- gem install bundler rake
26
+ gem install rake
27
27
  bundle install --jobs 4 --retry 3
28
28
  bundle exec rake test
@@ -7,16 +7,18 @@ jobs:
7
7
  stale:
8
8
  runs-on: ubuntu-latest
9
9
  steps:
10
- - uses: actions/stale@v3
10
+ - uses: actions/stale@v8
11
11
  with:
12
12
  repo-token: ${{ secrets.GITHUB_TOKEN }}
13
- days-before-stale: 90
14
- days-before-close: 30
15
- stale-issue-message: "This issue has been automatically marked as stale because it has been open 90 days with no activity. Remove stale label or comment or this issue will be closed in 30 days"
16
- stale-pr-message: "This PR has been automatically marked as stale because it has been open 90 days with no activity. Remove stale label or comment or this PR will be closed in 30 days"
17
- close-issue-message: "This issue was automatically closed because of stale in 30 days"
18
- close-pr-message: "This PR was automatically closed because of stale in 30 days"
13
+ days-before-stale: 30
14
+ days-before-close: 7
15
+ stale-issue-message: "This issue has been automatically marked as stale because it has been open 30 days with no activity. Remove stale label or comment or this issue will be closed in 7 days"
16
+ stale-pr-message: "This PR has been automatically marked as stale because it has been open 30 days with no activity. Remove stale label or comment or this PR will be closed in 7 days"
17
+ close-issue-message: "This issue was automatically closed because of stale in 7 days"
18
+ close-pr-message: "This PR was automatically closed because of stale in 7 days"
19
19
  stale-pr-label: "stale"
20
20
  stale-issue-label: "stale"
21
- exempt-issue-labels: "bug,help wanted,enhancement"
22
- exempt-pr-labels: "bug,help wanted,enhancement"
21
+ exempt-issue-labels: "waiting-for-triage,bug,help wanted,enhancement"
22
+ exempt-pr-labels: "waiting-for-triage,bug,help wanted,enhancement"
23
+ exempt-all-assignees: true
24
+ exempt-all-milestones: true
data/ChangeLog CHANGED
@@ -1,3 +1,12 @@
1
+ Release 1.8.0 - 2024/11/06
2
+
3
+ * out_s3: Add zstd compression support
4
+
5
+ Release 1.7.2 - 2022/10/19
6
+
7
+ * in_s3: Add `event_bridge_mode` parameter
8
+ * out_s3: Fix `s3_object_key_format` check to allow `%{hex_random}` as well as `%{uuid_flush}` or `${chunk_id}`
9
+
1
10
  Release 1.7.1 - 2022/07/15
2
11
 
3
12
  * in_s3: Add `match_regexp` parameter to selectively download S3 files based on the object key
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.7.1
1
+ 1.8.0
data/docs/credentials.md CHANGED
@@ -126,7 +126,7 @@ See also:
126
126
 
127
127
  ### retries
128
128
 
129
- Number of times to retry when retrieving credentials. Default is 5.
129
+ Number of times to retry when retrieving credentials. Default is nil.
130
130
 
131
131
  ### ip_address
132
132
 
data/docs/howto.md CHANGED
@@ -7,7 +7,7 @@ downstream processors to better identify the source of a given record.
7
7
 
8
8
  # IAM Policy
9
9
 
10
- The following is an example for a IAM policy needed to write to an s3 bucket (matches my-s3bucket/logs, my-s3bucket-test, etc.).
10
+ The following is an example for a IAM policy needed to write to an s3 bucket (matches my-s3bucket/logs, my-s3bucket/test, etc.).
11
11
 
12
12
  {
13
13
  "Version": "2012-10-17",
data/docs/input.md CHANGED
@@ -101,3 +101,7 @@ The long polling interval. Default is 20.
101
101
  ### retry_error_interval
102
102
 
103
103
  Interval to retry polling SQS if polling unsuccessful, in seconds. Default is 300.
104
+
105
+ ### event_bridge_mode
106
+ When true, Amazon S3 Event Notification should be configured using the EventBridge integration. Default is false.
107
+ See [Configure S3 event notification using EventBridge](https://docs.aws.amazon.com/AmazonS3/latest/userguide/EventBridge.html) for additional information.
@@ -19,6 +19,7 @@ Gem::Specification.new do |gem|
19
19
  gem.add_dependency "fluentd", [">= 0.14.22", "< 2"]
20
20
  gem.add_dependency "aws-sdk-s3", "~> 1.60"
21
21
  gem.add_dependency "aws-sdk-sqs", "~> 1.23"
22
+ gem.add_dependency 'zstd-ruby'
22
23
  gem.add_development_dependency "rake", ">= 0.9.2"
23
24
  gem.add_development_dependency "test-unit", ">= 3.0.8"
24
25
  gem.add_development_dependency "test-unit-rr", ">= 1.0.3"
@@ -110,6 +110,8 @@ module Fluent::Plugin
110
110
  config_param :wait_time_seconds, :integer, default: 20
111
111
  desc "Polling error retry interval."
112
112
  config_param :retry_error_interval, :integer, default: 300
113
+ desc "Event bridge mode"
114
+ config_param :event_bridge_mode, :bool, default: false
113
115
  end
114
116
 
115
117
  desc "Tag string"
@@ -205,10 +207,9 @@ module Fluent::Plugin
205
207
  begin
206
208
  body = Yajl.load(message.body)
207
209
  log.debug(body)
208
- next unless body["Records"] # skip test queue
210
+ next unless is_valid_queue(body) # skip test queue
209
211
  if @match_regexp
210
- s3 = body["Records"].first["s3"]
211
- raw_key = s3["object"]["key"]
212
+ raw_key = get_raw_key(body)
212
213
  key = CGI.unescape(raw_key)
213
214
  next unless @match_regexp.match?(key)
214
215
  end
@@ -226,6 +227,24 @@ module Fluent::Plugin
226
227
  end
227
228
  end
228
229
 
230
+ def is_valid_queue(body)
231
+ if @sqs.event_bridge_mode
232
+ log.debug("checking for eventbridge property")
233
+ !!body["detail"]
234
+ else
235
+ log.debug("checking for Records property")
236
+ !!body["Records"]
237
+ end
238
+ end
239
+
240
+ def get_raw_key(body)
241
+ if @sqs.event_bridge_mode
242
+ body["detail"]["object"]["key"]
243
+ else
244
+ body["Records"].first["s3"]["object"]["key"]
245
+ end
246
+ end
247
+
229
248
  def setup_credentials
230
249
  options = {}
231
250
  credentials_options = {}
@@ -318,8 +337,7 @@ module Fluent::Plugin
318
337
  end
319
338
 
320
339
  def process(body)
321
- s3 = body["Records"].first["s3"]
322
- raw_key = s3["object"]["key"]
340
+ raw_key = get_raw_key(body)
323
341
  key = CGI.unescape(raw_key)
324
342
 
325
343
  io = @bucket.object(key).get.body
@@ -471,8 +471,8 @@ module Fluent::Plugin
471
471
  end
472
472
 
473
473
  is_working_on_parallel = @buffer_config.flush_thread_count > 1 || system_config.workers > 1
474
- if is_working_on_parallel && ['${chunk_id}', '%{uuid_flush}'].none? { |key| @s3_object_key_format.include?(key) }
475
- log.warn "No ${chunk_id} or %{uuid_flush} in s3_object_key_format with multiple flush threads or multiple workers. Recommend to set ${chunk_id} or %{uuid_flush} to avoid data lost by object conflict"
474
+ if is_working_on_parallel && ['${chunk_id}', '%{uuid_flush}', '%{hex_random}'].none? { |key| @s3_object_key_format.include?(key) }
475
+ log.warn "No ${chunk_id}, %{uuid_flush} or %{hex_random} in s3_object_key_format with multiple flush threads or multiple workers. Recommend to set ${chunk_id}, %{uuid_flush} or %{hex_random} to avoid data lost by object conflict"
476
476
  end
477
477
  end
478
478
 
@@ -0,0 +1,30 @@
1
+ require 'zstd-ruby'
2
+
3
+ module Fluent::Plugin
4
+ class S3Output
5
+ class ZstdCompressor < Compressor
6
+ S3Output.register_compressor('zstd', self)
7
+
8
+ config_section :compress, param_name: :compress_config, init: true, multi: false do
9
+ desc "Compression level for zstd (1-22)"
10
+ config_param :level, :integer, default: 3
11
+ end
12
+
13
+ def ext
14
+ 'zst'.freeze
15
+ end
16
+
17
+ def content_type
18
+ 'application/x-zst'.freeze
19
+ end
20
+
21
+ def compress(chunk, tmp)
22
+ compressed = Zstd.compress(chunk.read, level: @compress_config.level)
23
+ tmp.write(compressed)
24
+ rescue => e
25
+ log.warn "zstd compression failed: #{e.message}"
26
+ raise
27
+ end
28
+ end
29
+ end
30
+ end
data/test/test_in_s3.rb CHANGED
@@ -166,9 +166,9 @@ buffer_type memory
166
166
  aws_key_id sqs_test_key_id
167
167
  </sqs>
168
168
  EOS
169
- create_driver(conf)
170
- }
171
- end
169
+ create_driver(conf)
170
+ }
171
+ end
172
172
 
173
173
  def test_sqs_with_invalid_aws_keys_missing_key_id
174
174
  assert_raise(Fluent::ConfigError, "sqs/aws_key_id or sqs/aws_sec_key is missing") {
@@ -677,4 +677,50 @@ EOS
677
677
  d.run {}
678
678
  end
679
679
  end
680
+
681
+ def test_event_bridge_mode
682
+ setup_mocks
683
+ d = create_driver("
684
+ aws_key_id test_key_id
685
+ aws_sec_key test_sec_key
686
+ s3_bucket test_bucket
687
+ buffer_type memory
688
+ check_apikey_on_start false
689
+ store_as text
690
+ format none
691
+ <sqs>
692
+ event_bridge_mode true
693
+ queue_name test_queue
694
+ queue_owner_aws_account_id 123456789123
695
+ </sqs>
696
+ ")
697
+
698
+ s3_object = stub(Object.new)
699
+ s3_response = stub(Object.new)
700
+ s3_response.body { StringIO.new("aaa") }
701
+ s3_object.get { s3_response }
702
+ @s3_bucket.object(anything).at_least(1) { s3_object }
703
+
704
+ body = {
705
+ "detail" => {
706
+ "object" => {
707
+ "key" => "test_key"
708
+ }
709
+ }
710
+ }
711
+
712
+ message = Struct::StubMessage.new(1, 1, Yajl.dump(body))
713
+ @sqs_poller.get_messages(anything, anything) do |config, stats|
714
+ config.before_request.call(stats) if config.before_request
715
+ stats.request_count += 1
716
+ if stats.request_count >= 1
717
+ d.instance.instance_variable_set(:@running, false)
718
+ end
719
+ [message]
720
+ end
721
+ d.run(expect_emits: 1)
722
+ events = d.events
723
+ assert_equal({ "message" => "aaa" }, events.first[2])
724
+ end
725
+
680
726
  end
data/test/test_out_s3.rb CHANGED
@@ -109,6 +109,18 @@ class S3OutputTest < Test::Unit::TestCase
109
109
  assert(e.is_a?(Fluent::ConfigError))
110
110
  end
111
111
 
112
+ data('level default' => nil,
113
+ 'level 1' => 1)
114
+ def test_configure_with_mime_type_zstd(level)
115
+ conf = CONFIG.clone
116
+ conf << "\nstore_as zstd\n"
117
+ conf << "\n<compress>\nlevel #{level}\n</compress>\n" if level
118
+ d = create_driver(conf)
119
+ assert_equal 'zst', d.instance.instance_variable_get(:@compressor).ext
120
+ assert_equal 'application/x-zst', d.instance.instance_variable_get(:@compressor).content_type
121
+ assert_equal (level || 3), d.instance.instance_variable_get(:@compressor).instance_variable_get(:@compress_config).level
122
+ end
123
+
112
124
  def test_configure_with_path_style
113
125
  conf = CONFIG.clone
114
126
  conf << "\nforce_path_style true\n"
@@ -456,6 +468,33 @@ EOC
456
468
  FileUtils.rm_f(s3_local_file_path)
457
469
  end
458
470
 
471
+ def test_write_with_zstd
472
+ setup_mocks(true)
473
+ s3_local_file_path = "/tmp/s3-test.zst"
474
+
475
+ expected_s3path = "log/events/ts=20110102-13/events_0-#{Socket.gethostname}.zst"
476
+
477
+ setup_s3_object_mocks(s3_local_file_path: s3_local_file_path, s3path: expected_s3path)
478
+
479
+ config = CONFIG_TIME_SLICE + "\nstore_as zstd\n"
480
+ d = create_time_sliced_driver(config)
481
+
482
+ time = event_time("2011-01-02 13:14:15 UTC")
483
+ d.run(default_tag: "test") do
484
+ d.feed(time, { "a" => 1 })
485
+ d.feed(time, { "a" => 2 })
486
+ end
487
+
488
+ File.open(s3_local_file_path, 'rb') do |file|
489
+ compressed_data = file.read
490
+ uncompressed_data = Zstd.decompress(compressed_data)
491
+ expected_data = %[2011-01-02T13:14:15Z\ttest\t{"a":1}\n] +
492
+ %[2011-01-02T13:14:15Z\ttest\t{"a":2}\n]
493
+ assert_equal expected_data, uncompressed_data
494
+ end
495
+ FileUtils.rm_f(s3_local_file_path)
496
+ end
497
+
459
498
  class MockResponse
460
499
  attr_reader :data
461
500
 
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-s3
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.1
4
+ version: 1.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sadayuki Furuhashi
8
8
  - Masahiro Nakagawa
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2022-07-15 00:00:00.000000000 Z
12
+ date: 2024-11-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: fluentd
@@ -59,6 +59,20 @@ dependencies:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
61
  version: '1.23'
62
+ - !ruby/object:Gem::Dependency
63
+ name: zstd-ruby
64
+ requirement: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ type: :runtime
70
+ prerelease: false
71
+ version_requirements: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
62
76
  - !ruby/object:Gem::Dependency
63
77
  name: rake
64
78
  requirement: !ruby/object:Gem::Requirement
@@ -138,6 +152,7 @@ files:
138
152
  - ".github/ISSUE_TEMPLATE/bug_report.yaml"
139
153
  - ".github/ISSUE_TEMPLATE/config.yml"
140
154
  - ".github/ISSUE_TEMPLATE/feature_request.yaml"
155
+ - ".github/dependabot.yml"
141
156
  - ".github/workflows/linux.yml"
142
157
  - ".github/workflows/stale-actions.yml"
143
158
  - ".gitignore"
@@ -162,6 +177,7 @@ files:
162
177
  - lib/fluent/plugin/s3_compressor_lzma2.rb
163
178
  - lib/fluent/plugin/s3_compressor_lzo.rb
164
179
  - lib/fluent/plugin/s3_compressor_parquet.rb
180
+ - lib/fluent/plugin/s3_compressor_zstd.rb
165
181
  - lib/fluent/plugin/s3_extractor_gzip_command.rb
166
182
  - lib/fluent/plugin/s3_extractor_lzma2.rb
167
183
  - lib/fluent/plugin/s3_extractor_lzo.rb
@@ -171,7 +187,7 @@ homepage: https://github.com/fluent/fluent-plugin-s3
171
187
  licenses:
172
188
  - Apache-2.0
173
189
  metadata: {}
174
- post_install_message:
190
+ post_install_message:
175
191
  rdoc_options: []
176
192
  require_paths:
177
193
  - lib
@@ -186,8 +202,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
186
202
  - !ruby/object:Gem::Version
187
203
  version: '0'
188
204
  requirements: []
189
- rubygems_version: 3.3.7
190
- signing_key:
205
+ rubygems_version: 3.5.22
206
+ signing_key:
191
207
  specification_version: 4
192
208
  summary: Amazon S3 output plugin for Fluentd event collector
193
209
  test_files: []