From e9680cc1020f9c54221993b3ae816b046d92bafc Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Thu, 5 Nov 2015 15:42:30 -0500 Subject: Additional upgrade enhancements - rework the version checking - provide better safety if the apiLevel attributes are missing - ensure a list of api levels are present - remove a list of api levels - pylint fixes --- playbooks/adhoc/upgrades/files/versions.sh | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 playbooks/adhoc/upgrades/files/versions.sh (limited to 'playbooks/adhoc/upgrades/files') diff --git a/playbooks/adhoc/upgrades/files/versions.sh b/playbooks/adhoc/upgrades/files/versions.sh new file mode 100644 index 000000000..01ea1d91a --- /dev/null +++ b/playbooks/adhoc/upgrades/files/versions.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +yum_installed=$(yum list installed "$@" | tail -n +2 | grep -v 'Installed Packages' | grep -v 'Red Hat Subscription Management' | awk '{ print $2 }' | tr '\n' ' ') +yum_available=$(yum list available "$@" | tail -n +2 | grep -v 'Available Packages' | grep -v 'Red Hat Subscription Management' | grep -v 'el7ose' | awk '{ print $2 }' | tr '\n' ' ') + +echo "---" +echo "curr_version: ${yum_installed}" +echo "avail_version: ${yum_available}" -- cgit v1.2.3 From 66791fd954731c7d4286d48683b7fe40288d5000 Mon Sep 17 00:00:00 2001 From: Devan Goodwin Date: Fri, 6 Nov 2015 09:49:17 -0400 Subject: Add pre-upgrade script to be run on first master. Script currently just checks for port names that are no longer valid. In theory other checks may be added to this script in the future. Script was originally written by Steve Milner and Andy Goldstein. If the script fails, ansible seems to handle this nicely by default, exiting the upgrade and displaying stderr and stdout, both of which contain useful info on what the problem was. --- playbooks/adhoc/upgrades/files/pre-upgrade-check | 185 +++++++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 playbooks/adhoc/upgrades/files/pre-upgrade-check (limited to 'playbooks/adhoc/upgrades/files') diff --git a/playbooks/adhoc/upgrades/files/pre-upgrade-check b/playbooks/adhoc/upgrades/files/pre-upgrade-check new file mode 100644 index 000000000..c8ecae399 --- /dev/null +++ b/playbooks/adhoc/upgrades/files/pre-upgrade-check @@ -0,0 +1,185 @@ +#!/usr/bin/env python +""" +Pre-upgrade checks that must be run on a master before proceeding with upgrade. +""" +# This is a script not a python module: +# pylint: disable=invalid-name + +# NOTE: This script should not require any python libs other than what is +# in the standard library. + +__license__ = "ASL 2.0" + +import json +import os +import subprocess +import re + +# The maximum length of container.ports.name +ALLOWED_LENGTH = 15 +# The valid structure of container.ports.name +ALLOWED_CHARS = re.compile('^[a-z0-9][a-z0-9\\-]*[a-z0-9]$') +AT_LEAST_ONE_LETTER = re.compile('[a-z]') +# look at OS_PATH for the full path. Default ot 'oc' +OC_PATH = os.getenv('OC_PATH', 'oc') + + +def validate(value): + """ + validate verifies that value matches required conventions + + Rules of container.ports.name validation: + + * must be less that 16 chars + * at least one letter + * only a-z0-9- + * hyphens can not be leading or trailing or next to each other + + :Parameters: + - `value`: Value to validate + """ + if len(value) > ALLOWED_LENGTH: + return False + + if '--' in value: + return False + + # We search since it can be anywhere + if not AT_LEAST_ONE_LETTER.search(value): + return False + + # We match because it must start at the beginning + if not ALLOWED_CHARS.match(value): + return False + return True + + +def list_items(kind): + """ + list_items returns a list of items from the api + + :Parameters: + - `kind`: Kind of item to access + """ + response = subprocess.check_output([OC_PATH, 'get', '--all-namespaces', '-o', 'json', kind]) + items = json.loads(response) + return items.get("items", []) + + +def get(obj, *paths): + """ + Gets an object + + :Parameters: + - `obj`: A dictionary structure + - `path`: All other non-keyword arguments + """ + ret_obj = obj + for path in paths: + if ret_obj.get(path, None) is None: + return [] + ret_obj = ret_obj[path] + return ret_obj + + +# pylint: disable=too-many-arguments +def pretty_print_errors(namespace, kind, item_name, container_name, port_name, valid): + """ + Prints out results in human friendly way. + + :Parameters: + - `namespace`: Namespace of the resource + - `kind`: Kind of the resource + - `item_name`: Name of the resource + - `container_name`: Name of the container. May be "" when kind=Service. + - `port_name`: Name of the port + - `valid`: True if the port is valid + """ + if not valid: + if len(container_name) > 0: + print('%s/%s -n %s (Container="%s" Port="%s")' % ( + kind, item_name, namespace, container_name, port_name)) + else: + print('%s/%s -n %s (Port="%s")' % ( + kind, item_name, namespace, port_name)) + + +def print_validation_header(): + """ + Prints the error header. Should run on the first error to avoid + overwhelming the user. + """ + print """\ +At least one port name does not validate. Valid port names: + + * must be less that 16 chars + * have at least one letter + * only a-z0-9- + * do not start or end with - + * Dashes may not be next to eachother ('--') +""" + + +def main(): + """ + main is the main entry point to this script + """ + try: + # the comma at the end suppresses the newline + print "Checking for oc ...", + subprocess.check_output([OC_PATH, 'whoami']) + print "found" + except: + print( + 'Can not find oc (%s). Override the path with the ' + 'OC_PATH environment variable. Exiting...' % OC_PATH) + raise SystemExit(1) + + # Where the magic happens + first_error = True + for kind, path in [ + ('replicationcontrollers', ("spec", "template", "spec", "containers")), + ('pods', ("spec", "containers")), + ('deploymentconfigs', ("spec", "template", "spec", "containers"))]: + for item in list_items(kind): + namespace = item["metadata"]["namespace"] + item_name = item["metadata"]["name"] + for container in get(item, *path): + container_name = container["name"] + for port in get(container, "ports"): + port_name = port.get("name", None) + if not port_name: + # Unnamed ports are OK + continue + valid = validate(port_name) + if not valid and first_error: + first_error = False + print_validation_header() + pretty_print_errors( + namespace, kind, item_name, + container_name, port_name, valid) + + # Services follow a different flow + for item in list_items('services'): + namespace = item["metadata"]["namespace"] + item_name = item["metadata"]["name"] + for port in get(item, "spec", "ports"): + port_name = port.get("targetPort", None) + if isinstance(port_name, int) or port_name is None: + # Integer only or unnamed ports are OK + continue + valid = validate(port_name) + if not valid and first_error: + first_error = False + print_validation_header() + pretty_print_errors( + namespace, "services", item_name, "", port_name, valid) + + # If we had at least 1 error then exit with 1 + if not first_error: + raise SystemExit(1) + + +if __name__ == '__main__': + main() + -- cgit v1.2.3 From 050209f3c86a9dccefdf8b9f05898d1503254a2c Mon Sep 17 00:00:00 2001 From: Jason DeTiberus Date: Fri, 6 Nov 2015 13:21:54 -0500 Subject: Fix issues related to upgrade packages being unavailable --- playbooks/adhoc/upgrades/files/versions.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'playbooks/adhoc/upgrades/files') diff --git a/playbooks/adhoc/upgrades/files/versions.sh b/playbooks/adhoc/upgrades/files/versions.sh index 01ea1d91a..f90719cab 100644 --- a/playbooks/adhoc/upgrades/files/versions.sh +++ b/playbooks/adhoc/upgrades/files/versions.sh @@ -1,7 +1,9 @@ #!/bin/bash -yum_installed=$(yum list installed "$@" | tail -n +2 | grep -v 'Installed Packages' | grep -v 'Red Hat Subscription Management' | awk '{ print $2 }' | tr '\n' ' ') -yum_available=$(yum list available "$@" | tail -n +2 | grep -v 'Available Packages' | grep -v 'Red Hat Subscription Management' | grep -v 'el7ose' | awk '{ print $2 }' | tr '\n' ' ') +yum_installed=$(yum list installed "$@" 2>&1 | tail -n +2 | grep -v 'Installed Packages' | grep -v 'Red Hat Subscription Management' | grep -v 'Error:' | awk '{ print $2 }' | tr '\n' ' ') + +yum_available=$(yum list available "$@" 2>&1 | tail -n +2 | grep -v 'Available Packages' | grep -v 'Red Hat Subscription Management' | grep -v 'el7ose' | grep -v 'Error:' | awk '{ print $2 }' | tr '\n' ' ') + echo "---" echo "curr_version: ${yum_installed}" -- cgit v1.2.3 From 0cfb416780b9e86c26eafd62ee6b99cd2a46b7cd Mon Sep 17 00:00:00 2001 From: Devan Goodwin Date: Fri, 6 Nov 2015 14:33:17 -0400 Subject: Minor upgrade improvements. Skip some 3.1 checks if doing a 3.0.x to 3.0.2 upgrade. Improve error message when oc whoami fails (i.e. openshift is down) during pre-upgrade checks, rather than assuming the binary doesn't exist. --- playbooks/adhoc/upgrades/files/pre-upgrade-check | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'playbooks/adhoc/upgrades/files') diff --git a/playbooks/adhoc/upgrades/files/pre-upgrade-check b/playbooks/adhoc/upgrades/files/pre-upgrade-check index c8ecae399..ed4ab6d1b 100644 --- a/playbooks/adhoc/upgrades/files/pre-upgrade-check +++ b/playbooks/adhoc/upgrades/files/pre-upgrade-check @@ -131,8 +131,11 @@ def main(): print "found" except: print( - 'Can not find oc (%s). Override the path with the ' - 'OC_PATH environment variable. Exiting...' % OC_PATH) + 'Unable to run "%s whoami"\n' + 'Please ensure OpenShift is running, and "oc" is on your system ' + 'path.\n' + 'You can override the path with the OC_PATH environment variable.' + % OC_PATH) raise SystemExit(1) # Where the magic happens -- cgit v1.2.3