sensu-plugins-kubernetes-reactiveops 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,87 @@
1
+ #! /usr/bin/env ruby
2
+ #
3
+ # handler-kube-pod
4
+ #
5
+ # DESCRIPTION:
6
+ # => Deletes pods from the k8s cluster and sensu, intended to be used as a
7
+ # keepalive handler.
8
+ #
9
+ # OUTPUT:
10
+ # plain text
11
+ #
12
+ # PLATFORMS:
13
+ # Linux
14
+ #
15
+ # DEPENDENCIES:
16
+ # gem: sensu-plugin
17
+ # gem: kube-client
18
+ #
19
+ # USAGE:
20
+ # -j JSONCONFIG - The settings section to use
21
+ #
22
+ # NOTES:
23
+ #
24
+ # LICENSE:
25
+ # Justin McCarty <jmccarty3@gmail.com>
26
+ # Released under the same terms as Sensu (the MIT license); see LICENSE
27
+ # for details.
28
+ #
29
+
30
+ require 'sensu-handler'
31
+ require 'sensu-plugins-kubernetes/client'
32
+
33
+ class KubePod < Sensu::Handler
34
+ include Sensu::Plugins::Kubernetes::Client
35
+
36
+ option :json_config,
37
+ description: 'Configuration section name',
38
+ short: '-j JSONCONFIG',
39
+ long: '--json JSONCONFIG',
40
+ default: 'k8s'
41
+
42
+ def client_config
43
+ defaults = {
44
+ server: ENV['KUBERNETES_MASTER'],
45
+ version: 'v1'
46
+ }
47
+ h = settings[config[:json_config]]
48
+ if h.is_a?(Hash)
49
+ # Maintain backwards compatibility
50
+ h[:server] ||= h[:api_server]
51
+ h[:version] ||= h[:api_version]
52
+ # And merge
53
+ defaults.merge!(h)
54
+ else
55
+ defaults
56
+ end
57
+ end
58
+
59
+ def handle
60
+ puts 'K8 handler'
61
+ response = api_request(:DELETE, '/clients/' + @event['client']['name']).code
62
+ deletion_status(response)
63
+ begin
64
+ client = kubeclient(client_config)
65
+ client.delete_pod @event['client']['name']
66
+ rescue ArgumentError => e
67
+ puts "[Kube Pod] Invalid settings: #{e.message}"
68
+ rescue KubeException => e
69
+ puts "[Kube Pod] KubeException: #{e.message}"
70
+ rescue Exception => e # rubocop:disable Lint/RescueException
71
+ puts "[Kube Pod] Unknown error #{e}"
72
+ end
73
+ end
74
+
75
+ def deletion_status(code)
76
+ case code
77
+ when '202'
78
+ puts "[Kube Pod] 202: Successfully deleted Sensu client: #{@event['client']['name']}"
79
+ when '404'
80
+ puts "[Kube Pod] 404: Unable to delete #{@event['client']['name']}, doesn't exist!"
81
+ when '500'
82
+ puts "[Kube Pod] 500: Miscellaneous error when deleting #{@event['client']['name']}"
83
+ else
84
+ puts "[Kube Pod] #{code}: Completely unsure of what happened!"
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,59 @@
1
+ #! /usr/bin/env ruby
2
+ #
3
+ # pod-metrics
4
+ #
5
+ # DESCRIPTION:
6
+ # Will give pod counts from all the exposed services
7
+ #
8
+ # OUTPUT:
9
+ # metric data
10
+ #
11
+ # PLATFORMS:
12
+ # Linux
13
+ #
14
+ # DEPENDENCIES:
15
+ # gem: sensu-plugin
16
+ # gem: kube-client
17
+ #
18
+ # USAGE:
19
+ #
20
+ # NOTES:
21
+ #
22
+ # LICENSE:
23
+ # Copyright 2016 Chris McFee <cmcfee@kent.edu>
24
+ # Released under the same terms as Sensu (the MIT license); see LICENSE
25
+ # for details.
26
+ require 'sensu-plugins-kubernetes/cli'
27
+ require 'sensu-plugin/metric/cli'
28
+ require 'uri'
29
+
30
+ class PodsMetrics < Sensu::Plugin::Metric::CLI::Graphite
31
+ @options = Sensu::Plugins::Kubernetes::CLI.options.dup
32
+
33
+ def run
34
+ config[:scheme] = "#{URI(config[:api_server]).host}.pods"
35
+ count = {}
36
+ client = Sensu::Plugins::Kubernetes::CLI.new.client
37
+ services = client.get_services
38
+ services.each do |s|
39
+ selector_key = []
40
+ count[s.metadata.name] = 0
41
+ services.delete(s.metadata.name)
42
+ s.spec.selector.to_h.each do |k, v|
43
+ selector_key << "#{k}=#{v}"
44
+ end
45
+ pod = nil
46
+ begin
47
+ pod = client.get_pods(label_selector: selector_key.join(',').to_s)
48
+ rescue KubeException => e
49
+ critical 'API error: ' << e.message
50
+ end
51
+ next if pod.nil?
52
+ pod.each do
53
+ count[s.metadata.name] += 1
54
+ end
55
+ end
56
+ count.each { |k, v| output "#{config[:scheme]}.#{k}", v }
57
+ ok
58
+ end
59
+ end
@@ -0,0 +1 @@
1
+ require 'sensu-plugins-kubernetes/version'
@@ -0,0 +1,96 @@
1
+ require 'sensu-plugin/check/cli'
2
+ require 'sensu-plugins-kubernetes/client.rb'
3
+
4
+ module Sensu
5
+ module Plugins
6
+ # Namespace for the Kubernetes sensu-plugin.
7
+ module Kubernetes
8
+ # Abstract base class for a Sensu check that also provides
9
+ # Kubernetes client connection support.
10
+ class CLI < Sensu::Plugin::Check::CLI
11
+ include Sensu::Plugins::Kubernetes::Client
12
+
13
+ option :api_server,
14
+ description: 'URL to API server',
15
+ short: '-s URL',
16
+ long: '--api-server',
17
+ default: ENV['KUBERNETES_MASTER']
18
+
19
+ option :api_version,
20
+ description: 'API version',
21
+ short: '-v VERSION',
22
+ long: '--api-version',
23
+ default: 'v1'
24
+
25
+ option :api_incluster,
26
+ description: 'Use service account authentication',
27
+ long: '--in-cluster',
28
+ boolean: true,
29
+ default: false
30
+
31
+ option :api_ca_file,
32
+ description: 'CA file to verify API server cert',
33
+ long: '--ca-file CA-FILE',
34
+ default: nil
35
+
36
+ option :api_client_cert,
37
+ description: 'Client cert to present',
38
+ long: '--cert CERT-FILE',
39
+ default: nil
40
+
41
+ option :api_client_key,
42
+ description: 'Client key for the client cert',
43
+ long: '--key KEY-FILE',
44
+ default: nil
45
+
46
+ option :api_user,
47
+ description: 'User with access to API',
48
+ short: '-u USER',
49
+ long: '--user',
50
+ default: nil
51
+
52
+ option :api_password,
53
+ description: 'If user is passed, also pass a password',
54
+ short: '-p PASSWORD',
55
+ long: '--password',
56
+ default: nil
57
+
58
+ option :api_token,
59
+ description: 'Bearer token for authorization',
60
+ short: '-t TOKEN',
61
+ long: '--token',
62
+ default: nil
63
+
64
+ option :api_token_file,
65
+ description: 'File containing bearer token for authorization',
66
+ long: '--token-file TOKEN-FILE',
67
+ default: nil
68
+
69
+ attr_reader :client
70
+
71
+ # Initializes the Sensu check by creating a Kubernetes client
72
+ # from the given options and will report a critical error if
73
+ # those arguments are incorrect.
74
+ def initialize
75
+ super()
76
+ begin
77
+ @client = kubeclient(
78
+ server: config[:api_server],
79
+ version: config[:api_version],
80
+ incluster: config[:api_incluster],
81
+ ca_file: config[:api_ca_file],
82
+ client_cert_file: config[:api_client_cert],
83
+ client_key_file: config[:api_client_key],
84
+ username: config[:api_user],
85
+ password: config[:api_password],
86
+ token: config[:api_token],
87
+ token_file: config[:api_token_file]
88
+ )
89
+ rescue ArgumentError => e
90
+ critical e.message
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,126 @@
1
+ require 'kubeclient'
2
+ require 'uri'
3
+
4
+ module Sensu
5
+ module Plugins
6
+ # Namespace for the Kubernetes sensu-plugin.
7
+ module Kubernetes
8
+ # A mixin module that provides Kubernetes client (kubeclient) support.
9
+ module Client
10
+ # The location of the service account provided CA.
11
+ # (if the cluster is configured to provide it)
12
+ INCLUSTER_CA_FILE =
13
+ '/var/run/secrets/kubernetes.io/serviceaccount/ca.crt'.freeze
14
+
15
+ # The location of the service account provided authentication token.
16
+ INCLUSTER_TOKEN_FILE =
17
+ '/var/run/secrets/kubernetes.io/serviceaccount/token'.freeze
18
+
19
+ # Creates a new Kubeclient::Client instance using the given SSL
20
+ # and authentication options (if any)
21
+ #
22
+ # @param [Hash] options The Kubernetes API connection details.
23
+ # @option options [String] :server URL to API server
24
+ # @option options [String] :version API version
25
+ # @option options [Boolean] :incluster
26
+ # Use service account authentication if true
27
+ # @option options [String] :ca_file
28
+ # CA file used to verify API server certificate
29
+ # @option options [String] :client_cert_file
30
+ # Client certificate file to present
31
+ # @option options [String] :client_key_file
32
+ # Client private key file for the client certificate
33
+ # @option options [String] :username
34
+ # Username with access to API
35
+ # @option options [String] :password
36
+ # If a username is passed, also pass a password
37
+ # @option options [String] :token
38
+ # The bearer token for Kubernetes authorization
39
+ # @option options [String] :token_file
40
+ # A file containing the bearer token for Kubernetes authorization
41
+ #
42
+ # @raise [ArgumentError] If an invalid option, or combination of options, is given.
43
+ # @raise [Errono::*] If there is a problem reading the client certificate or private key file.
44
+ # @raise [OpenSSL::X509::CertificateError] If there is a problem with the client certificate.
45
+ # @raise [OpenSSL::PKey::RSAError] If there is a problem with the client private key.
46
+ def kubeclient(options = {})
47
+ raise(ArgumentError, 'options must be a hash') unless options.is_a?(Hash)
48
+
49
+ api_server = options[:server]
50
+ api_version = options[:version]
51
+
52
+ ssl_options = {
53
+ ca_file: options[:ca_file]
54
+ }
55
+ auth_options = {
56
+ username: options[:username],
57
+ password: options[:password],
58
+ bearer_token: options[:token],
59
+ bearer_token_file: options[:token_file]
60
+ }
61
+
62
+ if [:client_cert_file, :client_key_file].count { |k| options[k] } == 1
63
+ raise ArgumentError, 'SSL requires both client cert and client key'
64
+ end
65
+
66
+ if options[:client_cert_file]
67
+ begin
68
+ ssl_options[:client_cert] = OpenSSL::X509::Certificate.new(File.read(options[:client_cert_file]))
69
+ rescue => e
70
+ raise e, "Unable to read client certificate: #{e}", e.backtrace
71
+ end
72
+ end
73
+
74
+ if options[:client_key_file]
75
+ begin
76
+ ssl_options[:client_key] = OpenSSL::PKey::RSA.new(File.read(options[:client_key_file]))
77
+ rescue => e
78
+ raise e, "Unable to read client key: #{e}", e.backtrace
79
+ end
80
+ end
81
+
82
+ if options[:incluster]
83
+ # Provide in-cluster defaults, if not already specified
84
+ # (following the kubernetes incluster config code, more or less)
85
+
86
+ # api-server
87
+ # TODO: use in-cluster DNS ??
88
+ if api_server.nil?
89
+ host = ENV['KUBERNETES_SERVICE_HOST']
90
+ port = ENV['KUBERNETES_SERVICE_PORT']
91
+ if host.nil? || port.nil?
92
+ raise ArgumentError, 'unable to load in-cluster configuration,'\
93
+ ' KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT'\
94
+ ' must be defined'
95
+ end
96
+ api_server = URI::HTTPS.build(host: host, port: port, path: '/api')
97
+ end
98
+
99
+ # ca file, but only if it exists
100
+ if ssl_options[:ca_file].nil? && File.exist?(INCLUSTER_CA_FILE)
101
+ # Readability/permission issues should be left to kubeclient
102
+ ssl_options[:ca_file] = INCLUSTER_CA_FILE
103
+ end
104
+
105
+ # token file
106
+ if auth_options[:bearer_token_file].nil?
107
+ auth_options[:bearer_token_file] = INCLUSTER_TOKEN_FILE
108
+ end
109
+ end
110
+
111
+ ssl_options[:verify_ssl] = ssl_options[:ca_file] ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE
112
+
113
+ begin
114
+ # new only throws errors on bad arguments
115
+ Kubeclient::Client.new(api_server, api_version,
116
+ ssl_options: ssl_options,
117
+ auth_options: auth_options)
118
+ rescue URI::InvalidURIError => e
119
+ # except for this one, which we'll re-wrap to make catching easier
120
+ raise ArgumentError, "Invalid API server: #{e}", e.backtrace
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,9 @@
1
+ module SensuPluginsKubernetes
2
+ module Version
3
+ MAJOR = 0
4
+ MINOR = 1
5
+ PATCH = 2
6
+
7
+ VER_STRING = [MAJOR, MINOR, PATCH].compact.join('.')
8
+ end
9
+ end
metadata ADDED
@@ -0,0 +1,242 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sensu-plugins-kubernetes-reactiveops
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-01-12 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: kubeclient
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 1.1.3
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 1.1.3
41
+ - !ruby/object:Gem::Dependency
42
+ name: activesupport
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "<"
46
+ - !ruby/object:Gem::Version
47
+ version: 5.0.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "<"
53
+ - !ruby/object:Gem::Version
54
+ version: 5.0.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.7'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.7'
69
+ - !ruby/object:Gem::Dependency
70
+ name: codeclimate-test-reporter
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: '10.5'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '10.5'
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: rubocop
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: 0.40.0
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: 0.40.0
153
+ - !ruby/object:Gem::Dependency
154
+ name: rspec
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '3.4'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: '3.4'
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
+ description: Provides monitoring for Kubernetes via Sensu
182
+ email: "<sensu-users@googlegroups.com>"
183
+ executables:
184
+ - check-kube-apiserver-available.rb
185
+ - check-kube-nodes-ready.rb
186
+ - check-kube-pods-pending.rb
187
+ - check-kube-pods-restarting.rb
188
+ - check-kube-pods-running.rb
189
+ - check-kube-pods-runtime.rb
190
+ - check-kube-service-available.rb
191
+ - handler-kube-pod.rb
192
+ - metrics-pods.rb
193
+ extensions: []
194
+ extra_rdoc_files: []
195
+ files:
196
+ - CHANGELOG.md
197
+ - LICENSE
198
+ - README.md
199
+ - bin/check-kube-apiserver-available.rb
200
+ - bin/check-kube-nodes-ready.rb
201
+ - bin/check-kube-pods-pending.rb
202
+ - bin/check-kube-pods-restarting.rb
203
+ - bin/check-kube-pods-running.rb
204
+ - bin/check-kube-pods-runtime.rb
205
+ - bin/check-kube-service-available.rb
206
+ - bin/handler-kube-pod.rb
207
+ - bin/metrics-pods.rb
208
+ - lib/sensu-plugins-kubernetes.rb
209
+ - lib/sensu-plugins-kubernetes/cli.rb
210
+ - lib/sensu-plugins-kubernetes/client.rb
211
+ - lib/sensu-plugins-kubernetes/version.rb
212
+ homepage: https://github.com/reactiveops/sensu-plugins-kubernetes
213
+ licenses:
214
+ - MIT
215
+ metadata:
216
+ maintainer: reactiveops
217
+ development_status: active
218
+ production_status: unstable - testing recommended
219
+ release_draft: 'false'
220
+ release_prerelease: 'false'
221
+ post_install_message: You can use the embedded Ruby by setting EMBEDDED_RUBY=true
222
+ in /etc/default/sensu
223
+ rdoc_options: []
224
+ require_paths:
225
+ - lib
226
+ required_ruby_version: !ruby/object:Gem::Requirement
227
+ requirements:
228
+ - - ">="
229
+ - !ruby/object:Gem::Version
230
+ version: 2.0.0
231
+ required_rubygems_version: !ruby/object:Gem::Requirement
232
+ requirements:
233
+ - - ">="
234
+ - !ruby/object:Gem::Version
235
+ version: '0'
236
+ requirements: []
237
+ rubyforge_project:
238
+ rubygems_version: 2.5.1
239
+ signing_key:
240
+ specification_version: 4
241
+ summary: Sensu plugins for kubernetes
242
+ test_files: []