Merge lp:~adam-collard/charm-helpers/fix-amulet-utils-validate-services-by-name into lp:charm-helpers

Proposed by Adam Collard
Status: Merged
Merged at revision: 427
Proposed branch: lp:~adam-collard/charm-helpers/fix-amulet-utils-validate-services-by-name
Merge into: lp:charm-helpers
Diff against target: 190 lines (+125/-10)
3 files modified
charmhelpers/contrib/amulet/utils.py (+18/-10)
test_requirements.txt (+2/-0)
tests/contrib/amulet/test_utils.py (+105/-0)
To merge this branch: bzr merge lp:~adam-collard/charm-helpers/fix-amulet-utils-validate-services-by-name
Reviewer Review Type Date Requested Status
Chris Glass (community) Approve
Review via email: mp+267817@code.launchpad.net

Description of the change

Make the validate_services_by_name check actually verify that Upstart jobs are running and not just "existing".

Drive-by fixes for Python3 compatibility and dependencies for running tests (i.e. amulet, distro-info)

To post a comment you must log in.
428. By Adam Collard

Add test files

Revision history for this message
Chris Glass (tribaal) wrote :

+1, thanks for your fix.

(Unit and amulet tests pass)

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'charmhelpers/contrib/amulet/utils.py'
--- charmhelpers/contrib/amulet/utils.py 2015-08-10 12:58:05 +0000
+++ charmhelpers/contrib/amulet/utils.py 2015-08-12 14:08:32 +0000
@@ -14,17 +14,21 @@
14# You should have received a copy of the GNU Lesser General Public License14# You should have received a copy of the GNU Lesser General Public License
15# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.15# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
1616
17import amulet
18import ConfigParser
19import distro_info
20import io17import io
21import logging18import logging
22import os19import os
23import re20import re
24import six
25import sys21import sys
26import time22import time
27import urlparse23
24import amulet
25import distro_info
26import six
27from six.moves import configparser
28if six.PY3:
29 from urllib import parse as urlparse
30else:
31 import urlparse
2832
2933
30class AmuletUtils(object):34class AmuletUtils(object):
@@ -143,18 +147,22 @@
143 for service_name in services_list:147 for service_name in services_list:
144 if (self.ubuntu_releases.index(release) >= systemd_switch or148 if (self.ubuntu_releases.index(release) >= systemd_switch or
145 service_name in ['rabbitmq-server', 'apache2']):149 service_name in ['rabbitmq-server', 'apache2']):
146 # init is systemd150 # init is systemd (or regular sysv)
147 cmd = 'sudo service {} status'.format(service_name)151 cmd = 'sudo service {} status'.format(service_name)
152 output, code = sentry_unit.run(cmd)
153 service_running = code == 0
148 elif self.ubuntu_releases.index(release) < systemd_switch:154 elif self.ubuntu_releases.index(release) < systemd_switch:
149 # init is upstart155 # init is upstart
150 cmd = 'sudo status {}'.format(service_name)156 cmd = 'sudo status {}'.format(service_name)
157 output, code = sentry_unit.run(cmd)
158 service_running = code == 0 and "start/running" in output
151159
152 output, code = sentry_unit.run(cmd)
153 self.log.debug('{} `{}` returned '160 self.log.debug('{} `{}` returned '
154 '{}'.format(sentry_unit.info['unit_name'],161 '{}'.format(sentry_unit.info['unit_name'],
155 cmd, code))162 cmd, code))
156 if code != 0:163 if not service_running:
157 return "command `{}` returned {}".format(cmd, str(code))164 return u"command `{}` returned {} {}".format(
165 cmd, output, str(code))
158 return None166 return None
159167
160 def _get_config(self, unit, filename):168 def _get_config(self, unit, filename):
@@ -164,7 +172,7 @@
164 # NOTE(beisner): by default, ConfigParser does not handle options172 # NOTE(beisner): by default, ConfigParser does not handle options
165 # with no value, such as the flags used in the mysql my.cnf file.173 # with no value, such as the flags used in the mysql my.cnf file.
166 # https://bugs.python.org/issue7005174 # https://bugs.python.org/issue7005
167 config = ConfigParser.ConfigParser(allow_no_value=True)175 config = configparser.ConfigParser(allow_no_value=True)
168 config.readfp(io.StringIO(file_contents))176 config.readfp(io.StringIO(file_contents))
169 return config177 return config
170178
171179
=== modified file 'test_requirements.txt'
--- test_requirements.txt 2015-07-15 17:01:57 +0000
+++ test_requirements.txt 2015-08-12 14:08:32 +0000
@@ -7,6 +7,8 @@
7nose>=1.3.17nose>=1.3.1
8flake88flake8
9testtools==0.9.14 # Before dependent on modern 'six'9testtools==0.9.14 # Before dependent on modern 'six'
10amulet
11distro-info
10#12#
11# Specify precise versions of runtime dependencies where possible.13# Specify precise versions of runtime dependencies where possible.
12netaddr==0.7.10 # trusty. precise is 0.7.5, but not in pypi.14netaddr==0.7.10 # trusty. precise is 0.7.5, but not in pypi.
1315
=== added directory 'tests/contrib/amulet'
=== added file 'tests/contrib/amulet/test_utils.py'
--- tests/contrib/amulet/test_utils.py 1970-01-01 00:00:00 +0000
+++ tests/contrib/amulet/test_utils.py 2015-08-12 14:08:32 +0000
@@ -0,0 +1,105 @@
1# Copyright 2015 Canonical Ltd.
2#
3# Authors:
4# Adam Collard <adam.collard@canonical.com>
5
6import unittest
7
8from charmhelpers.contrib.amulet.utils import AmuletUtils
9
10
11class FakeSentry(object):
12
13 commands = {}
14
15 info = {"unit_name": "foo"}
16
17 def run(self, command):
18 return self.commands[command]
19
20
21class ValidateServicesByNameTestCase(unittest.TestCase):
22
23 def setUp(self):
24 self.utils = AmuletUtils()
25 self.sentry_unit = FakeSentry()
26
27 def test_errors_for_unknown_upstart_service(self):
28 """
29 Returns a message if the Upstart service is unknown.
30 """
31 self.sentry_unit.commands["lsb_release -cs"] = "trusty", 0
32 self.sentry_unit.commands["sudo status foo"] = (
33 "status: Unknown job: foo", 1)
34
35 result = self.utils.validate_services_by_name(
36 {self.sentry_unit: ["foo"]})
37 self.assertIsNotNone(result)
38
39 def test_none_for_started_upstart_service(self):
40 """
41 Returns None if the Upstart service is running.
42 """
43 self.sentry_unit.commands["lsb_release -cs"] = "trusty", 0
44 self.sentry_unit.commands["sudo status foo"] = (
45 "foo start/running, process 42", 0)
46
47 result = self.utils.validate_services_by_name(
48 {self.sentry_unit: ["foo"]})
49 self.assertIsNone(result)
50
51 def test_errors_for_stopped_upstart_service(self):
52 """
53 Returns a message if the Upstart service is stopped.
54 """
55 self.sentry_unit.commands["lsb_release -cs"] = "trusty", 0
56 self.sentry_unit.commands["sudo status foo"] = "foo stop/waiting", 0
57
58 result = self.utils.validate_services_by_name(
59 {self.sentry_unit: ["foo"]})
60 self.assertIsNotNone(result)
61
62 def test_errors_for_unknown_systemd_service(self):
63 """
64 Returns a message if a systemd service is unknown.
65 """
66 self.sentry_unit.commands["lsb_release -cs"] = "vivid", 0
67 self.sentry_unit.commands["sudo service foo status"] = (u"""\
68\u25cf foo.service
69 Loaded: not-found (Reason: No such file or directory)
70 Active: inactive (dead)
71""", 3)
72
73 result = self.utils.validate_services_by_name({
74 self.sentry_unit: ["foo"]})
75 self.assertIsNotNone(result)
76
77 def test_none_for_started_systemd_service(self):
78 """
79 Returns None if a systemd service is running.
80 """
81 self.sentry_unit.commands["lsb_release -cs"] = "vivid", 0
82 self.sentry_unit.commands["sudo service foo status"] = (u"""\
83\u25cf foo.service - Foo
84 Loaded: loaded (/lib/systemd/system/foo.service; enabled)
85 Active: active (exited) since Thu 1970-01-01 00:00:00 UTC; 42h 42min ago
86 Main PID: 3 (code=exited, status=0/SUCCESS)
87 CGroup: /system.slice/foo.service
88""", 0)
89 result = self.utils.validate_services_by_name(
90 {self.sentry_unit: ["foo"]})
91 self.assertIsNone(result)
92
93 def test_errors_for_stopped_systemd_service(self):
94 """
95 Returns a message if a systemd service is stopped.
96 """
97 self.sentry_unit.commands["lsb_release -cs"] = "vivid", 0
98 self.sentry_unit.commands["sudo service foo status"] = (u"""\
99\u25cf foo.service - Foo
100 Loaded: loaded (/lib/systemd/system/foo.service; disabled)
101 Active: inactive (dead)
102""", 3)
103 result = self.utils.validate_services_by_name(
104 {self.sentry_unit: ["foo"]})
105 self.assertIsNotNone(result)

Subscribers

People subscribed via source and target branches