fluent-plugin-spectrum 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9bc88f1954fef9f516c4ef7c8f7fd134a6ed957d
4
+ data.tar.gz: de6e8bfdd3f67695df5de0f2f62fee25f9c15a91
5
+ SHA512:
6
+ metadata.gz: ec23275e1753d9d7bce921d6a8e3a6df5a48225dcde19a9fb5aaf6f7d1f3a1352a8b415676d7c131e1c54a4d657f12aaac1643ca9697adbed7de92df773cfb36
7
+ data.tar.gz: 54f6270b853b64f33290044b9d9a910dc7adb8d25aa3dacc2165ea91711a6ad643f79f7fb61d991aa3d575c2dbadf24a2c1727c0d43ae7b905fb76698fd745cd
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in fluent-plugin-spectrum.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,43 @@
1
+ # Fluent::Plugin::Spectrum
2
+
3
+ fluent-plugin-spectrum is an input plug-in for [Fluentd](http://fluentd.org)
4
+
5
+ ## Installation
6
+
7
+ These instructions assume you already have fluentd installed.
8
+ If you don't, please run through [quick start for fluentd] (https://github.com/fluent/fluentd#quick-start)
9
+
10
+ Now after you have fluentd installed you can follow either of the steps below:
11
+
12
+ Add this line to your application's Gemfile:
13
+
14
+ gem 'fluent-plugin-spectrum'
15
+
16
+ Or install it yourself as:
17
+
18
+ $ gem install fluent-plugin-spectrum
19
+
20
+ ## Usage
21
+ Add the following into your fluentd config.
22
+
23
+ <source>
24
+ type spectrum # required, choosing the input plugin.
25
+ endpoint hostname # required, FQDN of Spectrum EndPoint
26
+ username ws_user # optional, interface to listen on, default 0 for all.
27
+ password ws_password # optional, interface to listen on, default 0 for all.
28
+ tag alert.spectrum # optional, tag to assign to events, default is alert.spectrum
29
+ </source>
30
+
31
+ <match alert.spectrum>
32
+ type stdout
33
+ </match>
34
+
35
+ Now startup fluentd
36
+
37
+ $ sudo fluentd -c fluent.conf &
38
+
39
+ Send a test
40
+ TBD
41
+
42
+ ## To Do
43
+ Things left to do, not in any particular order.
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env rake
2
+ require 'bundler'
3
+ Bundler::GemHelper.install_tasks
4
+
5
+ require 'rake/testtask'
6
+
7
+ Rake::TestTask.new(:test) do |test|
8
+ test.libs << 'lib' << 'test'
9
+ test.pattern = 'test/**/test_*.rb'
10
+ test.verbose = true
11
+ end
12
+
13
+ task :default => [:build]
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.name = "fluent-plugin-spectrum"
6
+ gem.version = "0.0.1"
7
+ gem.date = '2015-02-24'
8
+ gem.authors = ["Alex Pena"]
9
+ gem.email = ["alex_pena@intuit.com"]
10
+ gem.summary = %q{Fluentd input plugin for Spectrum Alerts}
11
+ gem.description = %q{Fluentd plugin for Spectrum Alerts... WIP}
12
+ gem.homepage = 'https://github.com/Bigel0w/fluent-plugin-spectrum'
13
+ gem.license = 'MIT'
14
+
15
+ gem.files = `git ls-files`.split($\)
16
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
17
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_development_dependency "rake", '~> 0.9', '>= 0.9.6'
21
+
22
+ gem.add_runtime_dependency "fluentd", '~> 0.10', '>= 0.10.52'
23
+ gem.add_runtime_dependency "json", '~> 1.1', '>= 1.8.2'
24
+ gem.add_runtime_dependency "rest_client", '~> 1.1', '>= 1.8.3'
25
+ end
@@ -0,0 +1,182 @@
1
+ module Fluent
2
+ # TODO:
3
+ # Add a fields all or list option
4
+ # error checking in every section
5
+ class SpectrumInput < Input
6
+ Fluent::Plugin.register_input('spectrum', self)
7
+
8
+ config_param :tag, :string, :default => "alert.spectrum"
9
+ config_param :endpoint, :string, :default => "pleasechangeme.com" #fqdn of endpoint
10
+ config_param :interval, :integer, :default => '300' #Default 5 minutes
11
+ config_param :user, :string, :default => "username"
12
+ config_param :pass, :string, :default => "password"
13
+ config_param :include_raw, :string, :default => "false" #Include original object as raw
14
+ config_param :attributes, :string, :default => "ALL" # fields to include, ALL for... well, ALL.
15
+
16
+ def initialize
17
+ require 'rest_client'
18
+ require 'json'
19
+ super
20
+ end # def initialize
21
+
22
+ def configure(conf)
23
+ super
24
+ @conf = conf
25
+ # map of Spectrum attribute codes to names
26
+ @spectrum_access_code={
27
+ "0x11f9c" => "ALARM_ID",
28
+ "0x11f4e" => "CREATION_DATE",
29
+ "0x11f56" => "SEVERITY",
30
+ "0x12b4c" => "ALARM_TITLE",
31
+ "0x1006e" => "HOSTNAME",
32
+ "0x12d7f" => "IP_ADDRESS",
33
+ "0x1296e" => "ORIGINATING_EVENT_ATTR",
34
+ "0x10000" => "MODEL_STRING",
35
+ "0x11f4d" => "ACKNOWLEDGED",
36
+ "0x11f4f" => "ALARM_STATUS",
37
+ "0x11fc5" => "OCCURRENCES",
38
+ "0x11f57" => "TROUBLE_SHOOTER",
39
+ "0x11f9b" => "USER_CLEARABLE",
40
+ "0x12022" => "TROUBLE_TICKET_ID",
41
+ "0x12942" => "PERSISTENT",
42
+ "0x12adb" => "GC_NAME",
43
+ "0x57f0105" => "Custom_Project",
44
+ "0x11f4d" => "ACKNOWLEDGED",
45
+ #{}"0x11f51" => "CLEARED_BY_USER_NAME",
46
+ #{}"0x11f52" => "EVENT_ID_LIST",
47
+ #{}"0x11f53" => "MODEL_HANDLE",
48
+ #{}"0x11f54" => "PRIMARY_ALARM",
49
+ #{}"0x11fc4" => "ALARM_SOURCE",
50
+ #{}"0x11fc6" => "TROUBLE_SHOOTER_MH",
51
+ #{}"0x12a6c" => "TROUBLE_SHOOTER_EMAIL",
52
+ #{}"0x1290d" => "IMPACT_SEVERITY",
53
+ #{}"0x1290e" => "IMPACT_SCOPE",
54
+ #{}"0x1298a" => "IMPACT_TYPE_LIST",
55
+ #{}"0x12948" => "DIAGNOSIS_LOG",
56
+ #{}"0x129aa" => "MODEL_ID",
57
+ #{}"0x129ab" => "MODEL_TYPE_ID",
58
+ #{}"0x129af" => "CLEAR_DATE",
59
+ #{}"0x12a04" => "SYMPTOM_LIST_ATTR",
60
+ #{}"0x12a6f" => "EVENT_SYMPTOM_LIST_ATTR",
61
+ #{}"0x12a05" => "CAUSE_LIST_ATTR",
62
+ #{}"0x12a06" => "SYMPTOM_COUNT_ATTR",
63
+ #{}"0x12a70" => "EVENT_SYMPTOM_COUNT_ATTR",
64
+ #{}"0x12a07" => "CAUSE_COUNT_ATTR",
65
+ #{}"0x12a63" => "WEB_CONTEXT_URL",
66
+ #{}"0x12a6b" => "COMBINED_IMPACT_TYPE_LIST",
67
+ #{}"0x11f50" => "CAUSE_CODE",
68
+ #{}"0x10009" => "SECURITY_STRING"
69
+ }
70
+ # Create XML chunk for attributes we care about
71
+ @attr_of_interest=""
72
+ @spectrum_access_code.each do |key, array|
73
+ @attr_of_interest += " <rs:requested-attribute id=\"#{key}\"/>"
74
+ end
75
+ # Setup URL Resource
76
+ @url = 'http://' + @endpoint.to_s + '/spectrum/restful/alarms'
77
+ def spectrumEnd
78
+ RestClient::Resource.new(@url,@user,@pass)
79
+ end
80
+ end # def configure
81
+
82
+ def start
83
+ super
84
+ @loop = Coolio::Loop.new
85
+ timer_trigger = TimerWatcher.new(@interval, true, &method(:input))
86
+ timer_trigger.attach(@loop)
87
+ @thread = Thread.new(&method(:run))
88
+ $log.info "Spectrum :: starting poller, endpoint #{@endpoint} interval #{@interval}"
89
+ end # def start
90
+
91
+ def shutdown
92
+ super
93
+ @loop.stop
94
+ @thread.join
95
+ end # def shutdown
96
+
97
+ def run
98
+ @loop.run
99
+ end # def run
100
+
101
+ def input
102
+ alertStartTime = Engine.now.to_i - @interval.to_i
103
+ $log.info "Spectrum :: Polling for alerts for time period: #{alertStartTime.to_i} - #{Engine.now.to_i}"
104
+
105
+ # function to UTF8 encode
106
+ def to_utf8(str)
107
+ str = str.force_encoding('UTF-8')
108
+ return str if str.valid_encoding?
109
+ str.encode("UTF-8", 'binary', invalid: :replace, undef: :replace, replace: '')
110
+ end
111
+
112
+ # XML for spectrum post
113
+ @xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
114
+ <rs:alarm-request throttlesize=\"10000\"
115
+ xmlns:rs=\"http://www.ca.com/spectrum/restful/schema/request\"
116
+ xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
117
+ xsi:schemaLocation=\"http://www.ca.com/spectrum/restful/schema/request ../../../xsd/Request.xsd \">
118
+ <rs:attribute-filter>
119
+ <search-criteria xmlns=\"http://www.ca.com/spectrum/restful/schema/filter\">
120
+ <filtered-models>
121
+ <greater-than>
122
+ <attribute id=\"0x11f4e\">
123
+ <value> #{alertStartTime} </value>
124
+ </attribute>
125
+ </greater-than>
126
+ </filtered-models>
127
+ </search-criteria>
128
+ </rs:attribute-filter>
129
+ #{@attr_of_interest}
130
+ </rs:alarm-request>"
131
+
132
+ # Post to Spectrum and parse results
133
+ responsePost=spectrumEnd.post @xml,:content_type => 'application/xml',:accept => 'application/json'
134
+ body = JSON.parse(responsePost.body)
135
+ # Only continue if we have alarms in results
136
+ if body['ns1.alarm-response-list']['@total-alarms'].to_i > 1
137
+ $log.info "Spectrum :: returned #{body['ns1.alarm-response-list']['@total-alarms'].to_i} alarms"
138
+ # iterate through alarms in results
139
+ body['ns1.alarm-response-list']['ns1.alarm-responses']['ns1.alarm'].each do |alarm|
140
+ record_hash = Hash.new # temp hash to hold attributes of alarm
141
+ record_hash['event_type'] = @tag.to_s
142
+ record_hash['intermediary_source'] = @endpoint.to_s
143
+ # iterate though alarm attributes and add to temp hash
144
+ alarm['ns1.attribute'].each do |attribute|
145
+ record_hash[@spectrum_access_code[attribute['@id'].to_s].to_s] = to_utf8(attribute['$'].to_s)
146
+ end
147
+ # include raw?
148
+ if @include_raw.to_s == "true"
149
+ record_hash['raw'] = alarm
150
+ end
151
+ Engine.emit(@tag, record_hash['CREATION_DATE'].to_i,record_hash)
152
+ end
153
+ elsif body['ns1.alarm-response-list']['@total-alarms'].to_i == 1
154
+ $log.info "Spectrum :: returned #{body['ns1.alarm-response-list']['@total-alarms'].to_i} alarms"
155
+ record_hash = Hash.new # temp hash to hold attributes of alarm
156
+ record_hash['event_type'] = @tag.to_s
157
+ record_hash['intermediary_source'] = @endpoint.to_s
158
+ # iterate though alarm attributes and add to temp hash
159
+ body['ns1.alarm-response-list']['ns1.alarm-responses']['ns1.alarm']['ns1.attribute'].each do |attribute|
160
+ record_hash[@spectrum_access_code[attribute['@id'].to_s].to_s] = to_utf8(attribute['$'].to_s)
161
+ end
162
+ # include raw?
163
+ if @include_raw.to_s == "true"
164
+ record_hash['raw'] = alarm
165
+ end
166
+ Engine.emit(@tag, record_hash['CREATION_DATE'].to_i,record_hash)
167
+ end
168
+ end
169
+ end # class SpectrumInput
170
+
171
+ # class for handling interval in loop
172
+ class TimerWatcher < Coolio::TimerWatcher
173
+ def initialize(interval, repeat, &callback)
174
+ @callback = callback
175
+ super(interval, repeat)
176
+ end # def initialize
177
+ def on_timer
178
+ @callback.call
179
+ end # def on_timer
180
+ end
181
+
182
+ end # module Fluent
@@ -0,0 +1,8 @@
1
+ <source>
2
+ type spectrum
3
+ tag alert.spectrum
4
+ </source>
5
+
6
+ <match alert.spectrum*>
7
+ type stdout
8
+ </match>
data/test/helper.rb ADDED
@@ -0,0 +1,28 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'test/unit'
11
+
12
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
13
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
14
+ require 'fluent/test'
15
+ unless ENV.has_key?('VERBOSE')
16
+ nulllogger = Object.new
17
+ nulllogger.instance_eval {|obj|
18
+ def method_missing(method, *args)
19
+ # pass
20
+ end
21
+ }
22
+ $log = nulllogger
23
+ end
24
+
25
+ require 'fluent/plugin/in_spectrum'
26
+
27
+ class Test::Unit::TestCase
28
+ end
@@ -0,0 +1,24 @@
1
+ require 'helper'
2
+
3
+ class SpectrumInputTest < Test::Unit::TestCase
4
+ def setup
5
+ Fluent::Test.setup
6
+ end
7
+
8
+ CONFIG = %[
9
+ host 0
10
+ port 1062
11
+ tag alert.spectrum
12
+ ]
13
+
14
+ def create_driver(conf=CONFIG)
15
+ Fluent::Test::InputTestDriver.new(Fluent::SpectrumInput).configure(conf)
16
+ end
17
+
18
+ def test_configure
19
+ d = create_driver('')
20
+ assert_equal "0".to_i, d.instance.host
21
+ assert_equal "1062".to_i, d.instance.port
22
+ assert_equal 'alert.spectrum', d.instance.tag
23
+ end
24
+ end
metadata ADDED
@@ -0,0 +1,134 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-spectrum
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Alex Pena
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-02-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '0.9'
20
+ - - '>='
21
+ - !ruby/object:Gem::Version
22
+ version: 0.9.6
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '0.9'
30
+ - - '>='
31
+ - !ruby/object:Gem::Version
32
+ version: 0.9.6
33
+ - !ruby/object:Gem::Dependency
34
+ name: fluentd
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ~>
38
+ - !ruby/object:Gem::Version
39
+ version: '0.10'
40
+ - - '>='
41
+ - !ruby/object:Gem::Version
42
+ version: 0.10.52
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ~>
48
+ - !ruby/object:Gem::Version
49
+ version: '0.10'
50
+ - - '>='
51
+ - !ruby/object:Gem::Version
52
+ version: 0.10.52
53
+ - !ruby/object:Gem::Dependency
54
+ name: json
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ~>
58
+ - !ruby/object:Gem::Version
59
+ version: '1.1'
60
+ - - '>='
61
+ - !ruby/object:Gem::Version
62
+ version: 1.8.2
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: '1.1'
70
+ - - '>='
71
+ - !ruby/object:Gem::Version
72
+ version: 1.8.2
73
+ - !ruby/object:Gem::Dependency
74
+ name: rest_client
75
+ requirement: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ~>
78
+ - !ruby/object:Gem::Version
79
+ version: '1.1'
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: 1.8.3
83
+ type: :runtime
84
+ prerelease: false
85
+ version_requirements: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: '1.1'
90
+ - - '>='
91
+ - !ruby/object:Gem::Version
92
+ version: 1.8.3
93
+ description: Fluentd plugin for Spectrum Alerts... WIP
94
+ email:
95
+ - alex_pena@intuit.com
96
+ executables: []
97
+ extensions: []
98
+ extra_rdoc_files: []
99
+ files:
100
+ - Gemfile
101
+ - README.md
102
+ - Rakefile
103
+ - fluent-plugin-spectrum.gemspec
104
+ - lib/fluent/plugin/in_spectrum.rb
105
+ - sample/spectrum.conf.sample
106
+ - test/helper.rb
107
+ - test/plugin/test_in_spectrum.rb
108
+ homepage: https://github.com/Bigel0w/fluent-plugin-spectrum
109
+ licenses:
110
+ - MIT
111
+ metadata: {}
112
+ post_install_message:
113
+ rdoc_options: []
114
+ require_paths:
115
+ - lib
116
+ required_ruby_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - '>='
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ required_rubygems_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ requirements: []
127
+ rubyforge_project:
128
+ rubygems_version: 2.3.0
129
+ signing_key:
130
+ specification_version: 4
131
+ summary: Fluentd input plugin for Spectrum Alerts
132
+ test_files:
133
+ - test/helper.rb
134
+ - test/plugin/test_in_spectrum.rb