From 5d4e1cc8da198bd2c8aa5952036c34a63f159e99 Mon Sep 17 00:00:00 2001 From: Charles Butler Date: Mon, 10 Aug 2015 15:52:17 -0400 Subject: [PATCH 1/5] is_leader requires juju 1.22.0 or better The ETCD charm fails with a non committal error message when probing for is_leader on juju versions <= 1.21, 1.18 is still the default shipping in universe, and will cause some headaches if users of older juju versions attempt to use this charm as its leveraging the leader election components. There is probably a charm helper for consuming these methods that has a sane fallback strategy, but for now this will satisfy the requirement of blocking installation on anything < 1.22.0 Introduces a new dependency 'semver' to perform the version calculation --- hooks/hooks.py | 9 +++++++++ hooks/install | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/hooks/hooks.py b/hooks/hooks.py index 4f095cb..e6208a3 100755 --- a/hooks/hooks.py +++ b/hooks/hooks.py @@ -8,6 +8,7 @@ from path import path import string import random +import semver import shlex from subprocess import check_output, check_call import sys @@ -24,6 +25,10 @@ @hooks.hook('config-changed') def config_changed(): + if not version_check: + hookenv.log('This charm requires juju 1.22.0 or greater. Panic and exit!' + 'CRITICAL') + sys.exit(1) if not db.get('installed') or hookenv.config().changed('source-sum'): install_etcd() if leader_status: @@ -152,6 +157,10 @@ def install_etcd(): hookenv.open_port(4001) db.set('installed', True) +def version_check(): + version = check_output(["juju", "--version"]) + return semver.match(version, ">=1.22.0") + if __name__ == '__main__': with hook_data(): hooks.execute(sys.argv) diff --git a/hooks/install b/hooks/install index 4dcfd4b..cd85398 100755 --- a/hooks/install +++ b/hooks/install @@ -5,7 +5,7 @@ set -ex # corrected and easy_install is no longer required to make pip function. # apt-get install -y python-pip easy_install -U pip -pip install charmhelpers path.py requests +pip install charmhelpers path.py requests semver echo "Creating etcd data path on $JUJU_UNIT_NAME" mkdir -p /opt/etcd/var From e3748015e74f42619425723e0cbfa9b5286afe0a Mon Sep 17 00:00:00 2001 From: Charles Butler Date: Mon, 10 Aug 2015 16:56:38 -0400 Subject: [PATCH 2/5] Refactor the implementation away from semver check This favors a `which is_leader` command to probe if the command is available. It still panic's and bails on the installation if is_leader is not available (the current defacto method to determine if leader election is available on a unit - see https://github.com/whitmo/etcd-charm/pull/16 for more information on why this is probing as it were. --- hooks/hooks.py | 24 ++++++++++++++++++------ hooks/install | 2 +- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/hooks/hooks.py b/hooks/hooks.py index e6208a3..e9d4d29 100755 --- a/hooks/hooks.py +++ b/hooks/hooks.py @@ -8,7 +8,6 @@ from path import path import string import random -import semver import shlex from subprocess import check_output, check_call import sys @@ -25,8 +24,8 @@ @hooks.hook('config-changed') def config_changed(): - if not version_check: - hookenv.log('This charm requires juju 1.22.0 or greater. Panic and exit!' + if not isleader_available: + hookenv.log('This charm requires Juju 1.22.0 or greater. Panic and exit!' 'CRITICAL') sys.exit(1) if not db.get('installed') or hookenv.config().changed('source-sum'): @@ -157,9 +156,22 @@ def install_etcd(): hookenv.open_port(4001) db.set('installed', True) -def version_check(): - version = check_output(["juju", "--version"]) - return semver.match(version, ">=1.22.0") +def isleader_available(): + """Attempt to locate is_leader + + predicate method to determine if we are on a Juju revision that maintains + the leader election codebase. + """ + cmd = ['which', 'is_leader'] + try: + ret = subprocess.call(cmd, universal_newlines=True) + if ret == 0: + return True + else: + return False + except OSError as e: + # If we aren't finding the which command, we have bigger issues. + raise if __name__ == '__main__': with hook_data(): diff --git a/hooks/install b/hooks/install index cd85398..4dcfd4b 100755 --- a/hooks/install +++ b/hooks/install @@ -5,7 +5,7 @@ set -ex # corrected and easy_install is no longer required to make pip function. # apt-get install -y python-pip easy_install -U pip -pip install charmhelpers path.py requests semver +pip install charmhelpers path.py requests echo "Creating etcd data path on $JUJU_UNIT_NAME" mkdir -p /opt/etcd/var From 23d17ca3c12f86c2bae6982d28c35e7c604ca4d2 Mon Sep 17 00:00:00 2001 From: Charles Butler Date: Mon, 10 Aug 2015 17:11:57 -0400 Subject: [PATCH 3/5] Refactored is_leader refactored from a bash based sniff to just consume charm helpers and abort on NotImplementedError --- hooks/hooks.py | 29 +++++++---------------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/hooks/hooks.py b/hooks/hooks.py index e9d4d29..5aa2a5a 100755 --- a/hooks/hooks.py +++ b/hooks/hooks.py @@ -16,18 +16,20 @@ hook_data = unitdata.HookData() db = unitdata.kv() -leader_status = check_output(['is-leader']).rstrip() != "False" private_address = hookenv.unit_get('private-address') public_address = hookenv.unit_get('private-address') unit_name = environ['JUJU_UNIT_NAME'].replace('/', '') +try: + leader_status = hookenv.is_leader() +except NotImplementedError: + hookenv.log('This charm requires Juju 1.22.0 or greater. Panic and exit!' + 'CRITICAL') + sys.exit(1) + @hooks.hook('config-changed') def config_changed(): - if not isleader_available: - hookenv.log('This charm requires Juju 1.22.0 or greater. Panic and exit!' - 'CRITICAL') - sys.exit(1) if not db.get('installed') or hookenv.config().changed('source-sum'): install_etcd() if leader_status: @@ -156,23 +158,6 @@ def install_etcd(): hookenv.open_port(4001) db.set('installed', True) -def isleader_available(): - """Attempt to locate is_leader - - predicate method to determine if we are on a Juju revision that maintains - the leader election codebase. - """ - cmd = ['which', 'is_leader'] - try: - ret = subprocess.call(cmd, universal_newlines=True) - if ret == 0: - return True - else: - return False - except OSError as e: - # If we aren't finding the which command, we have bigger issues. - raise - if __name__ == '__main__': with hook_data(): hooks.execute(sys.argv) From a2efbc1dda26db9a69e2d056213f90b49412bee8 Mon Sep 17 00:00:00 2001 From: Charles Butler Date: Mon, 10 Aug 2015 17:42:16 -0400 Subject: [PATCH 4/5] refactor the error message, and properly scope to a CRITICAL warning --- hooks/hooks.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hooks/hooks.py b/hooks/hooks.py index 5aa2a5a..1b81cd1 100755 --- a/hooks/hooks.py +++ b/hooks/hooks.py @@ -23,7 +23,8 @@ try: leader_status = hookenv.is_leader() except NotImplementedError: - hookenv.log('This charm requires Juju 1.22.0 or greater. Panic and exit!' + hookenv.log('This charm requires Leader Election. Juju >= 1.23.2.' + ' Leader election binary not found, Panic and exit!', 'CRITICAL') sys.exit(1) From e9efc9ba026d48aae792038c33819b05d054cbbf Mon Sep 17 00:00:00 2001 From: Charles Butler Date: Mon, 10 Aug 2015 17:44:16 -0400 Subject: [PATCH 5/5] Add a blurb to the README about Juju minimum version --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index dbc6d07..698d96d 100644 --- a/README.md +++ b/README.md @@ -51,10 +51,17 @@ Health of the cluster can be checked by verified via juju actions juju action fetch +## Usage Caveats + +This charm requires Leader Election, which is a feature of Juju >= 1.23.2. The +charm will panic and refuse to continue if the leader_election binary is not +found. Please take care when deploying this charm on older versions of Juju. + ## Credits The etcd charm was originally written by Kapil Thangavelu ([@kapilt](https://github.com/kapilt)). + #### Mantainers: The kubernetes team maintains this charm: