sensu-plugins-kubernetes-reactiveops 0.1.0

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.
@@ -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: []