Merge lp:~free.ekanayaka/landscape-charm/pre-install-hooks into lp:~landscape/landscape-charm/trunk

Proposed by Free Ekanayaka
Status: Merged
Merged at revision: 292
Proposed branch: lp:~free.ekanayaka/landscape-charm/pre-install-hooks
Merge into: lp:~landscape/landscape-charm/trunk
Diff against target: 104 lines (+70/-1)
2 files modified
lib/install.py (+17/-1)
lib/tests/test_install.py (+53/-0)
To merge this branch: bzr merge lp:~free.ekanayaka/landscape-charm/pre-install-hooks
Reviewer Review Type Date Requested Status
Chad Smith Approve
🤖 Landscape Builder test results Needs Fixing
Adam Collard (community) Approve
Review via email: mp+260426@code.launchpad.net

Commit message

Add support for pre-install hooks, which are conventionally located at exec.d/*/charm-pre-install.

Description of the change

Add support for pre-install hooks, which are conventionally located at exec.d/*/charm-pre-install.

This is required by IS in order to deploy to prodstack, see:

https://wiki.canonical.com/InformationInfrastructure/DevOps#Install.2BAC8-support_basenode_in_your_charm

To post a comment you must log in.
Revision history for this message
🤖 Landscape Builder (landscape-builder) wrote :

Command: make ci-test
Result: Success
Revno: 291
Branch: lp:~free.ekanayaka/landscape-charm/pre-install-hooks
Jenkins: https://ci.lscape.net/job/latch-test/1068/

review: Approve (test results)
Revision history for this message
Adam Collard (adam-collard) wrote :

Minor suggestion inline.

review: Approve
292. By Free Ekanayaka

Address review comments

Revision history for this message
🤖 Landscape Builder (landscape-builder) wrote :
Download full text (15.7 KiB)

Command: make ci-test
Result: Fail
Revno: 292
Branch: lp:~free.ekanayaka/landscape-charm/pre-install-hooks
Jenkins: https://ci.lscape.net/job/latch-test/1073/
-------------------------------------------
./dev/ubuntu-deps
Reading package lists...
Building dependency tree...
Reading state information...
software-properties-common is already the newest version.
The following package was automatically installed and is no longer required:
  os-prober
Use 'apt-get autoremove' to remove it.
0 upgraded, 0 newly installed, 0 to remove and 9 not upgraded.
gpg: keyring `/tmp/tmpxhke205z/secring.gpg' created
gpg: keyring `/tmp/tmpxhke205z/pubring.gpg' created
gpg: requesting key C8068B11 from hkp server keyserver.ubuntu.com
gpg: /tmp/tmpxhke205z/trustdb.gpg: trustdb created
gpg: key C8068B11: public key "Launchpad Ensemble PPA" imported
gpg: Total number processed: 1
gpg: imported: 1 (RSA: 1)
OK
Ign http://security.ubuntu.com trusty-security InRelease
Ign http://ppa.launchpad.net trusty InRelease
Ign http://archive.ubuntu.com trusty InRelease
Hit http://security.ubuntu.com trusty-security Release.gpg
Hit http://ppa.launchpad.net trusty Release.gpg
Ign http://archive.ubuntu.com trusty-updates InRelease
Hit http://security.ubuntu.com trusty-security Release
Hit http://ppa.launchpad.net trusty Release
Hit http://archive.ubuntu.com trusty Release.gpg
Hit http://archive.ubuntu.com trusty-updates Release.gpg
Hit http://archive.ubuntu.com trusty Release
Hit http://archive.ubuntu.com trusty-updates Release
Hit http://security.ubuntu.com trusty-security/main Sources
Hit http://security.ubuntu.com trusty-security/universe Sources
Hit http://ppa.launchpad.net trusty/main amd64 Packages
Hit http://security.ubuntu.com trusty-security/main amd64 Packages
Hit http://security.ubuntu.com trusty-security/universe amd64 Packages
Hit http://security.ubuntu.com trusty-security/main Translation-en
Hit http://ppa.launchpad.net trusty/main Translation-en
Hit http://security.ubuntu.com trusty-security/universe Translation-en
Hit http://archive.ubuntu.com trusty/main Sources
Hit http://archive.ubuntu.com trusty/universe Sources
Hit http://archive.ubuntu.com trusty/main amd64 Packages
Hit http://archive.ubuntu.com trusty/universe amd64 Packages
Hit http://archive.ubuntu.com trusty/main Translation-en
Hit http://archive.ubuntu.com trusty/universe Translation-en
Hit http://archive.ubuntu.com trusty-updates/main Sources
Hit http://archive.ubuntu.com trusty-updates/universe Sources
Hit http://archive.ubuntu.com trusty-updates/main amd64 Packages
Hit http://archive.ubuntu.com trusty-updates/universe amd64 Packages
Hit http://archive.ubuntu.com trusty-updates/main Translation-en
Ign https://private-ppa.launchpad.net trusty InRelease
Ign https://private-ppa.launchpad.net trusty InRelease
Hit https://private-ppa.launchpad.net trusty Release.gpg
Hit https://private-ppa.launchpad.net trusty Release.gpg
Hit https://private-ppa.launchpad.net trusty Release
Hit https://private-ppa.launchpad.net trusty Release
Hit http://archive.ubuntu.com trusty-updates/universe Translation-en
Hit https://private-ppa.launchpad.net trusty/main amd64 Packages
Hit https://private-ppa.launchpad.net ...

review: Needs Fixing (test results)
Revision history for this message
Chad Smith (chad.smith) wrote :

Couple of minor points and a request for either an extended unit test or additional unit tests for fail case and ignore case for the CHARM_PRE_INSTALL_PATTERN.

review: Approve
293. By Free Ekanayaka

Merge from trunk

294. By Free Ekanayaka

Address review comments

Revision history for this message
Free Ekanayaka (free.ekanayaka) :
Revision history for this message
Free Ekanayaka (free.ekanayaka) :

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/install.py'
2--- lib/install.py 2015-02-03 09:58:42 +0000
3+++ lib/install.py 2015-05-29 07:54:29 +0000
4@@ -1,11 +1,16 @@
5+import os
6+import glob
7 import subprocess
8
9 from charmhelpers import fetch
10 from charmhelpers.core import hookenv
11
12-from lib.hook import Hook
13+from lib.hook import Hook, HookError
14 from lib.apt import Apt
15
16+# Pattern for pre-install hooks
17+CHARM_PRE_INSTALL_PATTERN = "exec.d/*/charm-pre-install"
18+
19
20 class InstallHook(Hook):
21 """Execute install hook logic."""
22@@ -16,6 +21,17 @@
23 self._subprocess = subprocess
24
25 def _run(self):
26+ # Run pre-install hooks.
27+ self._hookenv.log("Invoking charm-pre-install hooks")
28+ charm_dir = self._hookenv.charm_dir()
29+ hooks = glob.glob(os.path.join(charm_dir, CHARM_PRE_INSTALL_PATTERN))
30+ for hook in hooks:
31+ if os.access(hook, os.X_OK):
32+ try:
33+ self._subprocess.check_call(hook, shell=True)
34+ except subprocess.CalledProcessError as error:
35+ raise HookError(str(error))
36+
37 # Set APT sources and install Landscape packages
38 apt = Apt(
39 hookenv=self._hookenv, fetch=self._fetch,
40
41=== modified file 'lib/tests/test_install.py'
42--- lib/tests/test_install.py 2015-03-09 11:56:34 +0000
43+++ lib/tests/test_install.py 2015-05-29 07:54:29 +0000
44@@ -1,3 +1,5 @@
45+import os
46+
47 from lib.tests.helpers import HookenvTest
48 from lib.tests.stubs import FetchStub, SubprocessStub
49 from lib.install import InstallHook
50@@ -21,3 +23,54 @@
51 self.assertEqual(0, self.hook())
52 self.assertNotEqual([], self.fetch.sources)
53 self.assertNotEqual([], self.fetch.installed)
54+
55+ def test_pre_install_hooks(self):
56+ """
57+ The InstallHook invokes any pre-install hook found in the exec.d/
58+ sub-directory.
59+ """
60+ charm_dir = self.hookenv.charm_dir()
61+ flag = os.path.join(charm_dir, "foo-run")
62+ hook = os.path.join(charm_dir, "exec.d", "foo", "charm-pre-install")
63+ os.makedirs(os.path.dirname(hook))
64+ with open(hook, "w") as fd:
65+ fd.write("#!/bin/sh\ntouch %s\n" % flag)
66+ os.chmod(hook, 0755)
67+ self.hookenv.config()["source"] = "ppa:landscape/14.10"
68+ self.hook()
69+ self.assertTrue(os.path.exists(flag))
70+
71+ def test_pre_install_hook_fail(self):
72+ """
73+ If a pre-install hook fails, the hook returns 1 and logs the error.
74+ """
75+ charm_dir = self.hookenv.charm_dir()
76+ hook = os.path.join(charm_dir, "exec.d", "foo", "charm-pre-install")
77+ os.makedirs(os.path.dirname(hook))
78+ with open(hook, "w") as fd:
79+ fd.write("#!/bin/sh\ntexit 127\n")
80+ os.chmod(hook, 0755)
81+ self.hookenv.config()["source"] = "ppa:landscape/14.10"
82+ self.assertEqual(1, self.hook())
83+ self.assertEqual(
84+ "Command '%s' returned non-zero exit status 127" % hook,
85+ self.hookenv.messages[-1][0])
86+
87+ def test_pre_install_hooks_ignores(self):
88+ """
89+ Files that are not executable or don't match the expected name pattern
90+ are just ignored.
91+ """
92+ charm_dir = self.hookenv.charm_dir()
93+ flag = os.path.join(charm_dir, "foo-run")
94+ hook1 = os.path.join(charm_dir, "exec.d", "foo", "charm-pre-install")
95+ hook2 = os.path.join(charm_dir, "exec.d", "foo", "no-match")
96+ os.makedirs(os.path.dirname(hook1))
97+ with open(hook1, "w") as fd:
98+ fd.write("#!/bin/sh\ntouch %s\n" % flag)
99+ with open(hook2, "w") as fd:
100+ fd.write("#!/bin/sh\ntouch %s\n" % flag)
101+ os.chmod(hook2, 0755)
102+ self.hookenv.config()["source"] = "ppa:landscape/14.10"
103+ self.hook()
104+ self.assertFalse(os.path.exists(flag))

Subscribers

People subscribed via source and target branches