sensu-plugins-meta 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: af92cbbb28bc9c17d4c90d229e2f1eab8a0c5617
4
+ data.tar.gz: 45eda5fef6a258e566fc306ee2aeea01a7628c80
5
+ SHA512:
6
+ metadata.gz: ffe171614f4e544d4f0cac8401111db348ffa9caeb89898ad8acc549cf1fbec5c2b8fb921b8df52ea000ad4d8ae155ee232ef92707611a79040ff7fc9b5996ae
7
+ data.tar.gz: d1b8e0ed0d5a47faa17804e2abf2a2442020f38f4e3cb9f997b5f3eae064340af33580129e718528c597574fe3fdae3b64875ee82437793dd3ec2d4d19856929
@@ -0,0 +1,14 @@
1
+ # Change Log
2
+ This project adheres to [Semantic Versioning](http://semver.org/).
3
+
4
+ This CHANGELOG follows the format listed at [Keep A Changelog](http://keepachangelog.com/)
5
+
6
+ ## [Unreleased]
7
+ ### Added
8
+
9
+ ## [0.1.0] - 2017-03-07
10
+ ### Added
11
+ - Initial release
12
+
13
+ [Unreleased]: https://github.com/socrata-platform/sensu-plugins-meta/compare/0.1.0...HEAD
14
+ [0.1.0]: https://github.com/socrata-platform/sensu-plugins-meta/tree/v0.1.0
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2017 Sensu-Plugins
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,56 @@
1
+ Sensu Plugins Meta
2
+ ==================
3
+
4
+ [![Build Status](https://img.shields.io/travis/socrata-platform/sensu-plugins-meta.svg)][travis]
5
+ [![Gem Version](https://img.shields.io/gem/v/sensu-plugins-meta.svg)][rubygems]
6
+ [![Code Climate](https://img.shields.io/codeclimate/github/socrata-platform/sensu-plugins-meta.svg)][codeclimate]
7
+ [![Test Coverage](https://img.shields.io/coveralls/socrata-platform/sensu-plugins-meta.svg)][coveralls]
8
+ [![Dependency Status](https://gemnasium.com/socrata-platform/sensu-plugins-meta.svg)][gemnasium]
9
+
10
+ [travis]: https://travis-ci.org/socrata-platform/sensu-plugins-meta
11
+ [rubygems]: https://rubygems.org/gems/sensu-plugins-meta
12
+ [codeclimate]: https://codeclimate.com/github/socrata-platform/sensu-plugins-meta
13
+ [coveralls]: https://coveralls.io/r/socrata-platform/sensu-plugins-meta
14
+ [gemnasium]: https://gemnasium.com/socrata-platform/sensu-plugins-meta
15
+
16
+ Functionality
17
+ -------------
18
+
19
+ This Sensu plugin can be used to run another plugin multiple times as one
20
+ batch check.
21
+
22
+ Files
23
+ -----
24
+
25
+ * bin/check-meta-ruby.rb
26
+
27
+ Usage
28
+ -----
29
+
30
+ The `check-meta-ruby.rb` script requires another Sensu plugin to run and a JSON
31
+ array of options to run it with. The JSON can be provided either as a string:
32
+
33
+ check-meta-ruby.rb -c /opt/sensu/embedded/bin/check-http.rb \
34
+ -j '[{"url": "http://pants.com/"}, {"url": "https://www.google.com"}]'
35
+
36
+ ...or as a path to a file:
37
+
38
+ check-meta-ruby.rb -c /opt/sensu/embedded/bin/check-http.rb \
39
+ -j /etc/sensu/http_checks.json
40
+
41
+ If a full path is not provided for the Sensu plugin file, an attempt will be
42
+ made to find it relative to the `check-meta-ruby.rb` file.
43
+
44
+ Installation
45
+ ------------
46
+
47
+ [Installation and Setup](http://sensu-plugins.io/docs/installation_instructions.html)
48
+
49
+ Notes
50
+ -----
51
+
52
+ The Ruby check makes certain assumptions about the plugin it's being asked to
53
+ run:
54
+
55
+ * It must be a child of the `Sensu::Plugin::Check::CLI` class
56
+ * It must be the only Sensu check defined in the configured plugin file
@@ -0,0 +1,256 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+ # frozen_string_literal: false
4
+ #
5
+ # check-meta-ruby.rb
6
+ #
7
+ # DESCRIPTION:
8
+ # Give this check a file with another Sensu check and a JSON config and it
9
+ # will dispatch threads to run that check multiple times and batch up the
10
+ # results.
11
+ #
12
+ # OUTPUT:
13
+ # plain text
14
+ #
15
+ # PLATFORMS:
16
+ # Linux
17
+ #
18
+ # DEPENDENCIES:
19
+ # gem: sensu-plugin
20
+ #
21
+ # USAGE:
22
+ # Run a check multiple times using a JSON config file:
23
+ #
24
+ # check-meta-ruby.rb -c check-http.rb -j /etc/sensu/http_checks.json
25
+ #
26
+ # Run a check multiple times using an inline JSON config string:
27
+ #
28
+ # check-meta-ruby.rb -c check-http.rb -j '[
29
+ # {"host": "pants.com", "port": 80}, {"host": "google.com", "port": 443}
30
+ # ]'
31
+ #
32
+ # NOTES:
33
+ #
34
+ # LICENSE:
35
+ # Copyright 2017, Socrata, Inc <sysadmin@socrata.com>
36
+ #
37
+ # Released under the same terms as Sensu (the MIT license); see LICENSE
38
+ # for details.
39
+ #
40
+
41
+ require 'json'
42
+ require 'sensu-plugin/check/cli'
43
+
44
+ #
45
+ # Check Meta
46
+ #
47
+ class CheckMetaRuby < Sensu::Plugin::Check::CLI
48
+ option :check,
49
+ short: '-c CHECK_SCRIPT',
50
+ long: '--check CHECK_SCRIPT',
51
+ description: 'The Sensu Ruby check to run multiple times',
52
+ required: true
53
+
54
+ option :json_config,
55
+ short: '-j CONFIG_STRING_OR_PATH',
56
+ long: '--json-config CONFIG_STRING_OR_PATH',
57
+ description: 'A JSON config string or path to a config file',
58
+ required: true
59
+
60
+ #
61
+ # Import the check we want to run and dispatch threads for every instance of
62
+ # it. Once all threads are complete, batch the results and return any
63
+ # non-ok status messages.
64
+ #
65
+ def run
66
+ require File.expand_path("../#{config[:check]}", $PROGRAM_NAME)
67
+
68
+ threads.each(&:join)
69
+
70
+ puts status_information unless status_information.empty?
71
+ summarize!
72
+ end
73
+
74
+ #
75
+ # Send all the information about this run to stdout and exit with the
76
+ # appropriate status.
77
+ #
78
+ def summarize!
79
+ %i(critical warning unknown).each do |status|
80
+ send(status, summary) unless results[status].empty?
81
+ end
82
+ ok(summary)
83
+ end
84
+
85
+ #
86
+ # Construct a string of the results of all the subchecks that have been run
87
+ # and not returned okay.
88
+ #
89
+ # @return [String] a long string of all the non-ok subcheck statuses
90
+ #
91
+ def status_information
92
+ %i(unknown warning critical).map do |status|
93
+ results[status].map { |result| "#{status.upcase}: #{result}" }
94
+ end.flatten.compact.join("\n")
95
+ end
96
+
97
+ #
98
+ # Construct the final summary message for our metacheck output.
99
+ #
100
+ # @return [String] a summary status of all the checks that have been run
101
+ #
102
+ def summary
103
+ "Results: #{results[:critical].size} critical, " \
104
+ "#{results[:warning].size} warning, " \
105
+ "#{results[:unknown].size} unknown, #{results[:ok].size} ok"
106
+ end
107
+
108
+ #
109
+ # Find and patch the Sensu check class that was imported from the
110
+ # config[:check] file. Some assumptions are made here that will hopefully
111
+ # usually be valid.
112
+ #
113
+ # * The check is a child of Sensu::Plugin::Check::CLI
114
+ # * The check and we are the only check classes in Ruby's object space
115
+ #
116
+ def check_class
117
+ @check_class ||= begin
118
+ c = ObjectSpace.each_object(Class).find do |klass|
119
+ klass < Sensu::Plugin::Check::CLI && \
120
+ klass != self.class && \
121
+ !klass.ancestors.include?(self.class)
122
+ end
123
+ patch_class!(c)
124
+ c
125
+ end
126
+ end
127
+
128
+ #
129
+ # Patch a Sensu check class so it saves its output instead of sending it
130
+ # to stdout. Otherwise the threading screws up the rendering.
131
+ #
132
+ # @param klass [Sensu::Plugin::Check::CLI] the check class to patch
133
+ #
134
+ def patch_class!(klass)
135
+ klass.class_eval do
136
+ #
137
+ # Make the check status accessible as a reader method.
138
+ #
139
+ attr_reader :status
140
+
141
+ #
142
+ # Patch the output method so it returns the output string instead of
143
+ # sending it to stdout.
144
+ #
145
+ def output(msg = @message)
146
+ @output ||= self.class.check_name + (msg ? ": #{msg}" : '')
147
+ end
148
+ end
149
+ end
150
+
151
+ #
152
+ # Work through the array generated from our JSON config and return an array
153
+ # of corresponding thread objects.
154
+ #
155
+ #
156
+ # @return [Array<Thread>] an array of threads to run
157
+ #
158
+ def threads
159
+ parsed_config.map { |check_opts| thread_for(check_opts) }
160
+ end
161
+
162
+ #
163
+ # Return a parsed and symbolized version of our JSON config.
164
+ #
165
+ # @return [Hash] the metacheck config
166
+ #
167
+ def parsed_config
168
+ @parsed_config ||= begin
169
+ JSON.parse(config[:json_config], symbolize_names: true)
170
+ rescue JSON::ParserError
171
+ JSON.parse(File.read(config[:json_config]),
172
+ symbolize_names: true)
173
+ end
174
+ end
175
+
176
+ #
177
+ # Build a new thread object for a given set of check options. The options
178
+ # will be parsed into the command line arguments for the check, e.g.
179
+ #
180
+ # {
181
+ # host: 'example.com',
182
+ # port: 443,
183
+ # c: /etc/config.conf,
184
+ # do_something: nil
185
+ # }
186
+ #
187
+ # will get translated into the CLI arguments:
188
+ #
189
+ # --host example.com --port 443 -c /etc/config.conf --do-something
190
+ #
191
+ # @param check_opts [Hash] a hash of switches and their values.
192
+ #
193
+ def thread_for(check_opts)
194
+ Thread.new do
195
+ chk = check_class.new(check_args_for(check_opts))
196
+ run_check!(chk)
197
+ end
198
+ end
199
+
200
+ #
201
+ # Accept and run a given sub-check object, catch its resultant status and
202
+ # output, and preserve that data for later processing.
203
+ #
204
+ # @param chk [Sensu::Plugin::Check::CLI] a Sensu check object
205
+ #
206
+ def run_check!(chk)
207
+ chk.run
208
+ rescue SystemExit => e
209
+ results[exit_statuses[e.status]] << chk.output
210
+ rescue StandardError => e
211
+ # Though an argument could be made to treat other exceptions as
212
+ # critical instead of unknown.
213
+ results[:unknown] << e.to_s
214
+ end
215
+
216
+ #
217
+ # Invert Sensu's exit codes hash so it's an array of exit codes to statuses,
218
+ # downcased and symbolized, e.g. exit_status[0] => :ok.
219
+ #
220
+ # @return [Array<Symbol>] an inverted index of Sensu exit codes and statues
221
+ #
222
+ def exit_statuses
223
+ Sensu::Plugin::EXIT_CODES.each_with_object([]) do |(status, code), arr|
224
+ arr[code] = status.downcase.to_sym
225
+ end
226
+ end
227
+
228
+ #
229
+ # Construct the arg values for a check call based on a given set of options.
230
+ # Adhere to the following rules:
231
+ #
232
+ # * A single character option translates to "-o arg"
233
+ # * A >1 character option translates to "--option arg"
234
+ # * An option with a nil value translates to "--option"
235
+ #
236
+ # @param check_opts [Hash] a hash of check flags and values (or nil)
237
+ #
238
+ # @return [Array<String>] the correct argv for the given check options
239
+ #
240
+ def check_args_for(check_opts)
241
+ check_opts.each_with_object([]) do |(k, v), arr|
242
+ arr << (k.length == 1 ? "-#{k}" : "--#{k.to_s.tr('_', '-')}")
243
+ arr << v.to_s unless v.nil?
244
+ end
245
+ end
246
+
247
+ #
248
+ # Set up an object-level hash of result arrays so we can save the output
249
+ # from every check thread.
250
+ #
251
+ # @return [Hash] A hash of Sensu statuses => check output messages
252
+ #
253
+ def results
254
+ @results ||= { ok: [], warning: [], critical: [], unknown: [] }
255
+ end
256
+ end
@@ -0,0 +1,4 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: false
3
+
4
+ require 'sensu_plugins_meta/version'
@@ -0,0 +1,11 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: false
3
+
4
+ module SensuPluginsMeta
5
+ module Version
6
+ MAJOR = 0
7
+ MINOR = 1
8
+ PATCH = 0
9
+ VER_STRING = [MAJOR, MINOR, PATCH].compact.join('.')
10
+ end
11
+ end
metadata ADDED
@@ -0,0 +1,267 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sensu-plugins-meta
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Sensu-Plugins and contributors
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
+ name: sensu-plugin
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.7'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.7'
41
+ - !ruby/object:Gem::Dependency
42
+ name: coveralls
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.8'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.8'
55
+ - !ruby/object:Gem::Dependency
56
+ name: simplecov
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.12'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.12'
69
+ - !ruby/object:Gem::Dependency
70
+ name: simplecov-console
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.4'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.4'
83
+ - !ruby/object:Gem::Dependency
84
+ name: github-markup
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.3'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.3'
97
+ - !ruby/object:Gem::Dependency
98
+ name: pry
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '0.10'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '0.10'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rake
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '12.0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '12.0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: redcarpet
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '3.2'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '3.2'
139
+ - !ruby/object:Gem::Dependency
140
+ name: rspec
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '3.1'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '3.1'
153
+ - !ruby/object:Gem::Dependency
154
+ name: rubocop
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '0.47'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: '0.47'
167
+ - !ruby/object:Gem::Dependency
168
+ name: yard
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: '0.8'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: '0.8'
181
+ - !ruby/object:Gem::Dependency
182
+ name: test-kitchen
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - "~>"
186
+ - !ruby/object:Gem::Version
187
+ version: '1.6'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - "~>"
193
+ - !ruby/object:Gem::Version
194
+ version: '1.6'
195
+ - !ruby/object:Gem::Dependency
196
+ name: kitchen-vagrant
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - "~>"
200
+ - !ruby/object:Gem::Version
201
+ version: '1.0'
202
+ type: :development
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - "~>"
207
+ - !ruby/object:Gem::Version
208
+ version: '1.0'
209
+ - !ruby/object:Gem::Dependency
210
+ name: kitchen-docker
211
+ requirement: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - "~>"
214
+ - !ruby/object:Gem::Version
215
+ version: '2.6'
216
+ type: :development
217
+ prerelease: false
218
+ version_requirements: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - "~>"
221
+ - !ruby/object:Gem::Version
222
+ version: '2.6'
223
+ description: This plugin provides a way to call other check plugins multiple times
224
+ as a single check.
225
+ email: "<sensu-users@googlegroups.com>"
226
+ executables:
227
+ - check-meta-ruby.rb
228
+ extensions: []
229
+ extra_rdoc_files: []
230
+ files:
231
+ - CHANGELOG.md
232
+ - LICENSE
233
+ - README.md
234
+ - bin/check-meta-ruby.rb
235
+ - lib/sensu_plugins_meta.rb
236
+ - lib/sensu_plugins_meta/version.rb
237
+ homepage: https://github.com/sensu-plugins/sensu-plugins-meta
238
+ licenses:
239
+ - MIT
240
+ metadata:
241
+ maintainer: sensu-plugin
242
+ development_status: active
243
+ production_status: unstable - testing recommended
244
+ release_draft: 'false'
245
+ release_prerelease: 'false'
246
+ post_install_message: You can use the embedded Ruby by setting EMBEDDED_RUBY=true
247
+ in /etc/default/sensu
248
+ rdoc_options: []
249
+ require_paths:
250
+ - lib
251
+ required_ruby_version: !ruby/object:Gem::Requirement
252
+ requirements:
253
+ - - ">="
254
+ - !ruby/object:Gem::Version
255
+ version: 2.0.0
256
+ required_rubygems_version: !ruby/object:Gem::Requirement
257
+ requirements:
258
+ - - ">="
259
+ - !ruby/object:Gem::Version
260
+ version: '0'
261
+ requirements: []
262
+ rubyforge_project:
263
+ rubygems_version: 2.6.8
264
+ signing_key:
265
+ specification_version: 4
266
+ summary: Sensu plugins for batching multiple checks as one
267
+ test_files: []