Module: check_mk
Branch: master
Commit: f6f33997875531bbf925c3c7a368db7f4d2e959b
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=f6f33997875531…
Author: Tom Baerwinkel <tb(a)mathias-kettner.de>
Date: Sun Mar 31 15:57:34 2019 +0200
k8s_service_port: new check to monitor ports of Kubernetes services
Change-Id: I8d61af850f3deec8134e2c6f854a34e1281583ab
---
checkman/k8s_service_port | 14 ++++
checks/k8s_service_port | 71 +++++++++++++++++
cmk/gui/plugins/wato/check_parameters/k8s_port.py | 97 +++++++++++++++++++++++
cmk/special_agents/agent_kubernetes.py | 5 +-
4 files changed, 185 insertions(+), 2 deletions(-)
diff --git a/checkman/k8s_service_port b/checkman/k8s_service_port
new file mode 100644
index 0000000..28f007b
--- /dev/null
+++ b/checkman/k8s_service_port
@@ -0,0 +1,14 @@
+title: Kubernetes service ports
+agents: kubernetes
+catalog: containerization/kubernetes
+license: GPL
+distribution: check_mk
+description:
+ This check monitors the ports of a Kubernetes service.
+ Levels for expected values can be set via WATO.
+
+inventory:
+ One service per port is created.
+
+item:
+ The name of the port if given otherwise the port number.
\ No newline at end of file
diff --git a/checks/k8s_service_port b/checks/k8s_service_port
new file mode 100644
index 0000000..e6b875e
--- /dev/null
+++ b/checks/k8s_service_port
@@ -0,0 +1,71 @@
+#!/usr/bin/python
+# -*- encoding: utf-8; py-indent-offset: 4 -*-
+# +------------------------------------------------------------------+
+# | ____ _ _ __ __ _ __ |
+# | / ___| |__ ___ ___| | __ | \/ | |/ / |
+# | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
+# | | |___| | | | __/ (__| < | | | | . \ |
+# | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
+# | |
+# | Copyright Mathias Kettner 2018 mk(a)mathias-kettner.de |
+# +------------------------------------------------------------------+
+#
+# This file is part of Check_MK.
+# The official homepage is at http://mathias-kettner.de/check_mk.
+#
+# check_mk is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation in version 2. check_mk is distributed
+# in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
+# out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE. See the GNU General Public License for more de-
+# tails. You should have received a copy of the GNU General Public
+# License along with GNU Make; see the file COPYING. If not, write
+# to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+# Boston, MA 02110-1301 USA.
+
+
+def k8s_check_value(value, expected, infotext_template):
+ state = 0
+ infotext = infotext_template % value
+ if expected is not None and value != expected:
+ state = 2
+ infotext += ' (expected %s)' % expected
+ return state, infotext
+
+
+@get_parsed_item_data
+def check_k8s_service_port(item, params, parsed):
+ yield k8s_check_value(
+ parsed['port'],
+ params.get('port'),
+ 'Port: %s',
+ )
+ yield k8s_check_value(
+ parsed['target_port'],
+ params.get('target_port'),
+ 'Target port: %s',
+ )
+
+ if parsed['node_port']:
+ yield k8s_check_value(
+ parsed['node_port'],
+ params.get('node_port'),
+ 'Node port: %s',
+ )
+
+ yield k8s_check_value(
+ parsed['protocol'],
+ params.get('protocol'),
+ 'Protocol: %s',
+ )
+
+
+check_info['k8s_service_port'] = {
+ 'parse_function': parse_k8s,
+ 'inventory_function': discover(),
+ 'check_function': check_k8s_service_port,
+ 'service_description': 'Port %s',
+ 'group': 'k8s_port',
+ 'includes': ['k8s.include'],
+}
diff --git a/cmk/gui/plugins/wato/check_parameters/k8s_port.py b/cmk/gui/plugins/wato/check_parameters/k8s_port.py
new file mode 100644
index 0000000..145b210
--- /dev/null
+++ b/cmk/gui/plugins/wato/check_parameters/k8s_port.py
@@ -0,0 +1,97 @@
+#!/usr/bin/python
+# -*- encoding: utf-8; py-indent-offset: 4 -*-
+# +------------------------------------------------------------------+
+# | ____ _ _ __ __ _ __ |
+# | / ___| |__ ___ ___| | __ | \/ | |/ / |
+# | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
+# | | |___| | | | __/ (__| < | | | | . \ |
+# | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
+# | |
+# | Copyright Mathias Kettner 2014 mk(a)mathias-kettner.de |
+# +------------------------------------------------------------------+
+#
+# This file is part of Check_MK.
+# The official homepage is at http://mathias-kettner.de/check_mk.
+#
+# check_mk is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation in version 2. check_mk is distributed
+# in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
+# out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE. See the GNU General Public License for more de-
+# tails. You should have received a copy of the GNU General Public
+# License along with GNU Make; see the file COPYING. If not, write
+# to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+# Boston, MA 02110-1301 USA.
+
+from cmk.gui.i18n import _
+from cmk.gui.valuespec import (
+ Dictionary,
+ DropdownChoice,
+ Integer,
+ TextAscii,
+)
+
+from cmk.gui.plugins.wato import (
+ CheckParameterRulespecWithItem,
+ rulespec_registry,
+ RulespecGroupCheckParametersApplications,
+)
+
+
+(a)rulespec_registry.register
+class RulespecCheckgroupParametersK8SResources(CheckParameterRulespecWithItem):
+ @property
+ def group(self):
+ return RulespecGroupCheckParametersApplications
+
+ @property
+ def check_group_name(self):
+ return "k8s_port"
+
+ @property
+ def title(self):
+ return _("Kubernetes Port")
+
+ @property
+ def match_type(self):
+ return "dict"
+
+ @property
+ def parameter_valuespec(self):
+ return Dictionary(
+ elements=[
+ ('port', Integer(
+ title=_('Port'),
+ minvalue=0,
+ maxvalue=65535,
+ )),
+ ('target_port', Integer(
+ title=_('Target port'),
+ minvalue=0,
+ maxvalue=65535,
+ )),
+ ('node_port', Integer(
+ title=_('Node port'),
+ minvalue=0,
+ maxvalue=65535,
+ )),
+ ('protocol',
+ DropdownChoice(
+ title=_('Protocol'),
+ choices=[
+ ('TCP', _('TCP')),
+ ('UDP', _('UDP')),
+ ('HTTP', _('HTTP')),
+ ('PROXY', _('PROXY')),
+ ('SCTP', _('SCTP')),
+ ],
+ )),
+ ],)
+
+ @property
+ def item_spec(self):
+ return TextAscii(
+ title=_("Port"),
+ help=_("Name or number of the port"),
+ )
diff --git a/cmk/special_agents/agent_kubernetes.py b/cmk/special_agents/agent_kubernetes.py
index 036c08d..351e152 100644
--- a/cmk/special_agents/agent_kubernetes.py
+++ b/cmk/special_agents/agent_kubernetes.py
@@ -311,7 +311,8 @@ class Service(Metadata):
def ports(self):
# port is the only field that is not optional
return {
- port.port: {
+ port.name if port.name else port.port: {
+ 'port': port.port,
'name': port.name,
'protocol': port.protocol,
'target_port': port.target_port,
@@ -1032,7 +1033,7 @@ class ApiData(object):
g.join('labels', self.services.labels())
g.join('k8s_selector', self.services.selector())
g.join('k8s_service_info', self.services.infos())
- g.join('k8s_service_ports', self.services.ports())
+ g.join('k8s_service_port', self.services.ports())
pod_names = {
service_name: {
'names': [pod.name for pod in pods]
Module: check_mk
Branch: master
Commit: f8447dade9d36c3f8332d21904f65ab99dd5cc4a
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=f8447dade9d36c…
Author: Moritz Kiemer <mo(a)mathias-kettner.de>
Date: Thu Mar 28 09:07:36 2019 +0100
check_http: add validation
We now explicitly check for a invalid configuration
that never worked anyway.
CMK-1873
Change-Id: I16e00a7bf8c6d408f2f17a6c116ebf6343cb632f
---
checks/check_http | 4 +---
cmk/gui/plugins/wato/active_checks.py | 8 ++++++++
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/checks/check_http b/checks/check_http
index 812e157..ebeb13e 100644
--- a/checks/check_http
+++ b/checks/check_http
@@ -137,9 +137,7 @@ def _url_args(host, proxy, settings):
args += ["-H", host.address]
else:
args += ["-I", host.address]
- # TODO: what if we have a proxy, *and* virthost?
- # This was not possible earlier, so for now
- # ignore 'virthost' in that case.
+ # Proxy *and* virthost is not allowed
if "virthost" in settings:
args += ["-H", settings["virthost"]]
diff --git a/cmk/gui/plugins/wato/active_checks.py b/cmk/gui/plugins/wato/active_checks.py
index 0a932d9..c5cc2c4 100644
--- a/cmk/gui/plugins/wato/active_checks.py
+++ b/cmk/gui/plugins/wato/active_checks.py
@@ -1276,6 +1276,7 @@ class RulespecActiveChecksHttp(HostRulespec):
)),
],
required_keys=["name", "host", "mode"],
+ validate=self._validate_all,
),
forth=self._transform_check_http,
)
@@ -1285,6 +1286,13 @@ class RulespecActiveChecksHttp(HostRulespec):
if url.scheme or url.netloc or not url.path.startswith('/'):
raise MKUserError(varprefix, _("Invalid URI (see help for details)"))
+ def _validate_all(self, value, varprefix):
+ _name, mode = value['mode']
+ if 'proxy' in value and 'virthost' in mode:
+ msg = _("Unfortunately, using a proxy and a virtual host is not supported (try '%s')."
+ ) % _("Host settings")
+ raise MKUserError(varprefix, msg)
+
def _transform_check_http(self, params):
if isinstance(params, dict):
return params
Module: check_mk
Branch: master
Commit: e576f47b285645dbe308598be617701edc0aafe3
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=e576f47b285645…
Author: Tom Baerwinkel <tb(a)mathias-kettner.de>
Date: Mon Apr 1 10:02:29 2019 +0200
7414 FIX mail: fix bug with multiple recipients and synchronous delivery
If Email notifictations were sent to multiple recipients and synchronous
delivery via SMTP was used mail servers may process the recipients of
Emails wrong. This may result in failed notifications or only partially
delivered Emails. The exact behaviour depends on the mail server.
Change-Id: Ifd252ca68be11239d905bc8c9d5c74f7a4e87e59
---
.werks/7414 | 14 ++++++++++++++
cmk/notification_plugins/mail.py | 2 +-
2 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/.werks/7414 b/.werks/7414
new file mode 100644
index 0000000..1fab02a
--- /dev/null
+++ b/.werks/7414
@@ -0,0 +1,14 @@
+Title: mail: fix bug with multiple recipients and synchronous delivery
+Level: 1
+Component: notifications
+Class: fix
+Compatible: compat
+Edition: cre
+State: unknown
+Version: 1.6.0i1
+Date: 1554054898
+
+If Email notifictations were sent to multiple recipients and synchronous
+delivery via SMTP was used mail servers may process the recipients of
+Emails wrong. This may result in failed notifications or only partially
+delivered Emails. The exact behaviour depends on the mail server.
diff --git a/cmk/notification_plugins/mail.py b/cmk/notification_plugins/mail.py
index 5403488..049f9c7 100644
--- a/cmk/notification_plugins/mail.py
+++ b/cmk/notification_plugins/mail.py
@@ -614,7 +614,7 @@ def send_mail_smtp_impl(message, target, smarthost, from_address, context):
# the first parameter here is actually used in the return_path header
try:
- conn.sendmail(from_address, target, message.as_string())
+ conn.sendmail(from_address, target.split(','), message.as_string())
sys.stdout.write("success %d - %s\n" % (conn.last_code, conn.last_repl))
finally:
conn.quit()
Module: check_mk
Branch: master
Commit: 5a6b5fa1d59a6fe2157e14dc6cc272dd27e72d26
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=5a6b5fa1d59a6f…
Author: Lars Michelsen <lm(a)mathias-kettner.de>
Date: Thu Mar 28 20:42:14 2019 +0100
Cleaned up core specific autochecks loading
The CMC check helper specific autocheck file hierarchy was used when a
"world" parameter was set to "active". This parameter was propagated
several levels through the code to tell
cmk_base.autochecks.read_autochecks_of() to use a helper specific path.
Since each invokation of the Check_MK base code is either a helper or
not this can be swapped per execution in a central place.
This central place is the keepalive.enable() function now. It simply
changes the global path definitions in keepalive mode to point to
the keepalive helper specific directory.
CMK-1818
Change-Id: Ia58642b4e20a097aeb619daab52fb788b97a42f0
---
cmk_base/autochecks.py | 10 +++-------
cmk_base/check_table.py | 15 ++++-----------
cmk_base/checking.py | 10 ++--------
cmk_base/config.py | 9 ++++-----
cmk_base/data_sources/__init__.py | 5 +----
5 files changed, 14 insertions(+), 35 deletions(-)
diff --git a/cmk_base/autochecks.py b/cmk_base/autochecks.py
index 54a5ef8..74ff933 100644
--- a/cmk_base/autochecks.py
+++ b/cmk_base/autochecks.py
@@ -38,19 +38,14 @@ import cmk_base.console
# Read automatically discovered checks of one host.
-# world: "config" -> File in var/check_mk/autochecks
-# "active" -> Copy in var/check_mk/core/autochecks
# Returns a table with three columns:
# 1. check_plugin_name
# 2. item
# 3. parameters evaluated!
# TODO: use store.load_data_from_file()
# TODO: Common code with parse_autochecks_file? Cleanup.
-def read_autochecks_of(hostname, world="config"):
- if world == "config":
- basedir = cmk.utils.paths.autochecks_dir
- else:
- basedir = cmk.utils.paths.var_dir + "/core/autochecks"
+def read_autochecks_of(hostname):
+ basedir = cmk.utils.paths.autochecks_dir
filepath = basedir + '/' + hostname + '.mk'
if not os.path.exists(filepath):
@@ -58,6 +53,7 @@ def read_autochecks_of(hostname, world="config"):
check_config = cmk_base.config.get_check_variables()
try:
+ cmk_base.console.vverbose("Loading autochecks from %s\n", filepath)
autochecks_raw = eval(file(filepath).read(), check_config, check_config)
except SyntaxError as e:
cmk_base.console.verbose("Syntax error in file %s: %s\n", filepath, e, stream=sys.stderr)
diff --git a/cmk_base/check_table.py b/cmk_base/check_table.py
index 0e2a5f2..8df8934 100644
--- a/cmk_base/check_table.py
+++ b/cmk_base/check_table.py
@@ -46,7 +46,6 @@ import cmk_base.check_api_utils as check_api_utils
def get_check_table(hostname,
remove_duplicates=False,
use_cache=True,
- world='config',
skip_autochecks=False,
filter_mode=None,
skip_ignored=True):
@@ -162,7 +161,7 @@ def get_check_table(hostname,
# Now process all entries that are specific to the host
# in search (single host) or that might match the host.
if not skip_autochecks:
- for entry in config_cache.get_autochecks_of(hostname, world):
+ for entry in config_cache.get_autochecks_of(hostname):
handle_entry(entry)
for entry in single_host_checks.get(hostname, []):
@@ -178,7 +177,7 @@ def get_check_table(hostname,
for node in config.nodes_of(hostname):
node_checks = single_host_checks.get(node, [])
if not skip_autochecks:
- node_checks = node_checks + config_cache.get_autochecks_of(node, world)
+ node_checks = node_checks + config_cache.get_autochecks_of(node)
for entry in node_checks:
if len(entry) == 4:
entry = entry[1:] # drop hostname from single_host_checks
@@ -209,11 +208,10 @@ def get_check_table(hostname,
def get_precompiled_check_table(hostname,
remove_duplicates=True,
- world="config",
filter_mode=None,
skip_ignored=True):
host_checks = get_sorted_check_table(
- hostname, remove_duplicates, world, filter_mode=filter_mode, skip_ignored=skip_ignored)
+ hostname, remove_duplicates, filter_mode=filter_mode, skip_ignored=skip_ignored)
precomp_table = []
for check_plugin_name, item, params, description, _unused_deps in host_checks:
# make these globals available to the precompile function
@@ -258,18 +256,13 @@ def remove_duplicate_checks(check_table):
# if there already is a TCP based one with the same
# description. E.g: df vs hr_fs.
# TODO: Clean this up!
-def get_sorted_check_table(hostname,
- remove_duplicates=False,
- world="config",
- filter_mode=None,
- skip_ignored=True):
+def get_sorted_check_table(hostname, remove_duplicates=False, filter_mode=None, skip_ignored=True):
# Convert from dictionary into simple tuple list. Then sort
# it according to the service dependencies.
unsorted = [(checkname, item, params, descr, deps)
for ((checkname, item), (params, descr, deps)) in get_check_table(
hostname,
remove_duplicates=remove_duplicates,
- world=world,
filter_mode=filter_mode,
skip_ignored=skip_ignored).items()]
diff --git a/cmk_base/checking.py b/cmk_base/checking.py
index 6519db0..cc615ac 100644
--- a/cmk_base/checking.py
+++ b/cmk_base/checking.py
@@ -199,10 +199,7 @@ def _do_all_checks_on_host(sources, hostname, ipaddress, only_check_plugin_names
filter_mode = "include_clustered"
table = check_table.get_precompiled_check_table(
- hostname,
- remove_duplicates=True,
- filter_mode=filter_mode,
- world="active" if _in_keepalive_mode() else "config")
+ hostname, remove_duplicates=True, filter_mode=filter_mode)
# When check types are specified via command line, enforce them. Otherwise use the
# list of checks defined by the check table.
@@ -424,10 +421,7 @@ def _evaluate_timespecific_entry(entry):
def is_manual_check(hostname, check_plugin_name, item):
manual_checks = check_table.get_check_table(
- hostname,
- remove_duplicates=True,
- world="active" if _in_keepalive_mode() else "config",
- skip_autochecks=True)
+ hostname, remove_duplicates=True, skip_autochecks=True)
return (check_plugin_name, item) in manual_checks
diff --git a/cmk_base/config.py b/cmk_base/config.py
index b2ed2b8..a8e606c 100644
--- a/cmk_base/config.py
+++ b/cmk_base/config.py
@@ -3007,13 +3007,12 @@ class ConfigCache(object):
return hosts_in_folder
return self._folder_host_lookup[cache_id]
- def get_autochecks_of(self, hostname, world):
+ def get_autochecks_of(self, hostname):
try:
- return self._autochecks_cache[world][hostname]
+ return self._autochecks_cache[hostname]
except KeyError:
- self._autochecks_cache.setdefault(world, {})
- result = cmk_base.autochecks.read_autochecks_of(hostname, world)
- self._autochecks_cache[world][hostname] = result
+ result = cmk_base.autochecks.read_autochecks_of(hostname)
+ self._autochecks_cache[hostname] = result
return result
def section_name_of(self, section):
diff --git a/cmk_base/data_sources/__init__.py b/cmk_base/data_sources/__init__.py
index 896cd3e..36e9e88 100644
--- a/cmk_base/data_sources/__init__.py
+++ b/cmk_base/data_sources/__init__.py
@@ -259,10 +259,7 @@ class DataSources(object):
node_ipaddress = ip_lookup.lookup_ip_address(node_hostname)
table = check_table.get_precompiled_check_table(
- node_hostname,
- remove_duplicates=True,
- filter_mode="only_clustered",
- world="active" if _in_keepalive_mode() else "config")
+ node_hostname, remove_duplicates=True, filter_mode="only_clustered")
node_data_sources = DataSources(node_hostname, node_ipaddress)
node_data_sources.enforce_check_plugin_names(set([e[0] for e in table]))