fluent-plugin-gcs 0.1.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ac0dec9f5eadfcf591d969f57d8c0299e8f9060e
4
+ data.tar.gz: 6ca58b3c7a54526ac95d2711407491a7f8ccfed5
5
+ SHA512:
6
+ metadata.gz: f8e0681f28757ee42a811f623afdd987bcd59006574356cab3b64001f57c45ae6e64fdfb2cf6cd94eab258f554a886c79d50c52e18f8d38cc70d7f73a0980a57
7
+ data.tar.gz: cf27dad559db3e0306137cb395faf4268c96223d4da6dd2b06970ff2e060ecdc284a7cfaf7b4a5e158c855db6d59dbd903c337ad7ee9ec87ed7dcacb3cf85c61
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.travis.yml ADDED
@@ -0,0 +1,11 @@
1
+ language: ruby
2
+
3
+ rvm:
4
+ - 2.1
5
+ - 2.2
6
+ - 2.3.0
7
+
8
+ before_install:
9
+ - gem update bundler
10
+
11
+ script: bundle exec rake test
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in fluent-plugin-gcs.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,13 @@
1
+ Copyright (c) 2016 - Daichi HIRATA
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,197 @@
1
+ # fluent-plugin-gcs
2
+ [![Build Status](https://travis-ci.org/daichirata/fluent-plugin-gcs.svg?branch=master)](https://travis-ci.org/daichirata/fluent-plugin-gcs) [![Code Climate](https://codeclimate.com/github/daichirata/fluent-plugin-gcs/badges/gpa.svg)](https://codeclimate.com/github/daichirata/fluent-plugin-gcs)
3
+
4
+ Google Cloud Storage output plugin for [Fluentd](https://github.com/fluent/fluentd).
5
+
6
+ ## Installation
7
+
8
+ ``` shell
9
+ gem install fluent-plugin-gcs
10
+ ```
11
+
12
+ ## Examples
13
+
14
+ ```
15
+ <match pattern>
16
+ @type gcs
17
+
18
+ project YOUR_PROJECT
19
+ keyfile YOUR_KEYFILE_PATH
20
+ gcs_bucket YOUR_GCS_BUCKET_NAME
21
+ gcs_object_key_format %{path}%{time_slice}_%{index}.%{file_extension}
22
+ path logs/
23
+ buffer_path /var/log/fluent/gcs
24
+
25
+ time_slice_format %Y%m%d-%H
26
+ time_slice_wait 10m
27
+ utc
28
+ </match>
29
+ ```
30
+
31
+ ## Configuration
32
+
33
+ ### Authentication
34
+
35
+ You can provide the project and credential information to connect to the Storage
36
+ service, or if you are running on Google Compute Engine this configuration is taken care of for you.
37
+
38
+ **project**
39
+
40
+ Project identifier for GCS. Project are discovered in the following order:
41
+ * Specify project in `project`
42
+ * Discover project in environment variables `STORAGE_PROJECT`, `GOOGLE_CLOUD_PROJECT`, `GCLOUD_PROJECT`
43
+ * Discover GCE credentials
44
+
45
+ **keyfile**
46
+
47
+ Path of GCS service account credentials JSON file. Credentials are discovered in the following order:
48
+ * Specify credentials path in `keyfile`
49
+ * Discover credentials path in environment variables `GOOGLE_CLOUD_KEYFILE`, `GCLOUD_KEYFILE`
50
+ * Discover credentials JSON in environment variables `GOOGLE_CLOUD_KEYFILE_JSON`, `GCLOUD_KEYFILE_JSON`
51
+ * Discover credentials file in the Cloud SDK's path
52
+ * Discover GCE credentials
53
+
54
+ **client_retries**
55
+
56
+ Number of times to retry requests on server error.
57
+
58
+ **client_timeout**
59
+
60
+ Default timeout to use in requests.
61
+
62
+ **bucket (*required)**
63
+
64
+ GCS bucket name.
65
+
66
+ **store_as**
67
+
68
+ Archive format on GCS. You can use serveral format:
69
+
70
+ * gzip (default)
71
+ * json
72
+ * text
73
+
74
+ **path**
75
+
76
+ path prefix of the files on GCS. Default is "" (no prefix).
77
+
78
+ **object_key_format**
79
+
80
+ The format of GCS object keys. You can use several built-in variables:
81
+
82
+ * %{path}
83
+ * %{time_slice}
84
+ * %{index}
85
+ * %{file_extension}
86
+ * %{uuid_flush}
87
+ * %{hex_random}
88
+
89
+ to decide keys dynamically.
90
+
91
+ * `%{path}` is exactly the value of `path` configured in the configuration file. E.g., "logs/" in the example configuration above.
92
+ * `%{time_slice}` is the time-slice in text that are formatted with `time_slice_format`.
93
+ * `%{index}` is the sequential number starts from 0, increments when multiple files are uploaded to GCS in the same time slice.
94
+ * `%{file_extention}` is changed by the value of `store_as`.
95
+ * gzip - gz
96
+ * json - json
97
+ * text - txt
98
+ * `%{uuid_flush}` a uuid that is replaced everytime the buffer will be flushed
99
+ * `%{hex_random}` a random hex string that is replaced for each buffer chunk, not assured to be unique.
100
+ You can configure the length of string with a `hex_random_length` parameter (Default: 4).
101
+
102
+ The default format is `%{path}%{time_slice}_%{index}.%{file_extension}`.
103
+
104
+ **hex_random_length**
105
+
106
+ The length of `%{hex_random}` placeholder.
107
+
108
+ **transcoding**
109
+
110
+ Enable the decompressive form of transcoding.
111
+
112
+ See also [Transcoding of gzip-compressed files](https://cloud.google.com/storage/docs/transcoding).
113
+
114
+ **format**
115
+
116
+ Change one line format in the GCS object. You can use serveral format:
117
+
118
+ * out_file (default)
119
+ * json
120
+ * ltsv
121
+ * single_value
122
+
123
+ See also [official Formatter article](http://docs.fluentd.org/articles/formatter-plugin-overview).
124
+
125
+ **auto_create_bucket**
126
+
127
+ Create GCS bucket if it does not exists. Default is true.
128
+
129
+ TODO: rate limit
130
+
131
+ **acl**
132
+
133
+ Permission for the object in GCS. Acceptable values are:
134
+
135
+ * `auth_read` - File owner gets OWNER access, and allAuthenticatedUsers get READER access.
136
+ * `owner_full` - File owner gets OWNER access, and project team owners get OWNER access.
137
+ * `owner_read` - File owner gets OWNER access, and project team owners get READER access.
138
+ * `private` - File owner gets OWNER access.
139
+ * `project_private` - File owner gets OWNER access, and project team members get access according to their roles.
140
+ * `public_read` - File owner gets OWNER access, and allUsers get READER access.
141
+
142
+ Default is nil (bucket default object ACL). See also [official document](https://cloud.google.com/storage/docs/access-control/lists).
143
+
144
+ **encryption_key**, **encryption_key_sha256**
145
+
146
+ 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).
147
+
148
+ **overwrite**
149
+
150
+ Overwrite already existing path. Default is false, which raises an error
151
+ if a GCS object of the same path already exists, or increment the
152
+ `%{index}` placeholder until finding an absent path.
153
+
154
+ **buffer_path (*required)**
155
+
156
+ path prefix of the files to buffer logs.
157
+
158
+ **time_slice_format**
159
+
160
+ Format of the time used as the file name. Default is '%Y%m%d'. Use
161
+ '%Y%m%d%H' to split files hourly.
162
+
163
+ **time_slice_wait**
164
+
165
+ The time to wait old logs. Default is 10 minutes. Specify larger value if
166
+ old logs may reache.
167
+
168
+ **localtime**
169
+
170
+ Use Local time instead of UTC.
171
+
172
+ **utc**
173
+
174
+ Use UTC instead of local time.
175
+
176
+
177
+ And see [official Time Sliced Output article](http://docs.fluentd.org/articles/output-plugin-overview#time-sliced-output-parameters)
178
+
179
+ ### ObjectMetadata
180
+
181
+ User provided web-safe keys and arbitrary string values that will returned with requests for the file as "x-goog-meta-" response headers.
182
+
183
+ ```
184
+ <match *>
185
+ @type gcs
186
+
187
+ <object_metadata>
188
+ key KEY_DATA_1
189
+ value VALUE_DATA_1
190
+ </object_metadata>
191
+
192
+ <object_metadata>
193
+ key KEY_DATA_2
194
+ value VALUE_DATA_2
195
+ </object_metadata>
196
+ </match>
197
+ ```
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require "bundler"
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require "rake/testtask"
5
+ Rake::TestTask.new(:test) do |test|
6
+ test.libs << "lib" << "test"
7
+ test.test_files = FileList["test/plugin/test_*.rb"]
8
+ test.verbose = true
9
+ end
10
+
11
+ task :default => [:test]
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "fluent/plugin/gcs"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,32 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'fluent/plugin/gcs/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "fluent-plugin-gcs"
8
+ spec.version = Fluent::GCSPlugin::VERSION
9
+ spec.authors = ["Daichi HIRATA"]
10
+ spec.email = ["hirata.daichi@gmail.com"]
11
+ spec.summary = "Google Cloud Storage output plugin for Fluentd"
12
+ spec.description = "Google Cloud Storage output plugin for Fluentd"
13
+ spec.homepage = "https://github.com/daishirata/fluent-plugin-gcs"
14
+ spec.license = "Apache-2.0"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
+ f.match(%r{^(test|spec|features)/})
18
+ end
19
+ spec.bindir = "exe"
20
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
+ spec.require_paths = ["lib"]
22
+
23
+ spec.add_runtime_dependency "fluentd", "~> 0.12.0"
24
+ spec.add_runtime_dependency "google-cloud-storage", "~> 0.21"
25
+
26
+ spec.add_development_dependency "bundler", "~> 1.13"
27
+ spec.add_development_dependency "rake", "~> 10.0"
28
+ spec.add_development_dependency "rr", "= 1.1.2"
29
+ spec.add_development_dependency "test-unit", ">= 3.0.8"
30
+ spec.add_development_dependency "test-unit-rr", ">= 1.0.3"
31
+ spec.add_development_dependency "timecop"
32
+ end
@@ -0,0 +1,92 @@
1
+ require "tempfile"
2
+ require "zlib"
3
+
4
+ module Fluent
5
+ module GCS
6
+ def self.discovered_object_creator(store_as, transcoding: nil)
7
+ case store_as
8
+ when :gzip
9
+ Fluent::GCS::GZipObjectCreator.new(transcoding)
10
+ when :json
11
+ Fluent::GCS::JSONObjectCreator.new
12
+ when :text
13
+ Fluent::GCS::TextObjectCreator.new
14
+ end
15
+ end
16
+
17
+ class ObjectCreator
18
+ def content_type
19
+ raise NotImplementedError
20
+ end
21
+
22
+ def content_encoding
23
+ nil
24
+ end
25
+
26
+ def file_extension
27
+ raise NotImplementedError
28
+ end
29
+
30
+ def write(chunk, io)
31
+ raise NotImplementedError
32
+ end
33
+
34
+ def create(chunk, &block)
35
+ Tempfile.create("fluent-plugin-gcs") do |f|
36
+ f.binmode
37
+ f.sync = true
38
+ write(chunk, f)
39
+ block.call(f)
40
+ end
41
+ end
42
+ end
43
+
44
+ class GZipObjectCreator < ObjectCreator
45
+ def initialize(transcoding)
46
+ @transcoding = transcoding
47
+ end
48
+
49
+ def content_type
50
+ @transcoding ? "text/plain" : "application/gzip"
51
+ end
52
+
53
+ def content_encoding
54
+ @transcoding ? "gzip" : nil
55
+ end
56
+
57
+ def file_extension
58
+ "gz"
59
+ end
60
+
61
+ def write(chunk, io)
62
+ writer = Zlib::GzipWriter.new(io)
63
+ chunk.write_to(writer)
64
+ writer.finish
65
+ end
66
+ end
67
+
68
+ class TextObjectCreator < ObjectCreator
69
+ def content_type
70
+ "text/plain"
71
+ end
72
+
73
+ def file_extension
74
+ "txt"
75
+ end
76
+
77
+ def write(chunk, io)
78
+ chunk.write_to(io)
79
+ end
80
+ end
81
+
82
+ class JSONObjectCreator < TextObjectCreator
83
+ def content_type
84
+ "application/json"
85
+ end
86
+
87
+ def file_extension
88
+ "json"
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,5 @@
1
+ module Fluent
2
+ module GCSPlugin
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,161 @@
1
+ require "securerandom"
2
+ require "digest"
3
+
4
+ require "fluent/plugin/gcs/object_creator"
5
+ require "fluent/plugin/gcs/version"
6
+
7
+ module Fluent
8
+ class GCSOutput < TimeSlicedOutput
9
+ Fluent::Plugin.register_output("gcs", self)
10
+
11
+ def initialize
12
+ super
13
+ require "google/cloud/storage"
14
+ end
15
+
16
+ config_param :project, :string, default: nil,
17
+ desc: "Project identifier for GCS"
18
+ config_param :keyfile, :string, default: nil,
19
+ desc: "Path of GCS service account credentials JSON file"
20
+ config_param :client_retries, :integer, default: nil,
21
+ desc: "Number of times to retry requests on server error"
22
+ config_param :client_timeout, :integer, default: nil,
23
+ desc: "Default timeout to use in requests"
24
+ config_param :bucket, :string,
25
+ desc: "Name of a GCS bucket"
26
+ config_param :object_key_format, :string, default: "%{path}%{time_slice}_%{index}.%{file_extension}",
27
+ desc: "Format of GCS object keys"
28
+ config_param :path, :string, default: "",
29
+ desc: "Path prefix of the files on GCS"
30
+ config_param :store_as, :enum, list: [:gzip, :json, :text], default: :gzip,
31
+ desc: "Archive format on GCS"
32
+ config_param :transcoding, :bool, default: false,
33
+ desc: "Enable the decompressive form of transcoding"
34
+ config_param :auto_create_bucket, :bool, default: true,
35
+ desc: "Create GCS bucket if it does not exists"
36
+ config_param :hex_random_length, :integer, default: 4,
37
+ desc: "Max length of `%{hex_random}` placeholder(4-16)"
38
+ config_param :overwrite, :bool, default: false,
39
+ desc: "Overwrite already existing path"
40
+ config_param :format, :string, default: "out_file",
41
+ desc: "Change one line format in the GCS object"
42
+ config_param :acl, :enum, list: [:auth_read, :owner_full, :owner_read, :private, :project_private, :public_read], default: nil,
43
+ desc: "Permission for the object in GCS"
44
+ config_param :encryption_key, :string, default: nil, secret: true,
45
+ desc: "Customer-supplied, AES-256 encryption key"
46
+ config_param :encryption_key_sha256, :string, default: nil, secret: true,
47
+ desc: "SHA256 hash of the customer-supplied, AES-256 encryption key"
48
+ config_section :object_metadata, required: false do
49
+ config_param :key, :string, default: ""
50
+ config_param :value, :string, default: ""
51
+ end
52
+ # TODO: gem "google-cloud-storage" does not support object lavel storage_class yet.
53
+ # config_param :storage_class, :string, default: "regional"
54
+
55
+ MAX_HEX_RANDOM_LENGTH = 32
56
+
57
+ def configure(conf)
58
+ super
59
+
60
+ if @encryption_key && @encryption_key_sha256.nil?
61
+ raise Fluent::ConfigError, "encryption_key_sha256 parameter must be provided if `encryption_key` is provided."
62
+ end
63
+
64
+ if @hex_random_length > MAX_HEX_RANDOM_LENGTH
65
+ raise Fluent::ConfigError, "hex_random_length parameter should be set to #{MAX_HEX_RANDOM_LENGTH} characters or less."
66
+ end
67
+
68
+ # The customer-supplied, AES-256 encryption key and hash used to encrypt the file.
69
+ @encryption_opts = {
70
+ encryption_key: @encryption_key,
71
+ encryption_key_sha256: @encryption_key_sha256
72
+ }
73
+
74
+ if @object_metadata
75
+ @object_metadata_hash = @object_metadata.map {|m| [m.key, m.value] }.to_h
76
+ end
77
+
78
+ @formatter = Fluent::Plugin.new_formatter(@format)
79
+ @formatter.configure(conf)
80
+
81
+ @object_creator = Fluent::GCS.discovered_object_creator(@store_as, transcoding: @transcoding)
82
+ end
83
+
84
+ def start
85
+ @gcs = Google::Cloud::Storage.new(
86
+ project: @project,
87
+ keyfile: @keyfile,
88
+ retries: @client_retries,
89
+ timeout: @client_timeout
90
+ )
91
+ @gcs_bucket = @gcs.bucket(@bucket)
92
+
93
+ ensure_bucket
94
+ super
95
+ end
96
+
97
+ def format(tag, time, record)
98
+ @formatter.format(tag, time, record)
99
+ end
100
+
101
+ def write(chunk)
102
+ path = generate_path(chunk)
103
+
104
+ @object_creator.create(chunk) do |obj|
105
+ opts = {
106
+ metadata: @object_metadata_hash,
107
+ acl: @acl,
108
+ content_type: @object_creator.content_type,
109
+ content_encoding: @object_creator.content_encoding,
110
+ }
111
+ opts.merge!(@encryption_opts)
112
+
113
+ log.debug { "out_gcs: upload chunk:#{chunk.key} to gcs://#{@bucket}/#{path} options: #{opts}" }
114
+ @gcs_bucket.upload_file(obj.path, path, opts)
115
+ end
116
+ end
117
+
118
+ private
119
+
120
+ def ensure_bucket
121
+ return unless @gcs_bucket.nil?
122
+
123
+ if !@auto_create_bucket
124
+ raise "bucket `#{@bucket}` does not exist"
125
+ end
126
+ log.info "creating bucket `#{@bucket}`"
127
+ @gcs_bucket = @gcs.create_bucket(@bucket)
128
+ end
129
+
130
+ def hex_random(chunk)
131
+ Digest::MD5.hexdigest(chunk.unique_id)[0...@hex_random_length]
132
+ end
133
+
134
+ def format_path(chunk)
135
+ now = Time.strptime(chunk.key, @time_slice_format)
136
+ (@localtime ? now : now.utc).strftime(@path)
137
+ end
138
+
139
+ def generate_path(chunk, i = 0, prev = nil)
140
+ tags = {
141
+ "%{file_extension}" => @object_creator.file_extension,
142
+ "%{hex_random}" => hex_random(chunk),
143
+ "%{index}" => i,
144
+ "%{path}" => format_path(chunk),
145
+ "%{time_slice}" => chunk.key,
146
+ "%{uuid_flush}" => SecureRandom.uuid,
147
+ }
148
+ path = @object_key_format.gsub(Regexp.union(tags.keys), tags)
149
+ return path unless @gcs_bucket.find_file(path, @encryption_opts)
150
+
151
+ if path == prev
152
+ if @overwrite
153
+ log.warn "object `#{path}` already exists but overwrites it"
154
+ return path
155
+ end
156
+ raise "object `#{path}` already exists"
157
+ end
158
+ generate_path(chunk, i + 1, path)
159
+ end
160
+ end
161
+ end
metadata ADDED
@@ -0,0 +1,168 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-gcs
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Daichi HIRATA
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-11-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: fluentd
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.12.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.12.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: google-cloud-storage
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.21'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !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'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rr
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '='
74
+ - !ruby/object:Gem::Version
75
+ version: 1.1.2
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '='
81
+ - !ruby/object:Gem::Version
82
+ version: 1.1.2
83
+ - !ruby/object:Gem::Dependency
84
+ name: test-unit
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: 3.0.8
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: 3.0.8
97
+ - !ruby/object:Gem::Dependency
98
+ name: test-unit-rr
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: 1.0.3
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: 1.0.3
111
+ - !ruby/object:Gem::Dependency
112
+ name: timecop
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: Google Cloud Storage output plugin for Fluentd
126
+ email:
127
+ - hirata.daichi@gmail.com
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - ".gitignore"
133
+ - ".travis.yml"
134
+ - Gemfile
135
+ - LICENSE.txt
136
+ - README.md
137
+ - Rakefile
138
+ - bin/console
139
+ - bin/setup
140
+ - fluent-plugin-gcs.gemspec
141
+ - lib/fluent/plugin/gcs/object_creator.rb
142
+ - lib/fluent/plugin/gcs/version.rb
143
+ - lib/fluent/plugin/out_gcs.rb
144
+ homepage: https://github.com/daishirata/fluent-plugin-gcs
145
+ licenses:
146
+ - Apache-2.0
147
+ metadata: {}
148
+ post_install_message:
149
+ rdoc_options: []
150
+ require_paths:
151
+ - lib
152
+ required_ruby_version: !ruby/object:Gem::Requirement
153
+ requirements:
154
+ - - ">="
155
+ - !ruby/object:Gem::Version
156
+ version: '0'
157
+ required_rubygems_version: !ruby/object:Gem::Requirement
158
+ requirements:
159
+ - - ">="
160
+ - !ruby/object:Gem::Version
161
+ version: '0'
162
+ requirements: []
163
+ rubyforge_project:
164
+ rubygems_version: 2.5.1
165
+ signing_key:
166
+ specification_version: 4
167
+ summary: Google Cloud Storage output plugin for Fluentd
168
+ test_files: []