fluent-plugin-gcs 0.1.1 → 0.4.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 712de7c582c00ef25cd4c781daee6cfc537d9437
4
- data.tar.gz: 40d2803153868f6792d1f157e669ea9ab8b757b4
2
+ SHA256:
3
+ metadata.gz: 85b1b9b0ed8cd2b264dacc7f54fb1bf9e15b2f1e6f28871b17e0bb7e844e1669
4
+ data.tar.gz: a90fec1f3d5509be2df1a72d2479e9db6ba7f133ad67c60789abbdbb1360e519
5
5
  SHA512:
6
- metadata.gz: 8685cb9091a416bf6573c52fb675253eff9ed54a588a34af45baf9ca2f3556945f6b7ec1117f90fa2e54947c421626e2f44e3c1b08d9d873f72e329cf60a6f83
7
- data.tar.gz: 687066ae6f1c8201bfe8e9b5a61c7ed9d1b765bc10b95ec5aa2305a272eaf6bb9d5fc4f606804737f51d753ba6567e554ed68fd20479c1ef69f411000dff3744
6
+ metadata.gz: 8bcb9225215a56ea5ad0d34ac2447e0b39074ae9269e885c2ac70ba2679213340653b47941ea2c5c395861535fd565ae81a6e153e48adef175cf6966b1849a20
7
+ data.tar.gz: dfe13e0a8ea31f3d80d1174aa4c35385cf6206820d5574f31d501767e972b144f646a48711e64c63b10261045385aed4af9a2e7516aeeac0f6aa460cb37cf807
@@ -1,9 +1,9 @@
1
1
  language: ruby
2
2
 
3
3
  rvm:
4
- - 2.1
5
- - 2.2
6
- - 2.3.0
4
+ - 2.6
5
+ - 2.7
6
+ - ruby-head
7
7
 
8
8
  before_install:
9
9
  - gem update bundler
@@ -0,0 +1,40 @@
1
+ ## [Unreleased]
2
+
3
+ New features / Enhancements
4
+
5
+ ## [0.4.1] - 2020/04/17
6
+
7
+ New features
8
+ - [Support blind write to GSC](https://github.com/daichirata/fluent-plugin-gcs/pull/14)
9
+
10
+ ## [0.4.0] - 2019/04/01
11
+
12
+ New features / Enhancements
13
+
14
+ - [Support v0.14 (by @cosmo0920)](https://github.com/daichirata/fluent-plugin-gcs/pull/6)
15
+
16
+ ## [0.3.0] - 2017/02/28
17
+
18
+ New features / Enhancements
19
+
20
+ - [Add support for setting a File's storage_class on file creation](https://github.com/daichirata/fluent-plugin-gcs/pull/4)
21
+ - see also https://cloud.google.com/storage/docs/storage-classes
22
+
23
+ ## [0.2.0] - 2017/01/16
24
+
25
+ Bug fixes
26
+
27
+ - [Remove encryption_key_sha256 parameter.](https://github.com/daichirata/fluent-plugin-gcs/pull/2)
28
+ - see also. https://github.com/GoogleCloudPlatform/google-cloud-ruby/blob/master/google-cloud-storage/CHANGELOG.md#0230--2016-12-8
29
+
30
+ ## [0.1.1] - 2016/11/28
31
+
32
+ New features / Enhancements
33
+
34
+ - Add support for `%{hostname}` of object_key_format
35
+
36
+ [Unreleased]: https://github.com/daichirata/fluent-plugin-gcs/compare/v0.4.0...HEAD
37
+ [0.4.0]: https://github.com/daichirata/fluent-plugin-gcs/compare/v0.3.0...v0.4.0
38
+ [0.3.0]: https://github.com/daichirata/fluent-plugin-gcs/compare/v0.2.0...v0.3.0
39
+ [0.2.0]: https://github.com/daichirata/fluent-plugin-gcs/compare/v0.1.0...v0.2.0
40
+ [0.1.1]: https://github.com/daichirata/fluent-plugin-gcs/compare/v0.1.0...v0.1.1
data/README.md CHANGED
@@ -3,14 +3,52 @@
3
3
 
4
4
  Google Cloud Storage output plugin for [Fluentd](https://github.com/fluent/fluentd).
5
5
 
6
+ ## Requirements
7
+
8
+ | fluent-plugin-gcs | fluentd | ruby |
9
+ |--------------------|------------|--------|
10
+ | >= 0.4.0 | >= v0.14.0 | >= 2.4 |
11
+ | < 0.4.0 | >= v0.12.0 | >= 1.9 |
12
+
6
13
  ## Installation
7
14
 
8
15
  ``` shell
9
- gem install fluent-plugin-gcs
16
+ $ gem install fluent-plugin-gcs -v "~> 0.3" --no-document # for fluentd v0.12 or later
17
+ $ gem install fluent-plugin-gcs -v "0.4.0" --no-document # for fluentd v0.14 or later
10
18
  ```
11
19
 
12
20
  ## Examples
13
21
 
22
+ ### For v0.14 style
23
+
24
+ ```
25
+ <match pattern>
26
+ @type gcs
27
+
28
+ project YOUR_PROJECT
29
+ keyfile YOUR_KEYFILE_PATH
30
+ bucket YOUR_GCS_BUCKET_NAME
31
+ object_key_format %{path}%{time_slice}_%{index}.%{file_extension}
32
+ path logs/${tag}/%Y/%m/%d/
33
+
34
+ # if you want to use ${tag} or %Y/%m/%d/ like syntax in path / object_key_format,
35
+ # need to specify tag for ${tag} and time for %Y/%m/%d in <buffer> argument.
36
+ <buffer tag,time>
37
+ @type file
38
+ path /var/log/fluent/gcs
39
+ timekey 1h # 1 hour partition
40
+ timekey_wait 10m
41
+ timekey_use_utc true # use utc
42
+ </buffer>
43
+
44
+ <format>
45
+ @type json
46
+ </format>
47
+ </match>
48
+ ```
49
+
50
+ ### For v0.12 style
51
+
14
52
  ```
15
53
  <match pattern>
16
54
  @type gcs
@@ -127,8 +165,6 @@ See also [official Formatter article](http://docs.fluentd.org/articles/formatter
127
165
 
128
166
  Create GCS bucket if it does not exists. Default is true.
129
167
 
130
- TODO: rate limit
131
-
132
168
  **acl**
133
169
 
134
170
  Permission for the object in GCS. Acceptable values are:
@@ -142,10 +178,25 @@ Permission for the object in GCS. Acceptable values are:
142
178
 
143
179
  Default is nil (bucket default object ACL). See also [official document](https://cloud.google.com/storage/docs/access-control/lists).
144
180
 
145
- **encryption_key**, **encryption_key_sha256**
181
+ **storage_class**
182
+
183
+ Storage class of the file. Acceptable values are:
184
+
185
+ * `dra` - Durable Reduced Availability
186
+ * `nearline` - Nearline Storage
187
+ * `coldline` - Coldline Storage
188
+ * `multi_regional` - Multi-Regional Storage
189
+ * `regional` - Regional Storage
190
+ * `standard` - Standard Storage
191
+
192
+ Default is nil. See also [official document](https://cloud.google.com/storage/docs/storage-classes).
193
+
194
+ **encryption_key**
146
195
 
147
196
  You can also choose to provide your own AES-256 key for server-side encryption. See also [Customer-supplied encryption keys](https://cloud.google.com/storage/docs/encryption#customer-supplied).
148
197
 
198
+ `encryption_key_sha256` will be calculated using encryption_key.
199
+
149
200
  **overwrite**
150
201
 
151
202
  Overwrite already existing path. Default is false, which raises an error
@@ -174,9 +225,18 @@ Use Local time instead of UTC.
174
225
 
175
226
  Use UTC instead of local time.
176
227
 
177
-
178
228
  And see [official Time Sliced Output article](http://docs.fluentd.org/articles/output-plugin-overview#time-sliced-output-parameters)
179
229
 
230
+ **blind_write**
231
+
232
+ Doesn't check if an object exists in GCS before writing. Default is false.
233
+
234
+ Allows to avoid granting of `storage.objects.get` permission.
235
+
236
+ Warning! If the object exists and `storage.objects.delete` permission is not
237
+ granted, it will result in an unrecoverable error. Usage of `%{hex_random}` is
238
+ recommended.
239
+
180
240
  ### ObjectMetadata
181
241
 
182
242
  User provided web-safe keys and arbitrary string values that will returned with requests for the file as "x-goog-meta-" response headers.
@@ -20,11 +20,10 @@ Gem::Specification.new do |spec|
20
20
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
21
  spec.require_paths = ["lib"]
22
22
 
23
- spec.add_runtime_dependency "fluentd", "~> 0.12.0"
24
- spec.add_runtime_dependency "google-cloud-storage", "~> 0.21"
23
+ spec.add_runtime_dependency "fluentd", [">= 0.14.22", "< 2"]
24
+ spec.add_runtime_dependency "google-cloud-storage", "~> 1.1"
25
25
 
26
- spec.add_development_dependency "bundler", "~> 1.13"
27
- spec.add_development_dependency "rake", "~> 10.0"
26
+ spec.add_development_dependency "rake", ">= 12.3.3"
28
27
  spec.add_development_dependency "rr", "= 1.1.2"
29
28
  spec.add_development_dependency "test-unit", ">= 3.0.8"
30
29
  spec.add_development_dependency "test-unit-rr", ">= 1.0.3"
@@ -1,5 +1,5 @@
1
1
  module Fluent
2
2
  module GCSPlugin
3
- VERSION = "0.1.1"
3
+ VERSION = "0.4.1"
4
4
  end
5
5
  end
@@ -4,11 +4,14 @@ require "socket"
4
4
 
5
5
  require "fluent/plugin/gcs/object_creator"
6
6
  require "fluent/plugin/gcs/version"
7
+ require "fluent/plugin/output"
7
8
 
8
- module Fluent
9
- class GCSOutput < TimeSlicedOutput
9
+ module Fluent::Plugin
10
+ class GCSOutput < Output
10
11
  Fluent::Plugin.register_output("gcs", self)
11
12
 
13
+ helpers :compat_parameters, :formatter, :inject
14
+
12
15
  def initialize
13
16
  super
14
17
  require "google/cloud/storage"
@@ -28,7 +31,7 @@ module Fluent
28
31
  desc: "Format of GCS object keys"
29
32
  config_param :path, :string, default: "",
30
33
  desc: "Path prefix of the files on GCS"
31
- config_param :store_as, :enum, list: [:gzip, :json, :text], default: :gzip,
34
+ config_param :store_as, :enum, list: %i(gzip json text), default: :gzip,
32
35
  desc: "Archive format on GCS"
33
36
  config_param :transcoding, :bool, default: false,
34
37
  desc: "Enable the decompressive form of transcoding"
@@ -40,46 +43,56 @@ module Fluent
40
43
  desc: "Overwrite already existing path"
41
44
  config_param :format, :string, default: "out_file",
42
45
  desc: "Change one line format in the GCS object"
43
- config_param :acl, :enum, list: [:auth_read, :owner_full, :owner_read, :private, :project_private, :public_read], default: nil,
46
+ config_param :acl, :enum, list: %i(auth_read owner_full owner_read private project_private public_read), default: nil,
44
47
  desc: "Permission for the object in GCS"
48
+ config_param :storage_class, :enum, list: %i(dra nearline coldline multi_regional regional standard), default: nil,
49
+ desc: "Storage class of the file"
45
50
  config_param :encryption_key, :string, default: nil, secret: true,
46
51
  desc: "Customer-supplied, AES-256 encryption key"
47
- config_param :encryption_key_sha256, :string, default: nil, secret: true,
48
- desc: "SHA256 hash of the customer-supplied, AES-256 encryption key"
52
+ config_param :blind_write, :bool, default: false,
53
+ desc: "Whether to check if object already exists by given GCS path. Allows avoiding giving storage.object.get permission"
49
54
  config_section :object_metadata, required: false do
50
55
  config_param :key, :string, default: ""
51
56
  config_param :value, :string, default: ""
52
57
  end
53
- # TODO: gem "google-cloud-storage" does not support object lavel storage_class yet.
54
- # config_param :storage_class, :string, default: "regional"
58
+
59
+ DEFAULT_FORMAT_TYPE = "out_file"
60
+
61
+ config_section :format do
62
+ config_set_default :@type, DEFAULT_FORMAT_TYPE
63
+ end
64
+
65
+ config_section :buffer do
66
+ config_set_default :chunk_keys, ['time']
67
+ config_set_default :timekey, (60 * 60 * 24)
68
+ end
55
69
 
56
70
  MAX_HEX_RANDOM_LENGTH = 32
57
71
 
58
72
  def configure(conf)
73
+ compat_parameters_convert(conf, :buffer, :formatter, :inject)
59
74
  super
60
75
 
61
- if @encryption_key && @encryption_key_sha256.nil?
62
- raise Fluent::ConfigError, "encryption_key_sha256 parameter must be provided if `encryption_key` is provided."
63
- end
64
-
65
76
  if @hex_random_length > MAX_HEX_RANDOM_LENGTH
66
77
  raise Fluent::ConfigError, "hex_random_length parameter should be set to #{MAX_HEX_RANDOM_LENGTH} characters or less."
67
78
  end
68
79
 
69
- # The customer-supplied, AES-256 encryption key and hash used to encrypt the file.
80
+ # The customer-supplied, AES-256 encryption key that will be used to encrypt the file.
70
81
  @encryption_opts = {
71
82
  encryption_key: @encryption_key,
72
- encryption_key_sha256: @encryption_key_sha256
73
83
  }
74
84
 
75
85
  if @object_metadata
76
86
  @object_metadata_hash = @object_metadata.map {|m| [m.key, m.value] }.to_h
77
87
  end
78
88
 
79
- @formatter = Fluent::Plugin.new_formatter(@format)
80
- @formatter.configure(conf)
89
+ @formatter = formatter_create
81
90
 
82
91
  @object_creator = Fluent::GCS.discovered_object_creator(@store_as, transcoding: @transcoding)
92
+ # For backward compatibility
93
+ # TODO: Remove time_slice_format when end of support compat_parameters
94
+ @configured_time_slice_format = conf['time_slice_format']
95
+ @time_slice_with_tz = Fluent::Timezone.formatter(@timekey_zone, @configured_time_slice_format || timekey_to_timeformat(@buffer_config['timekey']))
83
96
  end
84
97
 
85
98
  def start
@@ -96,7 +109,12 @@ module Fluent
96
109
  end
97
110
 
98
111
  def format(tag, time, record)
99
- @formatter.format(tag, time, record)
112
+ r = inject_values_to_record(tag, time, record)
113
+ @formatter.format(tag, time, r)
114
+ end
115
+
116
+ def multi_workers_ready?
117
+ true
100
118
  end
101
119
 
102
120
  def write(chunk)
@@ -106,6 +124,7 @@ module Fluent
106
124
  opts = {
107
125
  metadata: @object_metadata_hash,
108
126
  acl: @acl,
127
+ storage_class: @storage_class,
109
128
  content_type: @object_creator.content_type,
110
129
  content_encoding: @object_creator.content_encoding,
111
130
  }
@@ -132,23 +151,33 @@ module Fluent
132
151
  Digest::MD5.hexdigest(chunk.unique_id)[0...@hex_random_length]
133
152
  end
134
153
 
135
- def format_path(chunk)
136
- now = Time.strptime(chunk.key, @time_slice_format)
137
- (@localtime ? now : now.utc).strftime(@path)
154
+ def check_object_exists(path)
155
+ if !@blind_write
156
+ return @gcs_bucket.find_file(path, @encryption_opts)
157
+ else
158
+ return false
159
+ end
138
160
  end
139
161
 
140
162
  def generate_path(chunk, i = 0, prev = nil)
163
+ metadata = chunk.metadata
164
+ time_slice = if metadata.timekey.nil?
165
+ ''.freeze
166
+ else
167
+ @time_slice_with_tz.call(metadata.timekey)
168
+ end
141
169
  tags = {
142
170
  "%{file_extension}" => @object_creator.file_extension,
143
171
  "%{hex_random}" => hex_random(chunk),
144
172
  "%{hostname}" => Socket.gethostname,
145
173
  "%{index}" => i,
146
- "%{path}" => format_path(chunk),
147
- "%{time_slice}" => chunk.key,
174
+ "%{path}" => @path,
175
+ "%{time_slice}" => time_slice,
148
176
  "%{uuid_flush}" => SecureRandom.uuid,
149
177
  }
150
178
  path = @object_key_format.gsub(Regexp.union(tags.keys), tags)
151
- return path unless @gcs_bucket.find_file(path, @encryption_opts)
179
+ path = extract_placeholders(path, chunk)
180
+ return path unless check_object_exists(path)
152
181
 
153
182
  if path == prev
154
183
  if @overwrite
@@ -159,5 +188,16 @@ module Fluent
159
188
  end
160
189
  generate_path(chunk, i + 1, path)
161
190
  end
191
+
192
+ # This is stolen from Fluentd
193
+ def timekey_to_timeformat(timekey)
194
+ case timekey
195
+ when nil then ''
196
+ when 0...60 then '%Y%m%d%H%M%S' # 60 exclusive
197
+ when 60...3600 then '%Y%m%d%H%M'
198
+ when 3600...86400 then '%Y%m%d%H'
199
+ else '%Y%m%d'
200
+ end
201
+ end
162
202
  end
163
203
  end
metadata CHANGED
@@ -1,71 +1,63 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-gcs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daichi HIRATA
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-11-28 00:00:00.000000000 Z
11
+ date: 2020-10-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fluentd
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 0.14.22
20
+ - - "<"
18
21
  - !ruby/object:Gem::Version
19
- version: 0.12.0
22
+ version: '2'
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
- - - "~>"
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 0.14.22
30
+ - - "<"
25
31
  - !ruby/object:Gem::Version
26
- version: 0.12.0
32
+ version: '2'
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: google-cloud-storage
29
35
  requirement: !ruby/object:Gem::Requirement
30
36
  requirements:
31
37
  - - "~>"
32
38
  - !ruby/object:Gem::Version
33
- version: '0.21'
39
+ version: '1.1'
34
40
  type: :runtime
35
41
  prerelease: false
36
42
  version_requirements: !ruby/object:Gem::Requirement
37
43
  requirements:
38
44
  - - "~>"
39
45
  - !ruby/object:Gem::Version
40
- version: '0.21'
41
- - !ruby/object:Gem::Dependency
42
- name: bundler
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '1.13'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '1.13'
46
+ version: '1.1'
55
47
  - !ruby/object:Gem::Dependency
56
48
  name: rake
57
49
  requirement: !ruby/object:Gem::Requirement
58
50
  requirements:
59
- - - "~>"
51
+ - - ">="
60
52
  - !ruby/object:Gem::Version
61
- version: '10.0'
53
+ version: 12.3.3
62
54
  type: :development
63
55
  prerelease: false
64
56
  version_requirements: !ruby/object:Gem::Requirement
65
57
  requirements:
66
- - - "~>"
58
+ - - ">="
67
59
  - !ruby/object:Gem::Version
68
- version: '10.0'
60
+ version: 12.3.3
69
61
  - !ruby/object:Gem::Dependency
70
62
  name: rr
71
63
  requirement: !ruby/object:Gem::Requirement
@@ -131,6 +123,7 @@ extra_rdoc_files: []
131
123
  files:
132
124
  - ".gitignore"
133
125
  - ".travis.yml"
126
+ - CHANGELOG.md
134
127
  - Gemfile
135
128
  - LICENSE.txt
136
129
  - README.md
@@ -160,8 +153,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
160
153
  - !ruby/object:Gem::Version
161
154
  version: '0'
162
155
  requirements: []
163
- rubyforge_project:
164
- rubygems_version: 2.5.1
156
+ rubygems_version: 3.0.3
165
157
  signing_key:
166
158
  specification_version: 4
167
159
  summary: Google Cloud Storage output plugin for Fluentd