logstash-output-monasca_log_api 0.3.3
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 +7 -0
- data/Gemfile +2 -0
- data/LICENSE +11 -0
- data/README.md +167 -0
- data/lib/logstash/outputs/helper/url_helper.rb +28 -0
- data/lib/logstash/outputs/keystone/keystone_client.rb +69 -0
- data/lib/logstash/outputs/keystone/token.rb +31 -0
- data/lib/logstash/outputs/monasca/monasca_log_api_client.rb +78 -0
- data/lib/logstash/outputs/monasca_log_api.rb +134 -0
- data/logstash-output-monasca_log_api.gemspec +29 -0
- data/spec/outputs/helper/url_helper_spec.rb +34 -0
- data/spec/outputs/keystone/keystone_client_spec.rb +81 -0
- data/spec/outputs/keystone/token_spec.rb +38 -0
- data/spec/outputs/monasca/monasca_api_client_spec.rb +105 -0
- data/spec/outputs/monasca_api_spec.rb +131 -0
- data/spec/outputs/spec_helper.rb +32 -0
- metadata +164 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 8a31e2b41940d7b7dec5eb88250d4bc27ce01e54
|
|
4
|
+
data.tar.gz: 71eecb218d00a0b32f762202d34d52f7bfc93a89
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 95ec1d08625205ed811036c5b7eb142d3970901a693dc5c8455a1e41a7a1c799e4eefdb602a91e73fdbedf1864514229a040361156431f01d088254f5eaa07ce
|
|
7
|
+
data.tar.gz: ab6ab077a31d5587cf8eae2063f1a05a6d7349d3ed179a912879119407947c6c94cba9827ba38a09f189f78065f043d60750ab48dc4a11d925fb45d801f2d28d
|
data/Gemfile
ADDED
data/LICENSE
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Copyright 2015 FUJITSU LIMITED
|
|
2
|
+
|
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
|
4
|
+
in compliance with the License. You may obtain a copy of the License at
|
|
5
|
+
|
|
6
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
|
|
8
|
+
Unless required by applicable law or agreed to in writing, software distributed under the License
|
|
9
|
+
is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
|
10
|
+
or implied. See the License for the specific language governing permissions and limitations under
|
|
11
|
+
the License.
|
data/README.md
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# Logstash Output Monasca-Log-Api Plugin
|
|
2
|
+
|
|
3
|
+
## Build from source
|
|
4
|
+
|
|
5
|
+
### Requirements
|
|
6
|
+
|
|
7
|
+
* JRuby (I recommend to use Ruby Version Manager (RVM) How to install? -> https://rvm.io/rvm/install)
|
|
8
|
+
* JDK
|
|
9
|
+
* Git
|
|
10
|
+
* bundler
|
|
11
|
+
|
|
12
|
+
### How to install the requirements
|
|
13
|
+
|
|
14
|
+
#### Ubuntu 14.04
|
|
15
|
+
|
|
16
|
+
##### RVM
|
|
17
|
+
```bash
|
|
18
|
+
gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
|
|
19
|
+
\curl -sSL https://get.rvm.io | bash
|
|
20
|
+
source /home/vagrant/.rvm/scripts/rvm
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
#### Git
|
|
24
|
+
```bash
|
|
25
|
+
sudo apt-get install git
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
#### JDK
|
|
29
|
+
```bash
|
|
30
|
+
sudo apt-get install default-jdk
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
#### JRuby
|
|
34
|
+
```bash
|
|
35
|
+
rvm install jruby
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Clone project
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
git clone https://github.com/FujitsuEnablingSoftwareTechnologyGmbH/logstash-output-monasca_api.git
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Use rvm jruby
|
|
45
|
+
```bash
|
|
46
|
+
rvm use jruby
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Install bundler
|
|
50
|
+
```bash
|
|
51
|
+
gem install bundler
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Fetch dependencies
|
|
55
|
+
```bash
|
|
56
|
+
bundle install
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Unit tests
|
|
60
|
+
|
|
61
|
+
### Run unit tests with:
|
|
62
|
+
```bash
|
|
63
|
+
bundle exec rspec
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Run specified test
|
|
67
|
+
```bash
|
|
68
|
+
bundle exec rspec spec/outputs/monasca/monasca_log_api_client_spec.rb
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Run coverage
|
|
72
|
+
```bash
|
|
73
|
+
JRUBY_OPTS="-Xcli.debug=true --debug" bundle exec rspec
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Coverage report can be found in ./coverage
|
|
77
|
+
|
|
78
|
+
## Deploy Plugin to logstash
|
|
79
|
+
|
|
80
|
+
### Build Gemfile
|
|
81
|
+
First we need to create a Gemfile.
|
|
82
|
+
|
|
83
|
+
What is a Gemfile? Gems are packages for the Ruby programming language. A Gemfile defines all dependencies which are neccessary to build the product.
|
|
84
|
+
|
|
85
|
+
How to build a Gemfile? Run this:
|
|
86
|
+
```bash
|
|
87
|
+
gem build logstash-output-monasca_log_api.gemspec
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Deploy Gemfile to logstash
|
|
91
|
+
|
|
92
|
+
* [Download logstash](http://download.elastic.co/logstash/logstash/logstash-1.5.0.tar.gz) (>=1.5.0)
|
|
93
|
+
* Extract logstash and navigate into the folder
|
|
94
|
+
* Add this line to the Gemfile
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
gem "logstash-output-monasca_log_api", :path => "/vagrant_home/cloudmonitor/logstash-output-monasca_log_api"
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
* __logstash-output-monasca_log_api__ = name of the gem
|
|
101
|
+
* __/vagrant_home/cloudmonitor/logstash-output-monasca_log_api__ = Path to git workspace
|
|
102
|
+
|
|
103
|
+
Run this command from logstash folder to install the plugin
|
|
104
|
+
```bash
|
|
105
|
+
bin/plugin install --no-verify
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Verify installed plugins:
|
|
109
|
+
With ``bin/plugin list`` you can check installed plugins. There should be ``logstash-output-monasca_log_api``.
|
|
110
|
+
|
|
111
|
+
## Start logstash output plugin
|
|
112
|
+
|
|
113
|
+
### Configuration
|
|
114
|
+
|
|
115
|
+
Save the configfile wherever you like. For example ~/logstash.conf
|
|
116
|
+
|
|
117
|
+
| name | description | required | example |
|
|
118
|
+
| - | - | - | - |
|
|
119
|
+
| monasca_log_api | monasca log api url | yes | http://192.168.10.4:8080 |
|
|
120
|
+
| keystone_api | keystone api url | yes | http://192.168.10.5:5000 |
|
|
121
|
+
| project_name | User-credentials: keystone project name | yes | mini-mon |
|
|
122
|
+
| username | User-credentials: keystone username | yes | admin-agent |
|
|
123
|
+
| password | User-credentials: keystone user password | yes | password |
|
|
124
|
+
| domain_id | User-credentials: keystone user domain-id | yes | default |
|
|
125
|
+
| dimensions | Dictionary of key-value pairs to describe logs | no | hostname: monasca, ip: 192.168.10.4 |
|
|
126
|
+
| application_type_key | Application name | no | monasca |
|
|
127
|
+
|
|
128
|
+
#### Example file
|
|
129
|
+
```bash
|
|
130
|
+
input {
|
|
131
|
+
stdin { }
|
|
132
|
+
}
|
|
133
|
+
output {
|
|
134
|
+
monasca_log_api {
|
|
135
|
+
monasca_log_api => "http://192.168.10.4:8080"
|
|
136
|
+
keystone_api => "http://192.168.10.5:5000"
|
|
137
|
+
project_name => "mini-mon"
|
|
138
|
+
username => "admin-agent"
|
|
139
|
+
password => "password"
|
|
140
|
+
domain_id => "default"
|
|
141
|
+
dimensions => "hostname: elkstack, ip: 192.168.10.4"
|
|
142
|
+
application_type_key => "monasca"
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Run
|
|
148
|
+
```bash
|
|
149
|
+
bin/logstash -f ~/logstash.conf
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Run in debug mode
|
|
153
|
+
```bash
|
|
154
|
+
bin/logstash -f ~/logstash.conf --debug
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Specify log output file
|
|
158
|
+
```bash
|
|
159
|
+
bin/logstash -f ~/logstash.conf -l /var/log/monasca/log/agent/test-log-agent.log
|
|
160
|
+
```
|
|
161
|
+
### Logstash Input plugins
|
|
162
|
+
https://www.elastic.co/guide/en/logstash/current/input-plugins.html
|
|
163
|
+
|
|
164
|
+
## Open tasks
|
|
165
|
+
* Language translations (Replace hardcoded String messages with a configuration/language file)
|
|
166
|
+
* Exception handling (monasca-api requests)
|
|
167
|
+
* Contribute to logstash http://www.elastic.co/guide/en/logstash/master/_how_to_write_a_logstash_output_plugin.html#_contributing_your_source_code_to_ulink_url_https_github_com_logstash_plugins_logstash_plugins_ulink_4
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
Copyright 2015 FUJITSU LIMITED
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
|
5
|
+
in compliance with the License. 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 distributed under the License
|
|
10
|
+
is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
|
11
|
+
or implied. See the License for the specific language governing permissions and limitations under
|
|
12
|
+
the License.
|
|
13
|
+
=end
|
|
14
|
+
|
|
15
|
+
# encoding: utf-8
|
|
16
|
+
|
|
17
|
+
require 'uri'
|
|
18
|
+
|
|
19
|
+
module LogStash::Outputs
|
|
20
|
+
module Helper
|
|
21
|
+
class UrlHelper
|
|
22
|
+
def self.generate_url(host, path)
|
|
23
|
+
uri = URI.parse(host)
|
|
24
|
+
URI::HTTP.new(uri.scheme, nil, uri.host, uri.port, nil, path, nil, nil, nil)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
Copyright 2015 FUJITSU LIMITED
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
|
5
|
+
in compliance with the License. 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 distributed under the License
|
|
10
|
+
is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
|
11
|
+
or implied. See the License for the specific language governing permissions and limitations under
|
|
12
|
+
the License.
|
|
13
|
+
=end
|
|
14
|
+
|
|
15
|
+
# encoding: utf-8
|
|
16
|
+
|
|
17
|
+
require 'logstash/environment'
|
|
18
|
+
require 'logger'
|
|
19
|
+
|
|
20
|
+
require_relative '../helper/url_helper'
|
|
21
|
+
require_relative './token'
|
|
22
|
+
|
|
23
|
+
# This class connects to keystone and authenticates an user.
|
|
24
|
+
# If successful authenticated, the class returns a token object
|
|
25
|
+
module LogStash::Outputs
|
|
26
|
+
module Keystone
|
|
27
|
+
class KeystoneClient
|
|
28
|
+
|
|
29
|
+
@client = nil
|
|
30
|
+
|
|
31
|
+
def initialize(host)
|
|
32
|
+
@logger = Cabin::Channel.get(LogStash)
|
|
33
|
+
@client = get_client(host, '/v3/auth/tokens')
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def authenticate(domain_id, username, password, project_name)
|
|
37
|
+
auth_hash = generate_hash(domain_id, username, password, project_name)
|
|
38
|
+
response = request(auth_hash)
|
|
39
|
+
handle_response(response)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def request(auth_hash)
|
|
45
|
+
@client.post(auth_hash, :content_type => 'application/json', :accept => 'application/json')
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def get_client(host, path)
|
|
49
|
+
RestClient::Resource.new(LogStash::Outputs::Helper::UrlHelper.generate_url(host, path).to_s)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def generate_hash(domain_id, username, password, project_name)
|
|
53
|
+
"{\"auth\":{\"identity\":{\"methods\":[\"password\"],\"password\":{\"user\":{\"domain\":{\"id\":\"#{domain_id}\"},\"name\":\"#{username}\",\"password\":\"#{password}\"}}},\"scope\":{\"project\":{\"domain\":{\"id\":\"#{domain_id}\"},\"name\":\"#{project_name}\"}}}}"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def handle_response(response)
|
|
57
|
+
case response.code
|
|
58
|
+
when 201
|
|
59
|
+
expires_at = DateTime.parse(JSON.parse(response.body)["token"]["expires_at"])
|
|
60
|
+
@logger.debug("Authentication succeed: code=#{response.code}, auth-token=#{response.headers[:x_subject_token]}, expires_at=#{expires_at.to_time}")
|
|
61
|
+
Token.new(response.headers[:x_subject_token], expires_at)
|
|
62
|
+
else
|
|
63
|
+
@logger.info("Authentication failed. Response=#{response}")
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
Copyright 2015 FUJITSU LIMITED
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
|
5
|
+
in compliance with the License. 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 distributed under the License
|
|
10
|
+
is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
|
11
|
+
or implied. See the License for the specific language governing permissions and limitations under
|
|
12
|
+
the License.
|
|
13
|
+
=end
|
|
14
|
+
|
|
15
|
+
# encoding: utf-8
|
|
16
|
+
|
|
17
|
+
module LogStash::Outputs
|
|
18
|
+
module Keystone
|
|
19
|
+
class Token
|
|
20
|
+
attr_accessor :id, :expire_at
|
|
21
|
+
def initialize id, expire_at
|
|
22
|
+
@id = id
|
|
23
|
+
@expire_at = expire_at
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def ==(another_token)
|
|
27
|
+
self.id == another_token.id && self.expire_at == another_token.expire_at
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
Copyright 2015 FUJITSU LIMITED
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
|
5
|
+
in compliance with the License. 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 distributed under the License
|
|
10
|
+
is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
|
11
|
+
or implied. See the License for the specific language governing permissions and limitations under
|
|
12
|
+
the License.
|
|
13
|
+
=end
|
|
14
|
+
|
|
15
|
+
# encoding: utf-8
|
|
16
|
+
|
|
17
|
+
require 'rest-client'
|
|
18
|
+
require 'logger'
|
|
19
|
+
|
|
20
|
+
# relative requirements
|
|
21
|
+
require_relative '../helper/url_helper'
|
|
22
|
+
|
|
23
|
+
# This class creates a connection to monasca-api
|
|
24
|
+
module LogStash::Outputs
|
|
25
|
+
module Monasca
|
|
26
|
+
class MonascaLogApiClient
|
|
27
|
+
|
|
28
|
+
SUPPORTED_API_VERSION = %w(2.0)
|
|
29
|
+
|
|
30
|
+
def initialize(host, version)
|
|
31
|
+
@logger = Cabin::Channel.get(LogStash)
|
|
32
|
+
@rest_client_url = LogStash::Outputs::Helper::UrlHelper.generate_url(host, '/' + check_version(version)).to_s
|
|
33
|
+
@rest_client = RestClient::Resource.new(@rest_client_url)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Send log events to monasca-api, requires token
|
|
37
|
+
def send_event(event, data, token, dimensions, application_type=nil)
|
|
38
|
+
begin
|
|
39
|
+
request(event, data, token, dimensions, application_type)
|
|
40
|
+
@logger.debug("Successfully send event=#{event}, with token=#{token} and dimensions=#{dimensions} to monasca-api")
|
|
41
|
+
rescue => e
|
|
42
|
+
@logger.warn('Sending event to monasca-log-api threw exception', :exceptionew => e)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
def request(event, data, token, dimensions, application_type)
|
|
49
|
+
post_headers = {
|
|
50
|
+
:x_auth_token => token,
|
|
51
|
+
:content_type => 'application/json',
|
|
52
|
+
}
|
|
53
|
+
if dimensions
|
|
54
|
+
post_headers[:x_dimensions] = dimensions
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
if application_type
|
|
58
|
+
post_headers[:x_application_type] = application_type
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
@logger.debug('Sending data to ', :url => @rest_client_url)
|
|
62
|
+
@rest_client['log']['single'].post(data, post_headers)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def check_version(version)
|
|
67
|
+
tmp_version = version.sub('v','')
|
|
68
|
+
|
|
69
|
+
unless SUPPORTED_API_VERSION.include? tmp_version
|
|
70
|
+
raise "#{tmp_version} is not supported, supported versions are #{SUPPORTED_API_VERSION}"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
version
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
Copyright 2015 FUJITSU LIMITED
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
|
5
|
+
in compliance with the License. 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 distributed under the License
|
|
10
|
+
is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
|
11
|
+
or implied. See the License for the specific language governing permissions and limitations under
|
|
12
|
+
the License.
|
|
13
|
+
=end
|
|
14
|
+
|
|
15
|
+
# encoding: utf-8
|
|
16
|
+
|
|
17
|
+
require 'logstash/outputs/base'
|
|
18
|
+
require 'logstash/namespace'
|
|
19
|
+
require 'vine'
|
|
20
|
+
|
|
21
|
+
# relative requirements
|
|
22
|
+
require_relative 'monasca/monasca_log_api_client'
|
|
23
|
+
require_relative 'keystone/keystone_client'
|
|
24
|
+
|
|
25
|
+
# This Logstash Output plugin, sends events to monasca-api.
|
|
26
|
+
# It authenticates against keystone and gets a token.
|
|
27
|
+
# The token is used to authenticate against the monasca-api and send log events.
|
|
28
|
+
class LogStash::Outputs::MonascaLogApi < LogStash::Outputs::Base
|
|
29
|
+
config_name 'monasca_log_api'
|
|
30
|
+
|
|
31
|
+
# monasca-api host and port configuration
|
|
32
|
+
config :monasca_log_api, :validate => :string, :required => true
|
|
33
|
+
config :monasca_log_api_version, :validate => :string, :required => false, :default => "v2.0"
|
|
34
|
+
|
|
35
|
+
# keystone host and port configuration
|
|
36
|
+
config :keystone_api, :validate => :string, :required => true
|
|
37
|
+
# keystone user configuration
|
|
38
|
+
config :project_name, :validate => :string, :required => true
|
|
39
|
+
config :username, :validate => :string, :required => true
|
|
40
|
+
config :password, :validate => :string, :required => true
|
|
41
|
+
config :domain_id, :validate => :string, :required => true
|
|
42
|
+
|
|
43
|
+
config :dimensions, :validate => :string, :default => nil
|
|
44
|
+
config :application_type_key, :validate => :string, :default => 'type'
|
|
45
|
+
|
|
46
|
+
attr_accessor :token
|
|
47
|
+
|
|
48
|
+
default :codec, 'json'
|
|
49
|
+
|
|
50
|
+
public
|
|
51
|
+
def register
|
|
52
|
+
@keystone_client = LogStash::Outputs::Keystone::KeystoneClient.new keystone_api
|
|
53
|
+
@monasca_log_api_client = LogStash::Outputs::Monasca::MonascaLogApiClient.new monasca_log_api, monasca_log_api_version
|
|
54
|
+
@token = get_token
|
|
55
|
+
|
|
56
|
+
@logger.info('Registering keystone user', :username => @username, :project_name => @project_name)
|
|
57
|
+
|
|
58
|
+
@codec.on_event do |event, data|
|
|
59
|
+
check_token
|
|
60
|
+
send_event(event, data, dimensions)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
end # def register
|
|
64
|
+
|
|
65
|
+
def receive(event)
|
|
66
|
+
return unless output?(event)
|
|
67
|
+
if event == LogStash::SHUTDOWN
|
|
68
|
+
finished
|
|
69
|
+
return
|
|
70
|
+
end
|
|
71
|
+
@codec.encode(event)
|
|
72
|
+
end # def receive
|
|
73
|
+
|
|
74
|
+
def finished
|
|
75
|
+
if @shutdown_queue
|
|
76
|
+
@logger.info('Sending shutdown event to agent queue', :plugin => self.class.config_name)
|
|
77
|
+
@shutdown_queue << self
|
|
78
|
+
end
|
|
79
|
+
if @plugin_state != :finished
|
|
80
|
+
@logger.info('Plugin is finished', :plugin => self.class.config_name)
|
|
81
|
+
@plugin_state = :finished
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def shutdown(queue)
|
|
86
|
+
teardown
|
|
87
|
+
@logger.info('Received shutdown signal', :plugin => self.class.config_name)
|
|
88
|
+
|
|
89
|
+
@shutdown_queue = queue
|
|
90
|
+
if @plugin_state == :finished
|
|
91
|
+
finished
|
|
92
|
+
else
|
|
93
|
+
@plugin_state = :terminating
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
private
|
|
98
|
+
def check_token
|
|
99
|
+
now = DateTime.now + Rational(1, 1440)
|
|
100
|
+
if now >= @token.expire_at
|
|
101
|
+
@token = get_token
|
|
102
|
+
@logger.info('Token expired. New token requested')
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def send_event(event, data, dimensions)
|
|
107
|
+
@monasca_log_api_client.send_event(event, data, @token.id, dimensions, get_application_type(event)) if event and @token.id and data
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def get_application_type(event)
|
|
111
|
+
|
|
112
|
+
# support for nested.keys.with.lists.0
|
|
113
|
+
if @application_type_key.include? '.'
|
|
114
|
+
split_key = @application_type_key.split('.')
|
|
115
|
+
event_value = event[split_key[0]]
|
|
116
|
+
access_key = split_key.slice(1..-1).join('.')
|
|
117
|
+
|
|
118
|
+
app_type = event_value.access(access_key)
|
|
119
|
+
|
|
120
|
+
else
|
|
121
|
+
app_type = event[@application_type_key]
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
@logger.debug(
|
|
125
|
+
'Retrieved application_type', :application_type => app_type, :application_type_key => @application_type_key
|
|
126
|
+
)
|
|
127
|
+
app_type
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def get_token
|
|
131
|
+
@keystone_client.authenticate(domain_id, username, password, project_name)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
end # class LogStash::Outputs::Example
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
Gem::Specification.new do |s|
|
|
2
|
+
s.name = 'logstash-output-monasca_log_api'
|
|
3
|
+
s.version = '0.3.3'
|
|
4
|
+
s.licenses = ['Apache License 2.0']
|
|
5
|
+
s.summary = 'This gem is a logstash output plugin to connect via http to monasca-log-api.'
|
|
6
|
+
s.description = 'This gem is a logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/plugin install gemname. This gem is not a stand-alone program'
|
|
7
|
+
s.authors = ['Fujitsu Enabling Software Technology GmbH']
|
|
8
|
+
s.email = 'kamil.choroba@est.fujitsu.com,tomasz.trebski@ts.fujitsu.com'
|
|
9
|
+
s.require_paths = ['lib']
|
|
10
|
+
s.homepage = 'https://github.com/FujitsuEnablingSoftwareTechnologyGmbH/logstash-output-monasca_api'
|
|
11
|
+
|
|
12
|
+
# Files
|
|
13
|
+
s.files = Dir["lib/**/*", "spec/**/*", "*.gemspec", "*.md", "Gemfile", "LICENSE"]
|
|
14
|
+
|
|
15
|
+
# Tests
|
|
16
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
|
17
|
+
|
|
18
|
+
# Special flag to let us know this is actually a logstash plugin
|
|
19
|
+
s.metadata = { 'logstash_plugin' => 'true', 'logstash_group' => 'output' }
|
|
20
|
+
|
|
21
|
+
# Gem dependencies
|
|
22
|
+
s.add_runtime_dependency 'logstash-core', '~> 1.5'
|
|
23
|
+
s.add_runtime_dependency 'logstash-codec-plain', '~> 0.1.6'
|
|
24
|
+
s.add_runtime_dependency 'logstash-codec-json', '~> 0.1.6'
|
|
25
|
+
s.add_runtime_dependency 'rest-client', '~> 1.8'
|
|
26
|
+
s.add_runtime_dependency 'vine', '~> 0.2'
|
|
27
|
+
s.add_development_dependency 'logstash-devutils', '~> 0.0.14'
|
|
28
|
+
s.add_development_dependency 'simplecov', '~> 0.10'
|
|
29
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
Copyright 2015 FUJITSU LIMITED
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
|
5
|
+
in compliance with the License. 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 distributed under the License
|
|
10
|
+
is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
|
11
|
+
or implied. See the License for the specific language governing permissions and limitations under
|
|
12
|
+
the License.
|
|
13
|
+
=end
|
|
14
|
+
|
|
15
|
+
# encoding: utf-8
|
|
16
|
+
|
|
17
|
+
require_relative '../spec_helper'
|
|
18
|
+
|
|
19
|
+
describe LogStash::Outputs::Helper::UrlHelper do
|
|
20
|
+
|
|
21
|
+
describe ".generate_url" do
|
|
22
|
+
it "generates a URI::HTTP object" do
|
|
23
|
+
expect(LogStash::Outputs::Helper::UrlHelper.generate_url('http://192.168.10.5:8080', '/v2.0')).to be_a URI::HTTP
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "should match a http url" do
|
|
27
|
+
expect(LogStash::Outputs::Helper::UrlHelper.generate_url('http://192.168.10.5:8080', '/v2.0').to_s).to eq('http://192.168.10.5:8080/v2.0')
|
|
28
|
+
expect(LogStash::Outputs::Helper::UrlHelper.generate_url('http://est.fujitsu:40', nil).to_s).to eq('http://est.fujitsu:40')
|
|
29
|
+
expect(LogStash::Outputs::Helper::UrlHelper.generate_url('http://est.fujitsu:80', nil).to_s).to eq('http://est.fujitsu')
|
|
30
|
+
expect(LogStash::Outputs::Helper::UrlHelper.generate_url('https://192.168.10.5:8080', '/v2.0').to_s).to eq('https://192.168.10.5:8080/v2.0')
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
Copyright 2015 FUJITSU LIMITED
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
|
5
|
+
in compliance with the License. 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 distributed under the License
|
|
10
|
+
is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
|
11
|
+
or implied. See the License for the specific language governing permissions and limitations under
|
|
12
|
+
the License.
|
|
13
|
+
=end
|
|
14
|
+
|
|
15
|
+
# encoding: utf-8
|
|
16
|
+
|
|
17
|
+
require_relative '../spec_helper'
|
|
18
|
+
|
|
19
|
+
describe LogStash::Outputs::Keystone::KeystoneClient do
|
|
20
|
+
|
|
21
|
+
let (:auth_hash) { "{\"auth\":{\"identity\":{\"methods\":[\"password\"],\"password\":{\"user\":{\"domain\":{\"id\":\"1051bd27b9394120b26d8b08847325c0\"},\"name\":\"csi-operator\",\"password\":\"password\"}}},\"scope\":{\"project\":{\"domain\":{\"id\":\"1051bd27b9394120b26d8b08847325c0\"},\"name\":\"csi\"}}}}" }
|
|
22
|
+
|
|
23
|
+
let (:ok_response) { stub_response(201, {:x_subject_token => "f8cdafb7dce94444ad781a53ddaff693"}, "{\"token\":{\"methods\":[\"password\"],\"roles\":[{\"id\":\"9fe2ff9ee4384b1894a90878d3e92bab\",\"name\":\"_member_\"},{\"id\":\"4e9ef1ffe73446c6b02f8fce0585c307\",\"name\":\"monasca-user\"}],\"expires_at\":\"2015-05-26T08:55:36.774122Z\",\"project\":{\"domain\":{\"id\":\"default\",\"name\":\"Default\"},\"id\":\"1051bd27b9394120b26d8b08847325c0\",\"name\":\"mini-mon\"},\"user\":{\"domain\":{\"id\":\"default\",\"name\":\"Default\"},\"id\":\"06ecc9869b8e4846b2fce3e5759ba4af\",\"name\":\"mini-mon\"},\"audit_ids\":[\"ORap7R56S2S-p6tFVeMkpg\"],\"issued_at\":\"2015-05-26T07:55:36.774146Z\"}}") }
|
|
24
|
+
|
|
25
|
+
let (:failed_response) { stub_response(401, {:x_subject_token => "f8cdafb7dce94444ad781a53ddaff693"}, "{\"error\": {\"message\": \"Could not find project: f8cdafb7dce94444ad781a53ddaff693 (Disable debug mode to suppress these details.)\", \"code\": 401, \"title\": \"Unauthorized\"}}") }
|
|
26
|
+
|
|
27
|
+
context 'when initializing' do
|
|
28
|
+
it 'then it should register without exceptions' do
|
|
29
|
+
expect {LogStash::Outputs::Keystone::KeystoneClient.new('hostname:8080')}.to_not raise_error
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "returns a failure if arguments are missing" do
|
|
33
|
+
expect {LogStash::Outputs::Keystone::KeystoneClient.new}.to raise_exception(ArgumentError)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
context 'when authenticates' do
|
|
38
|
+
it 'then it should request to keystone' do
|
|
39
|
+
expect_any_instance_of(RestClient::Resource).to receive(:post)
|
|
40
|
+
.with(auth_hash, :content_type => 'application/json', :accept => 'application/json')
|
|
41
|
+
keystone_client = LogStash::Outputs::Keystone::KeystoneClient.new('hostname:8080')
|
|
42
|
+
allow(keystone_client).to receive(:handle_response).and_return(LogStash::Outputs::Keystone::Token.new('abc', DateTime.now + Rational(5, 1440)))
|
|
43
|
+
keystone_client.authenticate('1051bd27b9394120b26d8b08847325c0', 'csi-operator', 'password', 'csi')
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it 'then it should create a new token' do
|
|
47
|
+
keystone_client = LogStash::Outputs::Keystone::KeystoneClient.new('hostname:8080')
|
|
48
|
+
allow(keystone_client).to receive(:request).and_return(ok_response)
|
|
49
|
+
expected = LogStash::Outputs::Keystone::Token.new('f8cdafb7dce94444ad781a53ddaff693', DateTime.parse("2015-05-26T08:55:36.774122Z"))
|
|
50
|
+
actual = keystone_client.authenticate('1051bd27b9394120b26d8b08847325c0', 'csi-operator', 'password', 'csi')
|
|
51
|
+
expect(actual).to eq(expected)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
context 'when authentication failed' do
|
|
56
|
+
it 'then it should not create a new token' do
|
|
57
|
+
expect_any_instance_of(Cabin::Channel).to receive(:info)
|
|
58
|
+
keystone_client = LogStash::Outputs::Keystone::KeystoneClient.new('hostname:8080')
|
|
59
|
+
allow(keystone_client).to receive(:request).and_return(failed_response)
|
|
60
|
+
actual = keystone_client.authenticate('1051bd27b9394120b26d8b08847325c0', 'csi-operator', 'password', 'csi')
|
|
61
|
+
expect(actual).to eq(nil)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it 'then it should log an information' do
|
|
65
|
+
expect_any_instance_of(Cabin::Channel).to receive(:info)
|
|
66
|
+
keystone_client = LogStash::Outputs::Keystone::KeystoneClient.new('hostname:8080')
|
|
67
|
+
allow(keystone_client).to receive(:request).and_return(failed_response)
|
|
68
|
+
keystone_client.authenticate('1051bd27b9394120b26d8b08847325c0', 'csi-operator', 'password', 'csi')
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
private
|
|
73
|
+
|
|
74
|
+
def stub_response(code, headers, body)
|
|
75
|
+
response = double
|
|
76
|
+
allow(response).to receive(:code) { code }
|
|
77
|
+
allow(response).to receive(:headers) { headers }
|
|
78
|
+
allow(response).to receive(:body) { body }
|
|
79
|
+
response
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
Copyright 2015 FUJITSU LIMITED
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
|
5
|
+
in compliance with the License. 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 distributed under the License
|
|
10
|
+
is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
|
11
|
+
or implied. See the License for the specific language governing permissions and limitations under
|
|
12
|
+
the License.
|
|
13
|
+
=end
|
|
14
|
+
|
|
15
|
+
# encoding: utf-8
|
|
16
|
+
|
|
17
|
+
require_relative '../spec_helper'
|
|
18
|
+
|
|
19
|
+
describe LogStash::Outputs::Keystone::Token do
|
|
20
|
+
|
|
21
|
+
describe "#new" do
|
|
22
|
+
it "takes two parameters and returns a Token object" do
|
|
23
|
+
token = LogStash::Outputs::Keystone::Token.new('token-id', DateTime.now)
|
|
24
|
+
expect(token).to be_a(LogStash::Outputs::Keystone::Token)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
describe "#==" do
|
|
29
|
+
it "should equal to another token instance" do
|
|
30
|
+
token = LogStash::Outputs::Keystone::Token.new('token-id', DateTime.parse("2015-05-26T08:55:36.774122Z"))
|
|
31
|
+
second_token = LogStash::Outputs::Keystone::Token.new('token-id', DateTime.parse("2015-05-26T08:55:36.774122Z"))
|
|
32
|
+
third_token = LogStash::Outputs::Keystone::Token.new('token-id', DateTime.parse("2015-05-30T08:55:36.774122Z"))
|
|
33
|
+
|
|
34
|
+
expect(token).to eq(second_token)
|
|
35
|
+
expect(third_token).to_not eq(second_token)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
Copyright 2015 FUJITSU LIMITED
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
|
5
|
+
in compliance with the License. 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 distributed under the License
|
|
10
|
+
is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
|
11
|
+
or implied. See the License for the specific language governing permissions and limitations under
|
|
12
|
+
the License.
|
|
13
|
+
=end
|
|
14
|
+
|
|
15
|
+
# encoding: utf-8
|
|
16
|
+
|
|
17
|
+
require_relative '../spec_helper'
|
|
18
|
+
|
|
19
|
+
describe LogStash::Outputs::Monasca::MonascaLogApiClient do
|
|
20
|
+
let (:version) { "v2.0" }
|
|
21
|
+
|
|
22
|
+
let (:auth_hash) { "{\"auth\":{\"identity\":{\"methods\":[\"password\"],\"password\":{\"user\":{\"domain\":{\"id\":\"1051bd27b9394120b26d8b08847325c0\"},\"name\":\"csi-operator\",\"password\":\"password\"}}},\"scope\":{\"project\":{\"domain\":{\"id\":\"1051bd27b9394120b26d8b08847325c0\"},\"name\":\"csi\"}}}}" }
|
|
23
|
+
|
|
24
|
+
let (:ok_response) { stub_response(201, {:x_subject_token => "f8cdafb7dce94444ad781a53ddaff693"}, "{\"token\":{\"methods\":[\"password\"],\"roles\":[{\"id\":\"9fe2ff9ee4384b1894a90878d3e92bab\",\"name\":\"_member_\"},{\"id\":\"4e9ef1ffe73446c6b02f8fce0585c307\",\"name\":\"monasca-user\"}],\"expires_at\":\"2015-05-26T08:55:36.774122Z\",\"project\":{\"domain\":{\"id\":\"default\",\"name\":\"Default\"},\"id\":\"1051bd27b9394120b26d8b08847325c0\",\"name\":\"mini-mon\"},\"user\":{\"domain\":{\"id\":\"default\",\"name\":\"Default\"},\"id\":\"06ecc9869b8e4846b2fce3e5759ba4af\",\"name\":\"mini-mon\"},\"audit_ids\":[\"ORap7R56S2S-p6tFVeMkpg\"],\"issued_at\":\"2015-05-26T07:55:36.774146Z\"}}") }
|
|
25
|
+
|
|
26
|
+
let (:failed_response) { stub_response(401, {:x_subject_token => "f8cdafb7dce94444ad781a53ddaff693"}, "{\"error\": {\"message\": \"Could not find project: f8cdafb7dce94444ad781a53ddaff693 (Disable debug mode to suppress these details.)\", \"code\": 401, \"title\": \"Unauthorized\"}}") }
|
|
27
|
+
|
|
28
|
+
let (:data) { LogStash::Event.new({'message' => '2015-08-13 08:36:59,316 INFO monasca_notification.main Received signal 17, beginning graceful shutdown.',
|
|
29
|
+
'@version' => '1',
|
|
30
|
+
'@timestamp' => '2015-08-13T08:37:00.287Z',
|
|
31
|
+
'type' => 'notification',
|
|
32
|
+
'service' => 'notification',
|
|
33
|
+
'host' => 'monasca',
|
|
34
|
+
'path' => '/var/log/monasca/notification/notification.log'}) }
|
|
35
|
+
|
|
36
|
+
let (:token) { LogStash::Outputs::Keystone::Token.new('abc', DateTime.now + Rational(5, 1440)) }
|
|
37
|
+
|
|
38
|
+
let (:dimensions) { { 'hostname' => 'monasca' } }
|
|
39
|
+
|
|
40
|
+
context 'when initializing' do
|
|
41
|
+
it 'then it should register without exceptions' do
|
|
42
|
+
expect {LogStash::Outputs::Monasca::MonascaLogApiClient.new('hostname:8080', version)}.to_not raise_error
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "returns a failure if arguments are missing" do
|
|
46
|
+
# noinspection RubyArgCount
|
|
47
|
+
expect {LogStash::Outputs::Monasca::MonascaLogApiClient.new}.to raise_exception(ArgumentError)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
context 'when sending events' do
|
|
52
|
+
it 'with dimensions then it should request monasca' do
|
|
53
|
+
expect_any_instance_of(RestClient::Resource).to receive(:post)
|
|
54
|
+
.with(data, :x_auth_token => token, :content_type => 'application/json', :x_dimensions => dimensions)
|
|
55
|
+
monasca_log_api_client = LogStash::Outputs::Monasca::MonascaLogApiClient.new('hostname:8080', version)
|
|
56
|
+
monasca_log_api_client.send_event(nil, data, token, dimensions)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it 'without dimensions then it should request monasca' do
|
|
60
|
+
expect_any_instance_of(RestClient::Resource).to receive(:post)
|
|
61
|
+
.with(data, :x_auth_token => token, :content_type => 'application/json')
|
|
62
|
+
monasca_log_api_client = LogStash::Outputs::Monasca::MonascaLogApiClient.new('hostname:8080', version)
|
|
63
|
+
monasca_log_api_client.send_event(nil, data, token, nil)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it 'with application_type then it should request monasca with that value' do
|
|
67
|
+
app_type = 'someapp'
|
|
68
|
+
expect_any_instance_of(RestClient::Resource).to receive(:post)
|
|
69
|
+
.with(data, :x_auth_token => token, :content_type => 'application/json', :x_application_type => app_type)
|
|
70
|
+
monasca_log_api_client = LogStash::Outputs::Monasca::MonascaLogApiClient.new('hostname:8080', version)
|
|
71
|
+
monasca_log_api_client.send_event(nil, data, token, nil, app_type)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
context 'when sending events failes' do
|
|
76
|
+
it 'then it should be rescued and a warn log printed' do
|
|
77
|
+
expect_any_instance_of(Cabin::Channel).to receive(:warn)
|
|
78
|
+
monasca_log_api_client = LogStash::Outputs::Monasca::MonascaLogApiClient.new('hostname:8080', version)
|
|
79
|
+
allow(monasca_log_api_client).to receive(:request).and_raise('an_error')
|
|
80
|
+
monasca_log_api_client.send_event(nil, data, token, dimensions)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
context 'api version checking' do
|
|
85
|
+
|
|
86
|
+
let (:supported_version) { %w(v2.0) }
|
|
87
|
+
|
|
88
|
+
it 'should pass for correct version' do
|
|
89
|
+
supported_version.each { |ver|
|
|
90
|
+
expect {LogStash::Outputs::Monasca::MonascaLogApiClient.new('hostname:8080', ver)}.to_not raise_error
|
|
91
|
+
}
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it 'should pass if version does not specify v' do
|
|
95
|
+
ver = '2.0'
|
|
96
|
+
expect {LogStash::Outputs::Monasca::MonascaLogApiClient.new('hostname:8080', ver)}.to_not raise_error
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it 'should fail for unsupported version' do
|
|
100
|
+
ver = 'v4.0'
|
|
101
|
+
expect {LogStash::Outputs::Monasca::MonascaLogApiClient.new('hostname:8080', ver)}.to raise_exception
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
end
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
Copyright 2015 FUJITSU LIMITED
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
|
5
|
+
in compliance with the License. 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 distributed under the License
|
|
10
|
+
is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
|
11
|
+
or implied. See the License for the specific language governing permissions and limitations under
|
|
12
|
+
the License.
|
|
13
|
+
=end
|
|
14
|
+
|
|
15
|
+
# encoding: utf-8
|
|
16
|
+
|
|
17
|
+
require_relative 'spec_helper'
|
|
18
|
+
|
|
19
|
+
describe 'outputs/monasca_log_api' do
|
|
20
|
+
|
|
21
|
+
let (:expected_application_type) { 'notification' }
|
|
22
|
+
|
|
23
|
+
let (:event) { LogStash::Event.new({'message' => '2015-08-13 08:36:59,316 INFO monasca_notification.main Received signal 17, beginning graceful shutdown.',
|
|
24
|
+
'@version' => '1',
|
|
25
|
+
'@timestamp' => '2015-08-13T08:37:00.287Z',
|
|
26
|
+
'type' => expected_application_type,
|
|
27
|
+
'service' => 'notification',
|
|
28
|
+
'host' => 'monasca',
|
|
29
|
+
'path' => '/var/log/monasca/notification/notification.log'}) }
|
|
30
|
+
|
|
31
|
+
let (:shutdown_event) { LogStash::SHUTDOWN }
|
|
32
|
+
|
|
33
|
+
let (:simple_config) { {'monasca_log_api' => 'http://192.168.10.4:8080',
|
|
34
|
+
'keystone_api' => 'http://192.168.10.5:5000',
|
|
35
|
+
'domain_id' => 'abadcf984cf7401e88579d393317b0d9',
|
|
36
|
+
'username' => 'username',
|
|
37
|
+
'password' => 'password',
|
|
38
|
+
'project_name' => 'project_name'} }
|
|
39
|
+
|
|
40
|
+
let (:token_id) { LogStash::Outputs::Keystone::Token.new('abc', DateTime.now + Rational(5, 1440)) }
|
|
41
|
+
|
|
42
|
+
let (:old_token_id) { LogStash::Outputs::Keystone::Token.new('def', DateTime.now - Rational(5, 1440)) }
|
|
43
|
+
|
|
44
|
+
context 'when initializing' do
|
|
45
|
+
it 'then it should register without exceptions' do
|
|
46
|
+
monasca_log_api = LogStash::Plugin.lookup('output', 'monasca_log_api').new(simple_config)
|
|
47
|
+
allow(monasca_log_api).to receive(:get_token).and_return(token_id)
|
|
48
|
+
expect {monasca_log_api.register}.to_not raise_error
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "should set a default application_type_key to \"type\"" do
|
|
52
|
+
monasca_log_api = LogStash::Plugin.lookup('output', 'monasca_log_api').new(simple_config)
|
|
53
|
+
expect(monasca_log_api.instance_variable_get('@application_type_key')).to eq("type")
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it 'should use passed variable from config as application_type_key' do
|
|
57
|
+
expected_key = 'mountain_dew'
|
|
58
|
+
simple_config_copy = simple_config.clone
|
|
59
|
+
simple_config_copy['application_type_key'] = expected_key
|
|
60
|
+
monasca_log_api = LogStash::Plugin.lookup('output', 'monasca_log_api').new(simple_config_copy)
|
|
61
|
+
|
|
62
|
+
expect(monasca_log_api.instance_variable_get('@application_type_key')).to eq(expected_key)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
context 'when receiving messages' do
|
|
68
|
+
it 'then it should be send to monasca-log-api' do
|
|
69
|
+
expect_any_instance_of(LogStash::Outputs::Monasca::MonascaLogApiClient).to receive(:send_event)
|
|
70
|
+
.with(event, event.to_hash.to_json, token_id.id, nil, expected_application_type)
|
|
71
|
+
monasca_log_api = LogStash::Outputs::MonascaLogApi.new(simple_config)
|
|
72
|
+
|
|
73
|
+
allow(monasca_log_api).to receive(:get_token).and_return(token_id)
|
|
74
|
+
allow(monasca_log_api).to receive(:get_application_type).and_call_original
|
|
75
|
+
|
|
76
|
+
monasca_log_api.register
|
|
77
|
+
monasca_log_api.receive(event)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it 'then it should check the token_id and renew it when its deprecated' do
|
|
81
|
+
expect_any_instance_of(LogStash::Outputs::Keystone::KeystoneClient).to receive(:authenticate)
|
|
82
|
+
.with(simple_config['domain_id'], simple_config['username'], simple_config['password'], simple_config['project_name'])
|
|
83
|
+
monasca_log_api = LogStash::Outputs::MonascaLogApi.new(simple_config)
|
|
84
|
+
allow(monasca_log_api).to receive(:get_token).and_return(old_token_id)
|
|
85
|
+
monasca_log_api.register
|
|
86
|
+
allow(monasca_log_api).to receive(:get_token).and_call_original
|
|
87
|
+
allow(monasca_log_api).to receive(:send_event)
|
|
88
|
+
monasca_log_api.receive(event)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
context 'when given dictionary as type in received message' do
|
|
93
|
+
it 'should read application_type from it properly' do
|
|
94
|
+
type_dict = {
|
|
95
|
+
"application_type" => 'notification'
|
|
96
|
+
}
|
|
97
|
+
config = simple_config.merge({"application_type_key" => 'type.application_type'})
|
|
98
|
+
|
|
99
|
+
event = LogStash::Event.new({"message" => '2015-08-13 08:36:59,316 INFO monasca_notification.main Received signal 17, beginning graceful shutdown.',
|
|
100
|
+
"@version" => '1',
|
|
101
|
+
"@timestamp" => '2015-08-13T08:37:00.287Z',
|
|
102
|
+
"type" => type_dict,
|
|
103
|
+
"service" => 'notification',
|
|
104
|
+
"host" => 'monasca',
|
|
105
|
+
"path" => '/var/log/monasca/notification/notification.log',
|
|
106
|
+
})
|
|
107
|
+
expect_any_instance_of(LogStash::Outputs::Monasca::MonascaLogApiClient).to receive(:send_event)
|
|
108
|
+
.with(event, event.to_hash.to_json, token_id.id, nil, expected_application_type)
|
|
109
|
+
monasca_log_api = LogStash::Outputs::MonascaLogApi.new(config)
|
|
110
|
+
|
|
111
|
+
allow(monasca_log_api).to receive(:get_token).and_return(token_id)
|
|
112
|
+
allow(monasca_log_api).to receive(:get_application_type).and_call_original
|
|
113
|
+
|
|
114
|
+
monasca_log_api.register
|
|
115
|
+
monasca_log_api.receive(event)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
context 'when receiving SHUTDOWN message' do
|
|
121
|
+
it 'then it should be send to monasca-log-api' do
|
|
122
|
+
expect_any_instance_of(LogStash::Outputs::Monasca::MonascaLogApiClient).to_not receive(:send_event)
|
|
123
|
+
.with(shutdown_event, nil, token_id.id, nil)
|
|
124
|
+
monasca_log_api = LogStash::Outputs::MonascaLogApi.new(simple_config)
|
|
125
|
+
allow(monasca_log_api).to receive(:get_token).and_return(token_id)
|
|
126
|
+
monasca_log_api.register
|
|
127
|
+
monasca_log_api.receive(shutdown_event)
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
Copyright 2015 FUJITSU LIMITED
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
|
5
|
+
in compliance with the License. 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 distributed under the License
|
|
10
|
+
is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
|
11
|
+
or implied. See the License for the specific language governing permissions and limitations under
|
|
12
|
+
the License.
|
|
13
|
+
=end
|
|
14
|
+
|
|
15
|
+
# encoding: utf-8
|
|
16
|
+
|
|
17
|
+
require 'simplecov'
|
|
18
|
+
SimpleCov.start do
|
|
19
|
+
add_filter '/test/'
|
|
20
|
+
add_filter '/config/'
|
|
21
|
+
add_filter '/vendor/'
|
|
22
|
+
add_filter '/spec/'
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
require_relative '../../lib/logstash/outputs/monasca_log_api'
|
|
26
|
+
require_relative '../../lib/logstash/outputs/keystone/keystone_client'
|
|
27
|
+
require_relative '../../lib/logstash/outputs/keystone/token'
|
|
28
|
+
require_relative '../../lib/logstash/outputs/monasca/monasca_log_api_client'
|
|
29
|
+
require_relative '../../lib/logstash/outputs/helper/url_helper'
|
|
30
|
+
|
|
31
|
+
require 'yaml'
|
|
32
|
+
require 'rest-client'
|
metadata
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: logstash-output-monasca_log_api
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.3.3
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Fujitsu Enabling Software Technology GmbH
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2015-12-03 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: logstash-core
|
|
15
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ~>
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '1.5'
|
|
20
|
+
requirement: !ruby/object:Gem::Requirement
|
|
21
|
+
requirements:
|
|
22
|
+
- - ~>
|
|
23
|
+
- !ruby/object:Gem::Version
|
|
24
|
+
version: '1.5'
|
|
25
|
+
prerelease: false
|
|
26
|
+
type: :runtime
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: logstash-codec-plain
|
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ~>
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: 0.1.6
|
|
34
|
+
requirement: !ruby/object:Gem::Requirement
|
|
35
|
+
requirements:
|
|
36
|
+
- - ~>
|
|
37
|
+
- !ruby/object:Gem::Version
|
|
38
|
+
version: 0.1.6
|
|
39
|
+
prerelease: false
|
|
40
|
+
type: :runtime
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: logstash-codec-json
|
|
43
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ~>
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: 0.1.6
|
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
|
49
|
+
requirements:
|
|
50
|
+
- - ~>
|
|
51
|
+
- !ruby/object:Gem::Version
|
|
52
|
+
version: 0.1.6
|
|
53
|
+
prerelease: false
|
|
54
|
+
type: :runtime
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: rest-client
|
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ~>
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '1.8'
|
|
62
|
+
requirement: !ruby/object:Gem::Requirement
|
|
63
|
+
requirements:
|
|
64
|
+
- - ~>
|
|
65
|
+
- !ruby/object:Gem::Version
|
|
66
|
+
version: '1.8'
|
|
67
|
+
prerelease: false
|
|
68
|
+
type: :runtime
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: vine
|
|
71
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - ~>
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '0.2'
|
|
76
|
+
requirement: !ruby/object:Gem::Requirement
|
|
77
|
+
requirements:
|
|
78
|
+
- - ~>
|
|
79
|
+
- !ruby/object:Gem::Version
|
|
80
|
+
version: '0.2'
|
|
81
|
+
prerelease: false
|
|
82
|
+
type: :runtime
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: logstash-devutils
|
|
85
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - ~>
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: 0.0.14
|
|
90
|
+
requirement: !ruby/object:Gem::Requirement
|
|
91
|
+
requirements:
|
|
92
|
+
- - ~>
|
|
93
|
+
- !ruby/object:Gem::Version
|
|
94
|
+
version: 0.0.14
|
|
95
|
+
prerelease: false
|
|
96
|
+
type: :development
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: simplecov
|
|
99
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - ~>
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '0.10'
|
|
104
|
+
requirement: !ruby/object:Gem::Requirement
|
|
105
|
+
requirements:
|
|
106
|
+
- - ~>
|
|
107
|
+
- !ruby/object:Gem::Version
|
|
108
|
+
version: '0.10'
|
|
109
|
+
prerelease: false
|
|
110
|
+
type: :development
|
|
111
|
+
description: This gem is a logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/plugin install gemname. This gem is not a stand-alone program
|
|
112
|
+
email: kamil.choroba@est.fujitsu.com,tomasz.trebski@ts.fujitsu.com
|
|
113
|
+
executables: []
|
|
114
|
+
extensions: []
|
|
115
|
+
extra_rdoc_files: []
|
|
116
|
+
files:
|
|
117
|
+
- Gemfile
|
|
118
|
+
- LICENSE
|
|
119
|
+
- README.md
|
|
120
|
+
- lib/logstash/outputs/helper/url_helper.rb
|
|
121
|
+
- lib/logstash/outputs/keystone/keystone_client.rb
|
|
122
|
+
- lib/logstash/outputs/keystone/token.rb
|
|
123
|
+
- lib/logstash/outputs/monasca/monasca_log_api_client.rb
|
|
124
|
+
- lib/logstash/outputs/monasca_log_api.rb
|
|
125
|
+
- logstash-output-monasca_log_api.gemspec
|
|
126
|
+
- spec/outputs/helper/url_helper_spec.rb
|
|
127
|
+
- spec/outputs/keystone/keystone_client_spec.rb
|
|
128
|
+
- spec/outputs/keystone/token_spec.rb
|
|
129
|
+
- spec/outputs/monasca/monasca_api_client_spec.rb
|
|
130
|
+
- spec/outputs/monasca_api_spec.rb
|
|
131
|
+
- spec/outputs/spec_helper.rb
|
|
132
|
+
homepage: https://github.com/FujitsuEnablingSoftwareTechnologyGmbH/logstash-output-monasca_api
|
|
133
|
+
licenses:
|
|
134
|
+
- Apache License 2.0
|
|
135
|
+
metadata:
|
|
136
|
+
logstash_plugin: 'true'
|
|
137
|
+
logstash_group: output
|
|
138
|
+
post_install_message:
|
|
139
|
+
rdoc_options: []
|
|
140
|
+
require_paths:
|
|
141
|
+
- lib
|
|
142
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
143
|
+
requirements:
|
|
144
|
+
- - '>='
|
|
145
|
+
- !ruby/object:Gem::Version
|
|
146
|
+
version: '0'
|
|
147
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
148
|
+
requirements:
|
|
149
|
+
- - '>='
|
|
150
|
+
- !ruby/object:Gem::Version
|
|
151
|
+
version: '0'
|
|
152
|
+
requirements: []
|
|
153
|
+
rubyforge_project:
|
|
154
|
+
rubygems_version: 2.4.5
|
|
155
|
+
signing_key:
|
|
156
|
+
specification_version: 4
|
|
157
|
+
summary: This gem is a logstash output plugin to connect via http to monasca-log-api.
|
|
158
|
+
test_files:
|
|
159
|
+
- spec/outputs/helper/url_helper_spec.rb
|
|
160
|
+
- spec/outputs/keystone/keystone_client_spec.rb
|
|
161
|
+
- spec/outputs/keystone/token_spec.rb
|
|
162
|
+
- spec/outputs/monasca/monasca_api_client_spec.rb
|
|
163
|
+
- spec/outputs/monasca_api_spec.rb
|
|
164
|
+
- spec/outputs/spec_helper.rb
|