logstash-input-qingstor 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4a30583b85c2e846709cecde14a016f28f1907b3
4
+ data.tar.gz: 7834fd79bf3ad2c7de3e971faf42e347fe38f769
5
+ SHA512:
6
+ metadata.gz: e63c11974c60a1fa33525c5b758ebbe7d80202d0e534605060bdbc7833df608d87db40e92c4cc4775be37ae78373df264ed6d96b226feab083bee8a658ec35f5
7
+ data.tar.gz: 0723a8e49fd65c445d5546030f8fc4130794cc96148ebeebd8e517b9280f00f2db732416a90eff7d8dbe3b7d499f2a9e166978bace5b2a624075cb51f4fbad0a
data/CHANGELOG.md ADDED
@@ -0,0 +1,2 @@
1
+ ## 0.1.0
2
+ - Basic functions: Fetch file(.log/.gz), delete atfer processing, backup to remote bucket/local dir.
@@ -0,0 +1,44 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
6
+
7
+ ## Our Standards
8
+
9
+ Examples of behavior that contributes to creating a positive environment
10
+ include:
11
+
12
+ * Using welcoming and inclusive language
13
+ * Being respectful of differing viewpoints and experiences
14
+ * Gracefully accepting constructive criticism
15
+ * Focusing on what is best for the community
16
+ * Showing empathy towards other community members
17
+
18
+ Examples of unacceptable behavior by participants include:
19
+
20
+ * The use of sexualized language or imagery and unwelcome sexual attention or advances
21
+ * Trolling, insulting/derogatory comments, and personal or political attacks
22
+ * Public or private harassment
23
+ * Publishing others' private information, such as a physical or electronic address, without explicit permission
24
+ * Other conduct which could reasonably be considered inappropriate in a professional setting
25
+
26
+ ## Our Responsibilities
27
+
28
+ Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
29
+
30
+ Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
31
+
32
+ ## Scope
33
+
34
+ This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
35
+
36
+ ## Enforcement
37
+
38
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at pengsrc@yunify.com. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
39
+
40
+ Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
41
+
42
+ ## Attribution
43
+
44
+ This Code of Conduct is adapted from the [Contributor Covenant][http://contributor-covenant.org], version 1.4, available at [http://contributor-covenant.org/version/1/4][http://contributor-covenant.org/version/1/4].
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,43 @@
1
+ # Contributing Guidelines
2
+
3
+ We love contributions from everyone. By participating in this project, you agree to abide by the [_`Contributor Covenant Code of Conduct`_](./CODE_OF_CONDUCT.md) and the conventions described in this documentation.
4
+
5
+ ## Getting Started
6
+
7
+ ### Reporting Issues
8
+
9
+ A great way to contribute to the project is to send a detailed report when you encounter an issue. We always appreciate a well-written, thorough bug report, and will thank you for it!
10
+
11
+ Check that [our issues list](https://github.com/Tacinight/logstash-output-qingstor/issues) doesn't already include that problem or suggestion before submitting an issue. If you find a match, you can use the "subscribe" button to get notified on updates. Do not leave random "+1" or "I have this too" comments, as they only clutter the discussion, and don't help resolving it. However, if you have ways to reproduce the issue or have additional information that may help resolving the issue, please leave a comment.
12
+
13
+ When reporting issues, please describe what happened clearly, and include the steps required to reproduce the problem if possible and applicable. This information will help us review and fix your issue faster. When sending lengthy log-files, consider posting them as a gist (https://gist.github.com). Don't forget to remove sensitive data from your log files before posting (you can replace those parts with "CONFIDENTIAL").
14
+
15
+ ### Sending Pull Request
16
+
17
+ Pull requests are always welcome, we will appreciate it.
18
+
19
+ Any significant improvement should be documented as a GitHub [issue](https://github.com/Tacinight/logstash-output-qingstor/issues) before anybody starts working on it.
20
+
21
+ 1. Fork it ( https://github.com/Tacinight/logstash-output-qingstor/fork )
22
+ 2. Create your feature branch (`git checkout -b new-feature`)
23
+ 3. Commit your changes (`git commit -asm 'Add some feature'`)
24
+ 4. Push to the branch (`git push origin new-feature`)
25
+ 5. Create a new Pull Request
26
+
27
+ ## Conventions
28
+
29
+ ### Patch Content
30
+
31
+ * Always remove the trailing whitespace
32
+ * Keep a newline at the end of text files
33
+ * Exclude irrelevant files, such as `*.a`, `.bundle`, and `.DS_Store`
34
+ * Always pass all the tests before submitting
35
+ * Let the propose of each patch simple and clear
36
+
37
+ ### Commit Message
38
+
39
+ * Capitalize the subject line
40
+ * Limit the subject line to 50 characters
41
+ * Do not end the subject line with a period
42
+ * Wrap the body at 72 characters
43
+ * Use the body to explain what happened
data/CONTRIBUTORS ADDED
@@ -0,0 +1,10 @@
1
+ The following is a list of people who have contributed ideas, code, bug
2
+ reports, or in general have helped logstash along its way.
3
+
4
+ Contributors:
5
+ * Evan Zhao - tacingiht@gmail.com
6
+
7
+ Note: If you've sent us patches, bug reports, or otherwise contributed to
8
+ Logstash, and you aren't on the list above and want to be, please let us know
9
+ and we'll make sure you're here. Contributions from folks like you are what make
10
+ open source awesome.
data/DEVELOPER.md ADDED
@@ -0,0 +1,2 @@
1
+ # logstash-input-qingstor
2
+ Example input plugin. This should help bootstrap your effort to write your own input plugin!
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
3
+
data/LICENSE ADDED
@@ -0,0 +1,11 @@
1
+ Licensed under the Apache License, Version 2.0 (the "License");
2
+ you may not use this file except in compliance with the License.
3
+ You may obtain a copy of the License at
4
+
5
+ http://www.apache.org/licenses/LICENSE-2.0
6
+
7
+ Unless required by applicable law or agreed to in writing, software
8
+ distributed under the License is distributed on an "AS IS" BASIS,
9
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
+ See the License for the specific language governing permissions and
11
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,168 @@
1
+ # Logstash Input Plugin for Qingstor
2
+
3
+ 这是一个适配了[Qingstor](https://www.qingcloud.com/products/storage#qingstor), 工作在logstash中的input插件. Qingstor是[Qingcloud](https://www.qingcloud.com/)推出的对象存储服务.
4
+ 作为一个input插件, 它能下载存储在Qingstor上的日志文件, 读入到logstash中进行进一步处理.
5
+ 详细功能参考下面配置说明.
6
+
7
+ 目前代码尚未提交至官方插件库, 需要手动安装, 安装方法参考下文.
8
+
9
+ ## 1. 配置说明
10
+
11
+ #### 1.1 最小运行配置
12
+ - 使用'-f' 接受一个*.conf文件或者使用'-e'参数最小运行配置时, 至少需要以下三项
13
+ ```sh
14
+ input {
15
+ qingstor {
16
+ access_key_id => 'your_access_key_id' #required
17
+ secret_access_key => 'your_secret_access_key' #required
18
+ bucket => 'bucket_name' #required
19
+ # region => "pek3a" #optional, default value "pek3a"
20
+ }
21
+ }
22
+
23
+ ```
24
+
25
+ #### 1.2 其他可选参数说明
26
+ ```sh
27
+ input {
28
+ qingstor {
29
+ ......
30
+ # 指定下载文件的前缀.
31
+ # 默认nil,
32
+ prefix => 'aprefix'
33
+
34
+ # 本地保存临时文件的目录.
35
+ # 默认: 系统临时文件目录下的qingstor2logstash文件夹, 例如linux下 "/tmp/qingstor2logstash".
36
+ tmpdir => '/local/temporary/directory'
37
+
38
+ # 是否在处理之后, 删除远程bucket中的文件.
39
+ # 默认: false
40
+ delete_later => true
41
+
42
+ # 如果指定一个本地目录, 那么在处理完之后将文件备份至该位置.
43
+ # 默认: nil
44
+ local_dir => 'your/local/directory'
45
+
46
+ # 如果指定了该值, 那么在处理完之后将文件上传到Qingstor指定的bucket中.
47
+ # 默认: nil
48
+ backup_bucket => 'backupbucket'
49
+
50
+ # 配合上一项使用, 指定备份bucket所在的region.
51
+ # 默认: "pek3a", 可选枚举值: ["pek3a", "sh1a"]
52
+ backup_region => "sh1a"
53
+
54
+ # 备份文件的前缀
55
+ # 默认: nil
56
+ backup_prefix => "logstash/backup"
57
+
58
+ # 指定一个sincedb的保存位置, sincedb用于记录上一次抓取文件的时间
59
+ # 没有指定时默认在用户HOME目录下创建
60
+ # 默认: nil
61
+ sincedb_path => "~/qingstor/.sincedb"
62
+
63
+ # 每次抓取的时间间隔, 单位秒
64
+ # 默认: 10(s)
65
+ interval => 30
66
+
67
+ }
68
+ }
69
+
70
+ ```
71
+
72
+ ## 2. 安装插件
73
+
74
+ #### 2.1 直接运行本地的插件
75
+
76
+ - 编辑Logstash目录下的Genfile, 添加插件的路径, 例如
77
+ ```ruby
78
+ gem "logstash-input-qingstor", :path => "/your/local/logstash-input-qingstor"
79
+ ```
80
+ - 安装插件
81
+ ```sh
82
+ bin/logstash-plugin install --no-verify
83
+ ```
84
+ - 使用插件运行
85
+ ```sh
86
+ bin/logstash -e "input {qingstor { access_key_id => 'your_access_key_id'
87
+ secret_access_key => 'your_secret_access_key'
88
+ bucket => 'bucket_name' }}'
89
+ ```
90
+ 此时你对插件所做的任意的代码上的修改都会直接生效.
91
+
92
+ #### 2.2 安装一个本地插件然后运行
93
+
94
+ 这一步你需要生成一个插件的gem包, 然后通过logstash来安装到logstash的插件目录下
95
+ - 在logstash-input-qingstor项目目录下生成gem
96
+ ```sh
97
+ gem build logstash-input-qingstor.gemspec
98
+ ```
99
+ - 在Logstash的目录下使用logstash-plugin安装
100
+ ```sh
101
+ bin/logstash-plugin install /your/local/plugin/logstash-input-qingstor.gem
102
+ ```
103
+ - 安装完毕之后, 就可以使用Logstash运行开始测试了.
104
+
105
+
106
+ # Logstash Output Plugin for Qingstor
107
+
108
+ As an input plugin, it can download the log files from [Qingstor](https://www.qingcloud.com/products/storage#qingstor), and read them into logstash.
109
+ Qingstor is a remarkable object storage service provided by [Qingcloud](https://www.qingcloud.com/).
110
+
111
+ For now, We haven't submitted this to official plugin repository. If you want to have a try, please refer to the following guide to install it manually.
112
+
113
+ ## 1. Configuration Guide
114
+
115
+ #### 1.1 Run in minimal Configuration Items
116
+ ```sh
117
+ input {
118
+ qingstor {
119
+ access_key_id => 'your_access_key_id' #required
120
+ secret_access_key => 'your_secret_access_key' #required
121
+ bucket => 'bucket_name' #required
122
+ # region => "pek3a" #optional, default value "pek3a"
123
+ }
124
+ }
125
+
126
+ ```
127
+
128
+ More configuration details please refer to [code part](lib/logstash/inputs/qingstor.rb).
129
+
130
+ ## 2. Running your unpublished Plugin in Logstash
131
+
132
+ #### 2.1 Run in a local Logstash clone
133
+
134
+ - Edit Logstash `Gemfile` and add the local plugin path, for example:
135
+ ```ruby
136
+ gem "logstash-input-qingstor", :path => "/your/local/logstash-input-qingstor"
137
+ ```
138
+ - Install plugin
139
+ ```sh
140
+ bin/logstash-plugin install --no-verify
141
+ ```
142
+ - Run Logstash with your plugin
143
+ ```sh
144
+ bin/logstash -e "input {qingstor { access_key_id => 'your_access_key_id'
145
+ secret_access_key => 'your_secret_access_key'
146
+ bucket => 'bucket_name' }}"
147
+ ```
148
+ At this point any modifications to the plugin code will be applied to this local Logstash setup. After modifying the plugin, simply rerun Logstash.
149
+
150
+ #### 2.2 Run in an installed Logstash
151
+
152
+ You can use the same **2.1** method to run your plugin in an installed Logstash by editing its `Gemfile` and pointing the `:path` to your local plugin development directory or you can build the gem and install it using:
153
+
154
+ - Build your plugin gem
155
+ ```sh
156
+ gem build logstash-input-qingstor.gemspec
157
+ ```
158
+ - Install the plugin from the Logstash home
159
+ ```sh
160
+ bin/logstash-plugin install /your/local/plugin/logstash-input-qingstor.gem
161
+ ```
162
+ - Start Logstash and proceed to test the plugin
163
+
164
+ ## Contributing
165
+ Please see [Contributing Guidelines](./CONTRIBUTING.md) of this project before submitting patches.
166
+
167
+ ## LICENSE
168
+ The Apache License (Version 2.0, January 2004).
@@ -0,0 +1,262 @@
1
+ # encoding: utf-8
2
+ require "logstash/inputs/base"
3
+ require "logstash/namespace"
4
+ require "stud/interval"
5
+ require "qingstor/sdk"
6
+ require "fileutils"
7
+ require "tmpdir"
8
+
9
+ class LogStash::Inputs::Qingstor < LogStash::Inputs::Base
10
+ require "logstash/inputs/qingstor/qingstor_validator"
11
+ config_name "qingstor"
12
+
13
+ default :codec, "plain"
14
+
15
+ # The key id to access your QingStor
16
+ config :access_key_id, :validate => :string, :required => true
17
+
18
+ # The key to access your QingStor
19
+ config :secret_access_key, :validate => :string, :required => true
20
+
21
+ # The name of the qingstor bucket
22
+ config :bucket, :validate => :string, :required => true
23
+
24
+ # The region of the QingStor bucket
25
+ config :region, :validate => ["pek3a", "sh1a"], :default => "pek3a"
26
+
27
+ # If specified, it would only download the files with the specified prefix.
28
+ config :prefix, :validate => :string, :default => nil
29
+
30
+ # Set the directory where logstash store the tmp files before
31
+ # sending it to logstash, default directory in linux /tmp/logstash2qingstor
32
+ config :tmpdir, :validate => :string, :default => File.join(Dir.tmpdir, "qingstor2logstash")
33
+
34
+ # If this set to true, the remote file will be deleted after processed
35
+ config :delete_later, :validate => :boolean, :default => false
36
+
37
+ # If this set to true, the file will backup to a local dir,
38
+ # please make sure you can access to this dir.
39
+ config :local_dir, :validate => :string, :default => File.expand_path("~/")
40
+
41
+ # If specified, the file will be upload to this bucket of the given region
42
+ config :backup_bucket, :validate => :string, :default => nil
43
+
44
+ # Specified the backup region in Qingstor.
45
+ config :backup_region, :validate => ["pek3a", "sh1a"], :default => "pek3a"
46
+
47
+ # This prefix will add before backup filename.
48
+ config :backup_prefix, :validate => :string, :default => nil
49
+
50
+ # Use sincedb to record the last download time
51
+ config :sincedb_path, :validate => :string, :default => nil
52
+
53
+ # Set how frequently messages should be sent.
54
+ # The default, `10`, means send a message every 10 seconds.
55
+ config :interval, :validate => :number, :default => 10
56
+
57
+ public
58
+ def register
59
+
60
+ if !@tmpdir.nil? && !directory_valid?(@tmpdir)
61
+ raise LogStash::ConfigurationError, "Logstash must have the permissions to write to the temporary directory: #{@tmpdir}"
62
+ end
63
+
64
+ if !@local_dir.nil? && !directory_valid?(@local_dir)
65
+ raise LogStash::ConfigurationError, "Logstash must have the permissions to write to the temporary directory: #{@local_dir}"
66
+ end
67
+
68
+
69
+ @logger.info "Registering QingStor plugin", :bucket => @bucket, :region => @region
70
+
71
+ @qs_config = QingStor::SDK::Config.init @access_key_id, @secret_access_key
72
+ @qs_service = QingStor::SDK::Service.new @qs_config
73
+ @qs_bucket = @qs_service.bucket @bucket, @region
74
+
75
+ QingstorValidator.bucket_valid?(@qs_bucket)
76
+ QingstorValidator.prefix_valid?(@backup_prefix)
77
+
78
+ end # def register
79
+
80
+ def run(queue)
81
+ @logger.info "starting processing"
82
+ @current_thread = Thread.current
83
+ Stud.interval(@interval) do
84
+ process_files(queue)
85
+ end
86
+ end # def run
87
+
88
+
89
+ def process_files(queue)
90
+ objects = list_new_files
91
+
92
+ # For each record in objects, it will be download and read
93
+ # into logstash. Then it will do deletion or backup job
94
+ # according to preset flags.
95
+ objects.each do |key, time|
96
+ process_log(queue, key)
97
+ backup_to_bucket key unless @backup_bucket.nil?
98
+ backup_to_local_dir unless @local_dir.nil?
99
+ @qs_bucket.delete_object key if @delete_later
100
+ end
101
+
102
+ # if fetched nothing, just return
103
+ return if objects.empty?
104
+ _time = objects.values.max
105
+ sincedb.write(Time.at(_time))
106
+ end
107
+
108
+ private
109
+ def list_new_files
110
+ objects = {}
111
+ @logger.info "starting fetching objects"
112
+ res = @qs_bucket.list_objects({'prefix' => @prefix})
113
+ res[:keys].each do |log|
114
+ next unless is_desired?(log[:key])
115
+ next unless sincedb.newer?(log[:modified])
116
+ objects[log[:key]] = log[:modified]
117
+ @logger.info("QingStor input: Adding to object:", :key => log[:key])
118
+ end
119
+ return objects
120
+ end
121
+
122
+ def process_log(queue, key)
123
+ # a global var, for the next possible upload and copy job
124
+ @tmp_file_path = File.join(@tmpdir, File.basename(key))
125
+
126
+ File.open(@tmp_file_path, 'wb') do |logfile|
127
+ logfile.write @qs_bucket.get_object(key)[:body]
128
+ end
129
+ process_local_log(queue, @tmp_file_path)
130
+ end
131
+
132
+ def backup_to_bucket(key)
133
+ properties = {'bucket-name' => @backup_bucket, 'zone' => @backup_region}
134
+ bucket = QingStor::SDK::Bucket.new @qs_config, properties
135
+
136
+ if bucket.head[:status_code] != 200
137
+ res = bucket.put
138
+ if res[:status_code] != 201
139
+ @logger.error("ERROR : cannot create the bucket ", res[:message])
140
+ raise LogStash::ConfigurationError, "cannot create the bucket"
141
+ end
142
+ end
143
+
144
+ md5_string = Digest::MD5.file(@tmp_file_path).to_s
145
+
146
+ new_key = if backup_prefix.end_with?('/')
147
+ backup_prefix + key
148
+ else
149
+ backup_prefix + '/' + key
150
+ end
151
+
152
+ bucket.put_object new_key, {
153
+ 'content_md5' => md5_string,
154
+ 'body' => File.open(@tmp_file_path)
155
+ }
156
+ end
157
+
158
+ def backup_to_local_dir
159
+ FileUtils.mkdir_p @local_dir unless File.exist? @local_dir
160
+ FileUtils.cp @tmp_file_path, @local_dir
161
+ end
162
+
163
+ def process_local_log(queue, filename)
164
+ read_file(filename) do |line|
165
+ @codec.decode(line) do |event|
166
+ decorate(event)
167
+ queue << event
168
+ end
169
+ end
170
+ end
171
+
172
+ def read_file(filename, &block)
173
+ if gzip?(filename)
174
+ read_gzip_file(filename, block)
175
+ else
176
+ read_plain_file(filename, block)
177
+ end
178
+ end
179
+
180
+ def read_gzip_file(filename, block)
181
+ begin
182
+ Zlib::GzipReader.open(filename) do |decoder|
183
+ decoder.each_line { |line| block.call(line) }
184
+ end
185
+ rescue Zlib::Error, Zlib::GzipFile::Error => e
186
+ @logger.error("Gzip codec: Cannot uncompress the file", :filename => filename)
187
+ raise e
188
+ end
189
+ end
190
+
191
+ def read_plain_file(filename, block)
192
+ File.open(filename, 'rb') do |file|
193
+ file.each(&block)
194
+ end
195
+ end
196
+
197
+ def is_desired?(filename)
198
+ return logger?(filename) || gzip?(filename)
199
+ end
200
+
201
+ def logger?(filename)
202
+ return filename.end_with?('.log')
203
+ end
204
+
205
+ def gzip?(filename)
206
+ return filename.end_with?('.gz')
207
+ end
208
+
209
+ def sincedb
210
+ @sincedb ||= if @sincedb_path.nil?
211
+ @logger.info("Using default path for the sincedb", :filename => sincedb_file)
212
+ SinceDB::File.new(sincedb_file)
213
+ else
214
+ @logger.info("Using the provided sincedb_path")
215
+ SinceDB::File.new(@sincedb_path)
216
+ end
217
+ end
218
+
219
+ def sincedb_file
220
+ File.join(ENV["HOME"], ".sincedb_" + Digest::MD5.hexdigest("#{@bucket}+#{@prefix}"))
221
+ end
222
+
223
+ module SinceDB
224
+ class File
225
+ def initialize(file)
226
+ @sincedb_path = file
227
+ end
228
+
229
+ def newer?(date)
230
+ Time.at(date) > read
231
+ end
232
+
233
+ def read
234
+ if ::File.exist?(@sincedb_path)
235
+ content = ::File.read(@sincedb_path).chomp.strip
236
+ return content.empty? ? Time.new(0) : Time.parse(content)
237
+ else
238
+ return Time.new(0)
239
+ end
240
+ end
241
+
242
+ def write(since = nil)
243
+ since = Time.now() if since.nil?
244
+ ::File.open(@sincedb_path, 'w') { |file| file.write(since.to_s) }
245
+ end
246
+ end
247
+ end
248
+
249
+ public
250
+ def stop
251
+ Stud.stop!(@current_thread)
252
+ end
253
+
254
+ def directory_valid?(path)
255
+ begin
256
+ FileUtils.mkdir_p(path) unless Dir.exist?(path)
257
+ ::File.writable?(path)
258
+ rescue
259
+ false
260
+ end
261
+ end
262
+ end # class LogStash::Inputs::Qingstor
@@ -0,0 +1,30 @@
1
+ # encoding: utf-8
2
+ require "qingstor/sdk"
3
+ require "fileutils"
4
+
5
+ module LogStash
6
+ module Inputs
7
+ class Qingstor
8
+ class QingstorValidator
9
+
10
+ def bucket_valid?(bucket)
11
+ res = bucket.head
12
+ case res[:status_code]
13
+ when 401
14
+ raise LogStash::ConfigurationError, "Incorrect key id or access key."
15
+ when 404
16
+ raise LogStash::ConfigurationError, "Incorrect bucket/region name."
17
+ end
18
+ true
19
+ end
20
+
21
+ def prefix_valid?(prefix)
22
+ if prefix.start_with?("/") || prefix.length >= 1024
23
+ raise LogStash::ConfigurationError, "Prefix must not start with '/' with length less than 1024 "
24
+ end
25
+ true
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,27 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'logstash-input-qingstor'
3
+ s.version = '0.1.0'
4
+ s.licenses = ['Apache License (2.0)']
5
+ s.summary = 'logstash input plugin for QingStor'
6
+ s.description = 'Use this plugin to fetch file as a input of logstash from QingStor'
7
+ s.homepage = 'https://github.com/Tacinight/logstash-input-qingstor'
8
+ s.authors = ['Evan Zhao']
9
+ s.email = 'tacingiht@gmail.com'
10
+ s.require_paths = ['lib']
11
+
12
+ # Files
13
+ s.files = Dir['lib/**/*','spec/**/*','vendor/**/*','*.gemspec','*.md','CONTRIBUTORS','Gemfile','LICENSE','NOTICE.TXT']
14
+ # Tests
15
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
16
+
17
+ # Special flag to let us know this is actually a logstash plugin
18
+ s.metadata = { "logstash_plugin" => "true", "logstash_group" => "input" }
19
+
20
+ # Gem dependencies
21
+ s.add_runtime_dependency "logstash-core-plugin-api", ">=1.6", "<=2.99"
22
+ s.add_runtime_dependency 'logstash-codec-plain'
23
+ s.add_runtime_dependency 'stud', '>= 0.0.22'
24
+ s.add_runtime_dependency "qingstor-sdk", "=1.9.2"
25
+
26
+ s.add_development_dependency 'logstash-devutils'
27
+ end
@@ -0,0 +1,100 @@
1
+ 83.149.9.216 - - [04/Jan/2015:05:13:42 +0000] "GET /presentations/logstash-monitorama-2013/images/kibana-search.png HTTP/1.1" 200 203023 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
2
+ 83.149.9.216 - - [04/Jan/2015:05:13:42 +0000] "GET /presentations/logstash-monitorama-2013/images/kibana-dashboard3.png HTTP/1.1" 200 171717 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
3
+ 83.149.9.216 - - [04/Jan/2015:05:13:44 +0000] "GET /presentations/logstash-monitorama-2013/plugin/highlight/highlight.js HTTP/1.1" 200 26185 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
4
+ 83.149.9.216 - - [04/Jan/2015:05:13:44 +0000] "GET /presentations/logstash-monitorama-2013/plugin/zoom-js/zoom.js HTTP/1.1" 200 7697 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
5
+ 83.149.9.216 - - [04/Jan/2015:05:13:45 +0000] "GET /presentations/logstash-monitorama-2013/plugin/notes/notes.js HTTP/1.1" 200 2892 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
6
+ 83.149.9.216 - - [04/Jan/2015:05:13:42 +0000] "GET /presentations/logstash-monitorama-2013/images/sad-medic.png HTTP/1.1" 200 430406 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
7
+ 83.149.9.216 - - [04/Jan/2015:05:13:45 +0000] "GET /presentations/logstash-monitorama-2013/css/fonts/Roboto-Bold.ttf HTTP/1.1" 200 38720 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
8
+ 83.149.9.216 - - [04/Jan/2015:05:13:45 +0000] "GET /presentations/logstash-monitorama-2013/css/fonts/Roboto-Regular.ttf HTTP/1.1" 200 41820 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
9
+ 83.149.9.216 - - [04/Jan/2015:05:13:45 +0000] "GET /presentations/logstash-monitorama-2013/images/frontend-response-codes.png HTTP/1.1" 200 52878 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
10
+ 83.149.9.216 - - [04/Jan/2015:05:13:43 +0000] "GET /presentations/logstash-monitorama-2013/images/kibana-dashboard.png HTTP/1.1" 200 321631 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
11
+ 83.149.9.216 - - [04/Jan/2015:05:13:46 +0000] "GET /presentations/logstash-monitorama-2013/images/Dreamhost_logo.svg HTTP/1.1" 200 2126 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
12
+ 83.149.9.216 - - [04/Jan/2015:05:13:43 +0000] "GET /presentations/logstash-monitorama-2013/images/kibana-dashboard2.png HTTP/1.1" 200 394967 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
13
+ 83.149.9.216 - - [04/Jan/2015:05:13:46 +0000] "GET /presentations/logstash-monitorama-2013/images/apache-icon.gif HTTP/1.1" 200 8095 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
14
+ 83.149.9.216 - - [04/Jan/2015:05:13:46 +0000] "GET /presentations/logstash-monitorama-2013/images/nagios-sms5.png HTTP/1.1" 200 78075 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
15
+ 83.149.9.216 - - [04/Jan/2015:05:13:46 +0000] "GET /presentations/logstash-monitorama-2013/images/redis.png HTTP/1.1" 200 25230 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
16
+ 83.149.9.216 - - [04/Jan/2015:05:13:47 +0000] "GET /presentations/logstash-monitorama-2013/images/elasticsearch.png HTTP/1.1" 200 8026 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
17
+ 83.149.9.216 - - [04/Jan/2015:05:13:47 +0000] "GET /presentations/logstash-monitorama-2013/images/logstashbook.png HTTP/1.1" 200 54662 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
18
+ 83.149.9.216 - - [04/Jan/2015:05:13:47 +0000] "GET /presentations/logstash-monitorama-2013/images/github-contributions.png HTTP/1.1" 200 34245 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
19
+ 83.149.9.216 - - [04/Jan/2015:05:13:47 +0000] "GET /presentations/logstash-monitorama-2013/css/print/paper.css HTTP/1.1" 200 4254 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
20
+ 83.149.9.216 - - [04/Jan/2015:05:13:47 +0000] "GET /presentations/logstash-monitorama-2013/images/1983_delorean_dmc-12-pic-38289.jpeg HTTP/1.1" 200 220562 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
21
+ 83.149.9.216 - - [04/Jan/2015:05:13:46 +0000] "GET /presentations/logstash-monitorama-2013/images/simple-inputs-filters-outputs.jpg HTTP/1.1" 200 1168622 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
22
+ 83.149.9.216 - - [04/Jan/2015:05:13:46 +0000] "GET /presentations/logstash-monitorama-2013/images/tiered-outputs-to-inputs.jpg HTTP/1.1" 200 1079983 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
23
+ 83.149.9.216 - - [04/Jan/2015:05:13:53 +0000] "GET /favicon.ico HTTP/1.1" 200 3638 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
24
+ 24.236.252.67 - - [04/Jan/2015:05:14:10 +0000] "GET /favicon.ico HTTP/1.1" 200 3638 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:26.0) Gecko/20100101 Firefox/26.0"
25
+ 93.114.45.13 - - [04/Jan/2015:05:14:32 +0000] "GET /articles/dynamic-dns-with-dhcp/ HTTP/1.1" 200 18848 "http://www.google.ro/url?sa=t&rct=j&q=&esrc=s&source=web&cd=2&ved=0CCwQFjAB&url=http%3A%2F%2Fwww.semicomplete.com%2Farticles%2Fdynamic-dns-with-dhcp%2F&ei=W88AU4n9HOq60QXbv4GwBg&usg=AFQjCNEF1X4Rs52UYQyLiySTQxa97ozM4g&bvm=bv.61535280,d.d2k" "Mozilla/5.0 (X11; Linux x86_64; rv:25.0) Gecko/20100101 Firefox/25.0"
26
+ 93.114.45.13 - - [04/Jan/2015:05:14:32 +0000] "GET /reset.css HTTP/1.1" 200 1015 "http://www.semicomplete.com/articles/dynamic-dns-with-dhcp/" "Mozilla/5.0 (X11; Linux x86_64; rv:25.0) Gecko/20100101 Firefox/25.0"
27
+ 93.114.45.13 - - [04/Jan/2015:05:14:33 +0000] "GET /style2.css HTTP/1.1" 200 4877 "http://www.semicomplete.com/articles/dynamic-dns-with-dhcp/" "Mozilla/5.0 (X11; Linux x86_64; rv:25.0) Gecko/20100101 Firefox/25.0"
28
+ 93.114.45.13 - - [04/Jan/2015:05:14:33 +0000] "GET /favicon.ico HTTP/1.1" 200 3638 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:25.0) Gecko/20100101 Firefox/25.0"
29
+ 93.114.45.13 - - [04/Jan/2015:05:14:33 +0000] "GET /images/jordan-80.png HTTP/1.1" 200 6146 "http://www.semicomplete.com/articles/dynamic-dns-with-dhcp/" "Mozilla/5.0 (X11; Linux x86_64; rv:25.0) Gecko/20100101 Firefox/25.0"
30
+ 93.114.45.13 - - [04/Jan/2015:05:14:33 +0000] "GET /images/web/2009/banner.png HTTP/1.1" 200 52315 "http://www.semicomplete.com/style2.css" "Mozilla/5.0 (X11; Linux x86_64; rv:25.0) Gecko/20100101 Firefox/25.0"
31
+ 66.249.73.135 - - [04/Jan/2015:05:15:03 +0000] "GET /blog/tags/ipv6 HTTP/1.1" 200 12251 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
32
+ 50.16.19.13 - - [04/Jan/2015:05:15:15 +0000] "GET /blog/tags/puppet?flav=rss20 HTTP/1.1" 200 14872 "http://www.semicomplete.com/blog/tags/puppet?flav=rss20" "Tiny Tiny RSS/1.11 (http://tt-rss.org/)"
33
+ 66.249.73.185 - - [04/Jan/2015:05:15:23 +0000] "GET / HTTP/1.1" 200 37932 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
34
+ 110.136.166.128 - - [04/Jan/2015:05:16:11 +0000] "GET /projects/xdotool/ HTTP/1.1" 200 12292 "http://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=5&cad=rja&sqi=2&ved=0CFYQFjAE&url=http%3A%2F%2Fwww.semicomplete.com%2Fprojects%2Fxdotool%2F&ei=6cwAU_bRHo6urAeI0YD4Ag&usg=AFQjCNE3V_aCf3-gfNcbS924S6jZ6FqffA&bvm=bv.61535280,d.bmk" "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0"
35
+ 46.105.14.53 - - [04/Jan/2015:05:16:17 +0000] "GET /blog/tags/puppet?flav=rss20 HTTP/1.1" 200 14872 "-" "UniversalFeedParser/4.2-pre-314-svn +http://feedparser.org/"
36
+ 110.136.166.128 - - [04/Jan/2015:05:16:22 +0000] "GET /reset.css HTTP/1.1" 200 1015 "http://www.semicomplete.com/projects/xdotool/" "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0"
37
+ 110.136.166.128 - - [04/Jan/2015:05:16:22 +0000] "GET /style2.css HTTP/1.1" 200 4877 "http://www.semicomplete.com/projects/xdotool/" "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0"
38
+ 110.136.166.128 - - [04/Jan/2015:05:16:22 +0000] "GET /favicon.ico HTTP/1.1" 200 3638 "-" "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0"
39
+ 110.136.166.128 - - [04/Jan/2015:05:16:22 +0000] "GET /images/jordan-80.png HTTP/1.1" 200 6146 "http://www.semicomplete.com/projects/xdotool/" "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0"
40
+ 123.125.71.35 - - [04/Jan/2015:05:16:31 +0000] "GET /blog/tags/release HTTP/1.1" 200 40693 "-" "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)"
41
+ 110.136.166.128 - - [04/Jan/2015:05:16:22 +0000] "GET /images/web/2009/banner.png HTTP/1.1" 200 52315 "http://www.semicomplete.com/style2.css" "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0"
42
+ 50.150.204.184 - - [04/Jan/2015:05:17:06 +0000] "GET /images/googledotcom.png HTTP/1.1" 200 65748 "http://www.google.com/search?q=https//:google.com&source=lnms&tbm=isch&sa=X&ei=4-r8UvDrKZOgkQe7x4CICw&ved=0CAkQ_AUoAA&biw=320&bih=441" "Mozilla/5.0 (Linux; U; Android 4.0.4; en-us; LG-MS770 Build/IMM76I) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30"
43
+ 207.241.237.225 - - [04/Jan/2015:05:17:35 +0000] "GET /blog/tags/examples HTTP/1.0" 200 9208 "http://www.semicomplete.com/blog/tags/C" "Mozilla/5.0 (compatible; archive.org_bot +http://www.archive.org/details/archive.org_bot)"
44
+ 200.49.190.101 - - [04/Jan/2015:05:17:39 +0000] "GET /reset.css HTTP/1.1" 200 1015 "-" "-"
45
+ 200.49.190.100 - - [04/Jan/2015:05:17:37 +0000] "GET /blog/tags/web HTTP/1.1" 200 44019 "-" "QS304 Profile/MIDP-2.0 Configuration/CLDC-1.1"
46
+ 200.49.190.101 - - [04/Jan/2015:05:17:41 +0000] "GET /style2.css HTTP/1.1" 200 4877 "-" "-"
47
+ 200.49.190.101 - - [04/Jan/2015:05:17:48 +0000] "GET /images/jordan-80.png HTTP/1.1" 200 6146 "-" "QS304 Profile/MIDP-2.0 Configuration/CLDC-1.1"
48
+ 66.249.73.185 - - [04/Jan/2015:05:18:48 +0000] "GET /reset.css HTTP/1.1" 200 1015 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
49
+ 66.249.73.135 - - [04/Jan/2015:05:18:55 +0000] "GET /blog/tags/munin HTTP/1.1" 200 9746 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
50
+ 66.249.73.135 - - [04/Jan/2015:05:19:16 +0000] "GET /blog/tags/firefox?flav=rss20 HTTP/1.1" 200 16021 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
51
+ 66.249.73.135 - - [04/Jan/2015:05:20:03 +0000] "GET /blog/geekery/eventdb-ideas.html HTTP/1.1" 200 11418 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
52
+ 67.214.178.190 - - [04/Jan/2015:05:20:48 +0000] "GET / HTTP/1.0" 200 37932 "http://www.semicomplete.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:21.0) Gecko/20100101 Firefox/21.0"
53
+ 67.214.178.190 - - [04/Jan/2015:05:20:59 +0000] "GET /blog/geekery/installing-windows-8-consumer-preview.html HTTP/1.0" 200 8948 "http://www.semicomplete.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:21.0) Gecko/20100101 Firefox/21.0"
54
+ 207.241.237.220 - - [04/Jan/2015:05:21:16 +0000] "GET /blog/tags/projects HTTP/1.0" 200 28370 "http://www.semicomplete.com/blog/tags/C" "Mozilla/5.0 (compatible; archive.org_bot +http://www.archive.org/details/archive.org_bot)"
55
+ 46.105.14.53 - - [04/Jan/2015:05:21:17 +0000] "GET /blog/tags/puppet?flav=rss20 HTTP/1.1" 200 14872 "-" "UniversalFeedParser/4.2-pre-314-svn +http://feedparser.org/"
56
+ 207.241.237.227 - - [04/Jan/2015:05:21:19 +0000] "GET /blog/geekery/soekris-gpio.html HTTP/1.0" 200 9587 "http://www.semicomplete.com/blog/tags/C" "Mozilla/5.0 (compatible; archive.org_bot +http://www.archive.org/details/archive.org_bot)"
57
+ 91.177.205.119 - - [04/Jan/2015:05:22:03 +0000] "GET /blog/geekery/xvfb-firefox.html HTTP/1.1" 200 10975 "http://en.wikipedia.org/wiki/Xvfb" "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
58
+ 91.177.205.119 - - [04/Jan/2015:05:22:03 +0000] "GET /reset.css HTTP/1.1" 200 1015 "http://semicomplete.com/blog/geekery/xvfb-firefox.html" "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
59
+ 91.177.205.119 - - [04/Jan/2015:05:22:03 +0000] "GET /style2.css HTTP/1.1" 200 4877 "http://semicomplete.com/blog/geekery/xvfb-firefox.html" "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
60
+ 91.177.205.119 - - [04/Jan/2015:05:22:03 +0000] "GET /images/jordan-80.png HTTP/1.1" 200 6146 "http://semicomplete.com/blog/geekery/xvfb-firefox.html" "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
61
+ 91.177.205.119 - - [04/Jan/2015:05:22:03 +0000] "GET /images/web/2009/banner.png HTTP/1.1" 200 52315 "http://semicomplete.com/blog/geekery/xvfb-firefox.html" "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
62
+ 91.177.205.119 - - [04/Jan/2015:05:22:04 +0000] "GET /favicon.ico HTTP/1.1" 200 3638 "-" "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Win64; x64; Trident/6.0)"
63
+ 66.249.73.185 - - [04/Jan/2015:05:22:13 +0000] "GET /doc/index.html?org/elasticsearch/action/search/SearchResponse.html HTTP/1.1" 404 294 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
64
+ 207.241.237.228 - - [04/Jan/2015:05:22:23 +0000] "GET /blog/tags/defcon HTTP/1.0" 200 24142 "http://www.semicomplete.com/blog/tags/C" "Mozilla/5.0 (compatible; archive.org_bot +http://www.archive.org/details/archive.org_bot)"
65
+ 207.241.237.101 - - [04/Jan/2015:05:22:27 +0000] "GET /blog/tags/regex HTTP/1.0" 200 14888 "http://www.semicomplete.com/blog/tags/C" "Mozilla/5.0 (compatible; archive.org_bot +http://www.archive.org/details/archive.org_bot)"
66
+ 87.169.99.232 - - [04/Jan/2015:05:23:41 +0000] "GET /presentations/puppet-at-loggly/puppet-at-loggly.pdf.html HTTP/1.1" 200 24747 "https://www.google.de/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36"
67
+ 209.85.238.199 - - [04/Jan/2015:05:23:47 +0000] "GET /blog/tags/firefox?flav=rss20 HTTP/1.1" 200 16021 "-" "Feedfetcher-Google; (+http://www.google.com/feedfetcher.html; 3 subscribers; feed-id=14171215010336145331)"
68
+ 209.85.238.199 - - [04/Jan/2015:05:24:00 +0000] "GET /test.xml HTTP/1.1" 200 1370 "-" "Feedfetcher-Google; (+http://www.google.com/feedfetcher.html; 1 subscribers; feed-id=11390274670024826467)"
69
+ 81.220.24.207 - - [04/Jan/2015:05:24:57 +0000] "GET /blog/geekery/ssl-latency.html HTTP/1.1" 200 17147 "http://www.google.fr/url?sa=t&rct=j&q=&esrc=s&source=web&cd=5&ved=0CE4QFjAE&url=http%3A%2F%2Fwww.semicomplete.com%2Fblog%2Fgeekery%2Fssl-latency.html&ei=ZdEAU9mGGuWX1AW09IDoBw&usg=AFQjCNHw6zioJpizqX8Q0YpKKaF4zdCSEg&bvm=bv.61535280,d.d2k" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.73.11 (KHTML, like Gecko) Version/7.0.1 Safari/537.73.11"
70
+ 81.220.24.207 - - [04/Jan/2015:05:24:57 +0000] "GET /reset.css HTTP/1.1" 200 1015 "http://www.semicomplete.com/blog/geekery/ssl-latency.html" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.73.11 (KHTML, like Gecko) Version/7.0.1 Safari/537.73.11"
71
+ 81.220.24.207 - - [04/Jan/2015:05:24:57 +0000] "GET /images/jordan-80.png HTTP/1.1" 200 6146 "http://www.semicomplete.com/blog/geekery/ssl-latency.html" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.73.11 (KHTML, like Gecko) Version/7.0.1 Safari/537.73.11"
72
+ 81.220.24.207 - - [04/Jan/2015:05:24:57 +0000] "GET /style2.css HTTP/1.1" 200 4877 "http://www.semicomplete.com/blog/geekery/ssl-latency.html" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.73.11 (KHTML, like Gecko) Version/7.0.1 Safari/537.73.11"
73
+ 81.220.24.207 - - [04/Jan/2015:05:24:57 +0000] "GET /images/web/2009/banner.png HTTP/1.1" 200 52315 "http://www.semicomplete.com/blog/geekery/ssl-latency.html" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.73.11 (KHTML, like Gecko) Version/7.0.1 Safari/537.73.11"
74
+ 81.220.24.207 - - [04/Jan/2015:05:24:58 +0000] "GET /favicon.ico HTTP/1.1" 200 3638 "http://www.semicomplete.com/blog/geekery/ssl-latency.html" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.73.11 (KHTML, like Gecko) Version/7.0.1 Safari/537.73.11"
75
+ 66.249.73.135 - - [04/Jan/2015:05:25:05 +0000] "GET /blog/geekery/vmware-cpu-performance.html HTTP/1.1" 200 12908 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
76
+ 46.105.14.53 - - [04/Jan/2015:05:26:17 +0000] "GET /blog/tags/puppet?flav=rss20 HTTP/1.1" 200 14872 "-" "UniversalFeedParser/4.2-pre-314-svn +http://feedparser.org/"
77
+ 218.30.103.62 - - [04/Jan/2015:05:27:05 +0000] "GET /robots.txt HTTP/1.1" 200 - "-" "Sogou web spider/4.0(+http://www.sogou.com/docs/help/webmasters.htm#07)"
78
+ 218.30.103.62 - - [04/Jan/2015:05:27:10 +0000] "GET /robots.txt HTTP/1.1" 200 - "-" "Sogou web spider/4.0(+http://www.sogou.com/docs/help/webmasters.htm#07)"
79
+ 218.30.103.62 - - [04/Jan/2015:05:27:15 +0000] "GET /projects/fex/ HTTP/1.1" 200 14352 "-" "Sogou web spider/4.0(+http://www.sogou.com/docs/help/webmasters.htm#07)"
80
+ 74.125.40.20 - - [04/Jan/2015:05:27:22 +0000] "GET /?flav=rss20 HTTP/1.1" 200 29941 "-" "FeedBurner/1.0 (http://www.FeedBurner.com)"
81
+ 71.212.224.97 - - [04/Jan/2015:05:27:34 +0000] "GET /projects/xdotool/ HTTP/1.1" 200 12292 "http://suckless.org/rocks" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36"
82
+ 71.212.224.97 - - [04/Jan/2015:05:27:34 +0000] "GET /reset.css HTTP/1.1" 200 1015 "http://www.semicomplete.com/projects/xdotool/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36"
83
+ 71.212.224.97 - - [04/Jan/2015:05:27:35 +0000] "GET /style2.css HTTP/1.1" 200 4877 "http://www.semicomplete.com/projects/xdotool/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36"
84
+ 71.212.224.97 - - [04/Jan/2015:05:27:35 +0000] "GET /images/jordan-80.png HTTP/1.1" 200 6146 "http://www.semicomplete.com/projects/xdotool/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36"
85
+ 71.212.224.97 - - [04/Jan/2015:05:27:35 +0000] "GET /images/web/2009/banner.png HTTP/1.1" 200 52315 "http://www.semicomplete.com/projects/xdotool/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36"
86
+ 218.30.103.62 - - [04/Jan/2015:05:27:36 +0000] "GET /projects/xdotool/xdotool.xhtml HTTP/1.1" 304 - "-" "Sogou web spider/4.0(+http://www.sogou.com/docs/help/webmasters.htm#07)"
87
+ 108.174.55.234 - - [04/Jan/2015:05:27:45 +0000] "GET /?flav=rss20 HTTP/1.1" 200 29941 "-" "-"
88
+ 218.30.103.62 - - [04/Jan/2015:05:27:57 +0000] "GET /blog/geekery/c-vs-python-bdb.html HTTP/1.1" 200 11388 "-" "Sogou web spider/4.0(+http://www.sogou.com/docs/help/webmasters.htm#07)"
89
+ 121.107.188.202 - - [04/Jan/2015:05:27:57 +0000] "GET /presentations/logstash-monitorama-2013/images/kibana-dashboard3.png HTTP/1.1" 200 171717 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36"
90
+ 218.30.103.62 - - [04/Jan/2015:05:28:21 +0000] "GET /blog/productivity/better-zsh-xterm-title-fix.html HTTP/1.1" 200 10185 "-" "Sogou web spider/4.0(+http://www.sogou.com/docs/help/webmasters.htm#07)"
91
+ 218.30.103.62 - - [04/Jan/2015:05:28:43 +0000] "GET /blog/geekery/xvfb-firefox.html HTTP/1.1" 200 10975 "-" "Sogou web spider/4.0(+http://www.sogou.com/docs/help/webmasters.htm#07)"
92
+ 218.30.103.62 - - [04/Jan/2015:05:29:06 +0000] "GET /blog/geekery/puppet-facts-into-mcollective.html HTTP/1.1" 200 9872 "-" "Sogou web spider/4.0(+http://www.sogou.com/docs/help/webmasters.htm#07)"
93
+ 198.46.149.143 - - [04/Jan/2015:05:29:13 +0000] "GET /blog/geekery/disabling-battery-in-ubuntu-vms.html?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+semicomplete%2Fmain+%28semicomplete.com+-+Jordan+Sissel%29 HTTP/1.1" 200 9316 "-" "Tiny Tiny RSS/1.11 (http://tt-rss.org/)"
94
+ 198.46.149.143 - - [04/Jan/2015:05:29:13 +0000] "GET /blog/geekery/solving-good-or-bad-problems.html?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+semicomplete%2Fmain+%28semicomplete.com+-+Jordan+Sissel%29 HTTP/1.1" 200 10756 "-" "Tiny Tiny RSS/1.11 (http://tt-rss.org/)"
95
+ 218.30.103.62 - - [04/Jan/2015:05:29:26 +0000] "GET /blog/geekery/jquery-interface-puffer.html%20target= HTTP/1.1" 200 202 "-" "Sogou web spider/4.0(+http://www.sogou.com/docs/help/webmasters.htm#07)"
96
+ 218.30.103.62 - - [04/Jan/2015:05:29:48 +0000] "GET /blog/geekery/ec2-reserved-vs-ondemand.html HTTP/1.1" 200 11834 "-" "Sogou web spider/4.0(+http://www.sogou.com/docs/help/webmasters.htm#07)"
97
+ 66.249.73.135 - - [04/Jan/2015:05:30:06 +0000] "GET /blog/web/firefox-scrolling-fix.html HTTP/1.1" 200 8956 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
98
+ 86.1.76.62 - - [04/Jan/2015:05:30:37 +0000] "GET /projects/xdotool/ HTTP/1.1" 200 12292 "http://www.haskell.org/haskellwiki/Xmonad/Frequently_asked_questions" "Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20140205 Firefox/24.0 Iceweasel/24.3.0"
99
+ 86.1.76.62 - - [04/Jan/2015:05:30:37 +0000] "GET /reset.css HTTP/1.1" 200 1015 "http://www.semicomplete.com/projects/xdotool/" "Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20140205 Firefox/24.0 Iceweasel/24.3.0"
100
+ 86.1.76.62 - - [04/Jan/2015:05:30:37 +0000] "GET /style2.css HTTP/1.1" 200 4877 "http://www.semicomplete.com/projects/xdotool/" "Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20140205 Firefox/24.0 Iceweasel/24.3.0"
Binary file
@@ -0,0 +1,58 @@
1
+ # encoding: utf-8
2
+ require "logstash/devutils/rspec/spec_helper"
3
+ require "logstash/inputs/qingstor"
4
+ require_relative "./qs_access_helper"
5
+ require "tmpdir"
6
+
7
+ describe LogStash::Inputs::Qingstor do
8
+
9
+ before do
10
+ Thread.abort_on_exception = true
11
+
12
+ upload_file("../fixtures/logstash.log", "log3.log")
13
+ upload_file("../fixtures/logstash.log.gz", "log3.log.gz")
14
+ end
15
+
16
+ after do
17
+ delete_remote_file "log3.log"
18
+ delete_remote_file "log3.log.gz"
19
+ end
20
+
21
+ let(:config) { {
22
+ "access_key_id" => ENV['access_key_id'],
23
+ "secret_access_key" => ENV['secret_access_key'],
24
+ "bucket" => ENV['bucket'],
25
+ "region" => ENV['region']
26
+ } }
27
+ let(:key1) { "log3.log" }
28
+ let(:key2) { "log3.log.gz" }
29
+ let(:backup) { "logstash-backup" }
30
+ let(:local_backup_dir) { File.join(Dir.tmpdir, backup) }
31
+
32
+ context "local backup" do
33
+ it "backup to local dir" do
34
+ fetch_events(config.merge({"local_dir" => local_backup_dir }))
35
+ expect(File.exists?(File.join(local_backup_dir, key1))).to be_truthy
36
+ expect(File.exists?(File.join(local_backup_dir, key2))).to be_truthy
37
+ end
38
+
39
+ after do
40
+ FileUtils.rm_r(File.join(local_backup_dir, key1))
41
+ FileUtils.rm_r(File.join(local_backup_dir, key2))
42
+ end
43
+ end
44
+
45
+ context "remote backup" do
46
+ it "backup to another bucket" do
47
+ fetch_events(config.merge({"backup_bucket" => backup}))
48
+ expect(list_remote_file(backup).size).to eq(2)
49
+ end
50
+
51
+ after do
52
+ delete_bucket(backup)
53
+ end
54
+ end
55
+
56
+ context ""
57
+
58
+ end
@@ -0,0 +1,37 @@
1
+ # encoding: utf-8
2
+ require "logstash/devutils/rspec/spec_helper"
3
+ require "logstash/inputs/qingstor"
4
+
5
+ describe LogStash::Inputs::Qingstor do
6
+ let(:config) { {
7
+ "access_key_id" => ENV['access_key_id'],
8
+ "secret_access_key" => ENV['secret_access_key'],
9
+ "bucket" => ENV['bucket'],
10
+ "region" => ENV['region']
11
+ } }
12
+
13
+ it "raise error if it has incorrect key id or access key" do
14
+ config["access_key_id"] = "wrongid"
15
+ expect{ described_class.new(config).register }.to raise_error(LogStash::ConfigurationError)
16
+ end
17
+
18
+ it "raise error if it has incorrect key id or access key" do
19
+ config["secret_access_key"] = "wrongaccesskey"
20
+ expect{ described_class.new(config).register }.to raise_error(LogStash::ConfigurationError)
21
+ end
22
+
23
+ it "raise error if it has incorrect bucket/region name" do
24
+ config["bucket"] = "wrongbucket"
25
+ expect{ described_class.new(config).register }.to raise_error(LogStash::ConfigurationError)
26
+ end
27
+
28
+ it "raise error if it has incorrect bucket/region name" do
29
+ config["region"] = "wrongregion"
30
+ expect{ described_class.new(config).register }.to raise_error(LogStash::ConfigurationError)
31
+ end
32
+
33
+ it "use default region if it is not set" do
34
+ config.delete("region")
35
+ expect(described_class.new(config).register ).to be_truthy
36
+ end
37
+ end
@@ -0,0 +1,43 @@
1
+ def fetch_events(settings)
2
+ queue = []
3
+ qs = LogStash::Inputs::Qingstor.new(settings)
4
+ qs.register
5
+ qs.process_files(queue)
6
+ queue
7
+ end
8
+
9
+ def qs_init_config(access_key_id = ENV['access_key_id'],
10
+ secret_access_key = ENV['secret_access_key'])
11
+ return QingStor::SDK::Config.init access_key_id, secret_access_key
12
+ end
13
+
14
+ def qs_init_bucket(bucket = ENV['bucket'], region = ENV['region'])
15
+ config = qs_init_config
16
+ properties = {'bucket-name' => bucket, 'zone' => region }
17
+ return QingStor::SDK::Bucket.new(config, properties)
18
+ end
19
+
20
+ def upload_file(local_file, remote_file)
21
+ bucket = qs_init_bucket
22
+ file = File.expand_path(File.join(File.dirname(__FILE__), local_file))
23
+ md5_string = Digest::MD5.file(file).to_s
24
+ bucket.put_object remote_file, {
25
+ 'content_md5' => md5_string,
26
+ 'body' => File.open(file)
27
+ }
28
+ end
29
+
30
+ def delete_remote_file(key)
31
+ bucket = qs_init_bucket
32
+ bucket.delete_object key
33
+ end
34
+
35
+ def list_remote_file(bucket = ENV['bucket'], region = ENV['region'])
36
+ bucket = qs_init_bucket(bucket, region)
37
+ return bucket.list_objects[:keys]
38
+ end
39
+
40
+ def delete_bucket(bucket)
41
+ bucket = qs_init_bucket(bucket)
42
+ bucket.delete
43
+ end
metadata ADDED
@@ -0,0 +1,142 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: logstash-input-qingstor
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Evan Zhao
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-03-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '1.6'
19
+ - - "<="
20
+ - !ruby/object:Gem::Version
21
+ version: '2.99'
22
+ name: logstash-core-plugin-api
23
+ prerelease: false
24
+ type: :runtime
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '1.6'
30
+ - - "<="
31
+ - !ruby/object:Gem::Version
32
+ version: '2.99'
33
+ - !ruby/object:Gem::Dependency
34
+ requirement: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ name: logstash-codec-plain
40
+ prerelease: false
41
+ type: :runtime
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ - !ruby/object:Gem::Dependency
48
+ requirement: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 0.0.22
53
+ name: stud
54
+ prerelease: false
55
+ type: :runtime
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: 0.0.22
61
+ - !ruby/object:Gem::Dependency
62
+ requirement: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - '='
65
+ - !ruby/object:Gem::Version
66
+ version: 1.9.2
67
+ name: qingstor-sdk
68
+ prerelease: false
69
+ type: :runtime
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - '='
73
+ - !ruby/object:Gem::Version
74
+ version: 1.9.2
75
+ - !ruby/object:Gem::Dependency
76
+ requirement: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ name: logstash-devutils
82
+ prerelease: false
83
+ type: :development
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ description: Use this plugin to fetch file as a input of logstash from QingStor
90
+ email: tacingiht@gmail.com
91
+ executables: []
92
+ extensions: []
93
+ extra_rdoc_files: []
94
+ files:
95
+ - CHANGELOG.md
96
+ - CODE_OF_CONDUCT.md
97
+ - CONTRIBUTING.md
98
+ - CONTRIBUTORS
99
+ - DEVELOPER.md
100
+ - Gemfile
101
+ - LICENSE
102
+ - README.md
103
+ - lib/logstash/inputs/qingstor.rb
104
+ - lib/logstash/inputs/qingstor/qingstor_validator.rb
105
+ - logstash-input-qingstor.gemspec
106
+ - spec/fixtures/logstash.log
107
+ - spec/fixtures/logstash.log.gz
108
+ - spec/inputs/qingstor_spec.rb
109
+ - spec/inputs/qingstor_spec_validator_spec.rb
110
+ - spec/inputs/qs_access_helper.rb
111
+ homepage: https://github.com/Tacinight/logstash-input-qingstor
112
+ licenses:
113
+ - Apache License (2.0)
114
+ metadata:
115
+ logstash_plugin: 'true'
116
+ logstash_group: input
117
+ post_install_message:
118
+ rdoc_options: []
119
+ require_paths:
120
+ - lib
121
+ required_ruby_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ required_rubygems_version: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ requirements: []
132
+ rubyforge_project:
133
+ rubygems_version: 2.4.8
134
+ signing_key:
135
+ specification_version: 4
136
+ summary: logstash input plugin for QingStor
137
+ test_files:
138
+ - spec/fixtures/logstash.log
139
+ - spec/fixtures/logstash.log.gz
140
+ - spec/inputs/qingstor_spec.rb
141
+ - spec/inputs/qingstor_spec_validator_spec.rb
142
+ - spec/inputs/qs_access_helper.rb