Page MenuHomeDevCentral

D2809.diff
No OneTemporary

D2809.diff

diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -100,6 +100,36 @@
This check isn't intended to detect containers
run with other engines like `systemd-nspawn`.
+### check_software_version
+
+#### Run the check
+
+With argument, check if the specified software is up-to-date.
+
+Without argument, get a list of software from the configuration.
+
+If the software can't be found, an UNKNOWN exit code is returned.
+
+#### Available check types
+
+* check_software_version: a list of software to keep up-to-date
+
+#### Configuration example
+
+```yaml
+checks:
+ check_software_version:
+ - consul
+ - nomad
+ - terraform
+ - vagrant
+ - vault
+```
+
+#### Supported software
+
+* HashiCorp CLI products with a "version" subcommand, like Consul, Vault, Vagrant or TerraForm.
+
## Return values of checks
The checks use the standard Nagios/NRPE exit codes:
diff --git a/bin/check_software_version b/bin/check_software_version
new file mode 100755
--- /dev/null
+++ b/bin/check_software_version
@@ -0,0 +1,64 @@
+#!/usr/bin/env python3
+
+# -------------------------------------------------------------
+# Platform checks - Software version
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Project: Nasqueron
+# Description: Check if softwareversions is up-to-date
+# License: BSD-2-Clause
+# -------------------------------------------------------------
+
+
+import sys
+
+from platformchecks import exitcode
+from platformchecks.checks import SoftwareVersionCheck
+from platformchecks.config import parse_config
+
+
+# -------------------------------------------------------------
+# Configuration
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+
+def get_software_list():
+ return parse_config().get("checks", {}).get("check_software_version", [])
+
+
+# -------------------------------------------------------------
+# Application entry point
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+
+def run_all(software_list):
+ success = True
+ messages = []
+
+ for software in software_list:
+ check = SoftwareVersionCheck(software)
+ check_success, message = check.perform()
+
+ success &= check_success
+ messages.append(f"{software} {message}")
+
+ print("\n".join(messages))
+ return exitcode.ok_or_critical(success)
+
+
+def run(software):
+ check = SoftwareVersionCheck(software)
+ success, message = check.perform()
+
+ print(message)
+ return exitcode.ok_or_critical(success)
+
+
+if __name__ == "__main__":
+ argc = len(sys.argv)
+
+ if argc < 2:
+ exitCode = run_all(get_software_list())
+ else:
+ exitCode = run(sys.argv[1])
+
+ sys.exit(exitCode)
diff --git a/setup.cfg b/setup.cfg
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,6 +1,6 @@
[metadata]
name = platform-checks
-version = 0.1.3
+version = 0.2.0
author = Sébastien Santoro
author_email = dereckson@espace-win.org
description = Platform checks NRPE / Nagios
@@ -26,6 +26,7 @@
scripts =
bin/check_container_present
bin/check_http_200
+ bin/check_software_version
python_requires = >=3.6
install_requires =
PyYAML>=3.12,<7.0
diff --git a/src/platformchecks/checks/__init__.py b/src/platformchecks/checks/__init__.py
--- a/src/platformchecks/checks/__init__.py
+++ b/src/platformchecks/checks/__init__.py
@@ -1,2 +1,3 @@
from .http import HttpCheck
from .docker import DockerContainerCheck
+from .software import SoftwareVersionCheck
diff --git a/src/platformchecks/checks/software.py b/src/platformchecks/checks/software.py
new file mode 100644
--- /dev/null
+++ b/src/platformchecks/checks/software.py
@@ -0,0 +1,255 @@
+# -------------------------------------------------------------
+# Platform checks
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Project: Nasqueron
+# Description: Check if a softwareversions is up-to-date
+# License: BSD-2-Clause
+# -------------------------------------------------------------
+
+
+from .softwareversions import HashiCorpSoftwareVersionCheck
+
+
+class SoftwareVersionCheck:
+ def __init__(self, software):
+ self.software = software
+
+ def perform(self):
+ check = get_software_version_check(self.software)
+ return check.perform()
+
+
+def get_software_version_check(software):
+ group = get_software_group(software)
+ if group == "HashiCorp":
+ return HashiCorpSoftwareVersionCheck(software)
+
+ raise RuntimeError(f"Unknown software group for {software}")
+
+
+def get_software_group(software):
+ for group, candidates in SOFTWARE_GROUPS.items():
+ for candidate in candidates:
+ if candidate == software:
+ return group
+
+
+SOFTWARE_GROUPS = {
+ "HashiCorp": [
+ "atlas-upload-cli",
+ "boundary",
+ "boundary-desktop",
+ "boundary-worker",
+ "consul",
+ "consul-api-gateway",
+ "consul-aws",
+ "consul-cni",
+ "consul-dataplane",
+ "consul-ecs",
+ "consul-esm",
+ "consul-k8s",
+ "consul-k8s-control-plane",
+ "consul-lambda-extension",
+ "consul-lambda-registrator",
+ "consul-replicate",
+ "consul-template",
+ "consul-terraform-sync",
+ "docker-base",
+ "docker-basetool",
+ "envconsul",
+ "hc-install",
+ "hcdiag",
+ "hcs",
+ "levant",
+ "nomad",
+ "nomad-autoscaler",
+ "nomad-device-nvidia",
+ "nomad-driver-ecs",
+ "nomad-driver-lxc",
+ "nomad-driver-podman",
+ "nomad-pack",
+ "otto",
+ "packer",
+ "sentinel",
+ "serf",
+ "terraform",
+ "terraform-ls",
+ "terraform-provider-aci",
+ "terraform-provider-acme",
+ "terraform-provider-ad",
+ "terraform-provider-akamai",
+ "terraform-provider-alicloud",
+ "terraform-provider-archive",
+ "terraform-provider-arukas",
+ "terraform-provider-atlas",
+ "terraform-provider-auth0",
+ "terraform-provider-avi",
+ "terraform-provider-aviatrix",
+ "terraform-provider-aws",
+ "terraform-provider-awscc",
+ "terraform-provider-azure",
+ "terraform-provider-azuread",
+ "terraform-provider-azuredevops",
+ "terraform-provider-azurerm",
+ "terraform-provider-azurestack",
+ "terraform-provider-baiducloud",
+ "terraform-provider-bigip",
+ "terraform-provider-bitbucket",
+ "terraform-provider-boundary",
+ "terraform-provider-brightbox",
+ "terraform-provider-checkpoint",
+ "terraform-provider-chef",
+ "terraform-provider-cherryservers",
+ "terraform-provider-circonus",
+ "terraform-provider-ciscoasa",
+ "terraform-provider-clc",
+ "terraform-provider-cloudamqp",
+ "terraform-provider-cloudflare",
+ "terraform-provider-cloudinit",
+ "terraform-provider-cloudscale",
+ "terraform-provider-cloudstack",
+ "terraform-provider-cobbler",
+ "terraform-provider-cohesity",
+ "terraform-provider-constellix",
+ "terraform-provider-consul",
+ "terraform-provider-datadog",
+ "terraform-provider-digitalocean",
+ "terraform-provider-dme",
+ "terraform-provider-dns",
+ "terraform-provider-dnsimple",
+ "terraform-provider-docker",
+ "terraform-provider-dome9",
+ "terraform-provider-dyn",
+ "terraform-provider-ecl",
+ "terraform-provider-equinix",
+ "terraform-provider-exoscale",
+ "terraform-provider-external",
+ "terraform-provider-fakewebservices",
+ "terraform-provider-fastly",
+ "terraform-provider-flexibleengine",
+ "terraform-provider-fortios",
+ "terraform-provider-genymotion",
+ "terraform-provider-github",
+ "terraform-provider-gitlab",
+ "terraform-provider-google",
+ "terraform-provider-google-beta",
+ "terraform-provider-googleworkspace",
+ "terraform-provider-grafana",
+ "terraform-provider-gridscale",
+ "terraform-provider-hcloud",
+ "terraform-provider-hcp",
+ "terraform-provider-hcs",
+ "terraform-provider-hedvig",
+ "terraform-provider-helm",
+ "terraform-provider-heroku",
+ "terraform-provider-http",
+ "terraform-provider-icinga2",
+ "terraform-provider-ignition",
+ "terraform-provider-incapsula",
+ "terraform-provider-influxdb",
+ "terraform-provider-infoblox",
+ "terraform-provider-jdcloud",
+ "terraform-provider-ksyun",
+ "terraform-provider-kubernetes",
+ "terraform-provider-kubernetes-alpha",
+ "terraform-provider-lacework",
+ "terraform-provider-launchdarkly",
+ "terraform-provider-librato",
+ "terraform-provider-linode",
+ "terraform-provider-local",
+ "terraform-provider-logentries",
+ "terraform-provider-logicmonitor",
+ "terraform-provider-mailgun",
+ "terraform-provider-metalcloud",
+ "terraform-provider-mongodbatlas",
+ "terraform-provider-mso",
+ "terraform-provider-mysql",
+ "terraform-provider-ncloud",
+ "terraform-provider-netlify",
+ "terraform-provider-newrelic",
+ "terraform-provider-nomad",
+ "terraform-provider-ns1",
+ "terraform-provider-nsxt",
+ "terraform-provider-null",
+ "terraform-provider-nutanix",
+ "terraform-provider-oci",
+ "terraform-provider-okta",
+ "terraform-provider-oktaasa",
+ "terraform-provider-oneandone",
+ "terraform-provider-onelogin",
+ "terraform-provider-opc",
+ "terraform-provider-opennebula",
+ "terraform-provider-openstack",
+ "terraform-provider-opentelekomcloud",
+ "terraform-provider-opsgenie",
+ "terraform-provider-oraclepaas",
+ "terraform-provider-ovh",
+ "terraform-provider-packet",
+ "terraform-provider-pagerduty",
+ "terraform-provider-panos",
+ "terraform-provider-postgresql",
+ "terraform-provider-powerdns",
+ "terraform-provider-prismacloud",
+ "terraform-provider-profitbricks",
+ "terraform-provider-pureport",
+ "terraform-provider-rabbitmq",
+ "terraform-provider-rancher",
+ "terraform-provider-rancher2",
+ "terraform-provider-random",
+ "terraform-provider-rightscale",
+ "terraform-provider-rubrik",
+ "terraform-provider-rundeck",
+ "terraform-provider-runscope",
+ "terraform-provider-salesforce",
+ "terraform-provider-scaleway",
+ "terraform-provider-sdm",
+ "terraform-provider-selectel",
+ "terraform-provider-selvpc",
+ "terraform-provider-signalfx",
+ "terraform-provider-skytap",
+ "terraform-provider-softlayer",
+ "terraform-provider-spotinst",
+ "terraform-provider-stackpath",
+ "terraform-provider-statuscake",
+ "terraform-provider-sumologic",
+ "terraform-provider-telefonicaopencloud",
+ "terraform-provider-template",
+ "terraform-provider-tencentcloud",
+ "terraform-provider-terraform",
+ "terraform-provider-tfcoremock",
+ "terraform-provider-tfe",
+ "terraform-provider-thunder",
+ "terraform-provider-time",
+ "terraform-provider-tls",
+ "terraform-provider-triton",
+ "terraform-provider-turbot",
+ "terraform-provider-ucloud",
+ "terraform-provider-ultradns",
+ "terraform-provider-vault",
+ "terraform-provider-vcd",
+ "terraform-provider-venafi",
+ "terraform-provider-vmc",
+ "terraform-provider-vra",
+ "terraform-provider-vra7",
+ "terraform-provider-vsphere",
+ "terraform-provider-vthunder",
+ "terraform-provider-vultr",
+ "terraform-provider-wavefront",
+ "terraform-provider-yandex",
+ "tfc-agent",
+ "vagrant",
+ "vagrant-vmware-utility",
+ "vault",
+ "vault-auditor",
+ "vault-csi-provider",
+ "vault-k8s",
+ "vault-lambda-extension",
+ "vault-mssql-ekm-provider",
+ "vault-pkcs11-provider",
+ "vault-plugin-database-oracle",
+ "vault-servicenow-credential-resolver",
+ "vault-ssh-helper",
+ "waypoint",
+ "waypoint-entrypoint",
+ ]
+}
diff --git a/src/platformchecks/checks/softwareversions/__init__.py b/src/platformchecks/checks/softwareversions/__init__.py
new file mode 100644
--- /dev/null
+++ b/src/platformchecks/checks/softwareversions/__init__.py
@@ -0,0 +1 @@
+from .hashicorp import HashiCorpSoftwareVersionCheck
diff --git a/src/platformchecks/checks/softwareversions/hashicorp.py b/src/platformchecks/checks/softwareversions/hashicorp.py
new file mode 100644
--- /dev/null
+++ b/src/platformchecks/checks/softwareversions/hashicorp.py
@@ -0,0 +1,83 @@
+# -------------------------------------------------------------
+# Platform checks
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Project: Nasqueron
+# Description: Check if a softwareversions is up-to-date
+# License: BSD-2-Clause
+# -------------------------------------------------------------
+
+
+import re
+import requests
+import subprocess
+
+from semver import VersionInfo as Version
+
+
+class HashiCorpSoftwareVersionCheck:
+ def __init__(self, software, executable_name=None):
+ self.software = software
+ if executable_name:
+ self.executable_name = executable_name
+ else:
+ self.executable_name = software
+
+ def perform(self):
+ _, last = self.get_last_version()
+ current = self.get_current_version()
+
+ last = Version.parse(last)
+ current = Version.parse(current)
+
+ if current < last:
+ return False, f"can be upgraded from {current} to {last}"
+
+ return True, "up-to-date"
+
+ def get_last_version(self, rc=False):
+ url = f"https://releases.hashicorp.com/{self.software}/"
+ response = requests.get(url)
+
+ if response.status_code != 200:
+ return False, None
+
+ lines = [
+ line.strip()
+ for line in response.text.split("\n")
+ if f"/{self.software}/" in line
+ ]
+
+ try:
+ for line in lines:
+ version = self.extract_published_version(line)
+
+ if "+" in version:
+ continue
+
+ if rc or not is_beta(version):
+ return True, version
+ except RuntimeError:
+ return False, None
+
+ def extract_published_version(self, expression):
+ result = re.findall(r"\/([a-z0-9\-]+)\/(.*?)\/", expression)
+ if len(result) != 1:
+ raise RuntimeError("Can't extract version")
+
+ software, version = result[0]
+ if software != self.software:
+ raise RuntimeError("Unexpected software name")
+
+ return version
+
+ def get_current_version(self):
+ p = subprocess.run([self.executable_name, "version"], capture_output=True)
+ if p.returncode != 0:
+ raise RuntimeError("Can't get executable version")
+
+ expression = p.stdout.decode("UTF-8").strip()
+ return expression.split()[1][1:]
+
+
+def is_beta(version):
+ return "rc" in version or "beta" in version

File Metadata

Mime Type
text/plain
Expires
Sun, Nov 17, 00:51 (19 h, 52 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2248336
Default Alt Text
D2809.diff (15 KB)

Event Timeline