Merge lp:~fwereade/pyjuju/cobbler-zk-connect-error-messages into lp:~fwereade/pyjuju/cobbler-zk-connect

Proposed by William Reade
Status: Merged
Approved by: William Reade
Approved revision: 339
Merged at revision: 339
Proposed branch: lp:~fwereade/pyjuju/cobbler-zk-connect-error-messages
Merge into: lp:~fwereade/pyjuju/cobbler-zk-connect
Diff against target: 1156 lines (+192/-174)
43 files modified
ensemble/agents/provision.py (+4/-4)
ensemble/agents/tests/test_provision.py (+3/-3)
ensemble/agents/tests/test_unit.py (+4/-4)
ensemble/control/status.py (+3/-3)
ensemble/control/tests/test_status.py (+0/-2)
ensemble/errors.py (+7/-19)
ensemble/formula/bundle.py (+3/-3)
ensemble/formula/provider.py (+1/-1)
ensemble/formula/tests/test_bundle.py (+8/-4)
ensemble/formula/tests/test_config.py (+6/-4)
ensemble/formula/tests/test_repository.py (+4/-4)
ensemble/hooks/tests/test_arguments.py (+2/-2)
ensemble/hooks/tests/test_cli.py (+5/-2)
ensemble/hooks/tests/test_executor.py (+1/-1)
ensemble/hooks/tests/test_invoker.py (+1/-1)
ensemble/lib/tests/test_schema.py (+1/-1)
ensemble/machine/tests/test_unit_deployment.py (+6/-4)
ensemble/machine/unit.py (+1/-1)
ensemble/providers/common/connect.py (+2/-2)
ensemble/providers/common/findzookeepers.py (+1/-1)
ensemble/providers/common/tests/test_connect.py (+5/-7)
ensemble/providers/common/tests/test_findzookeepers.py (+27/-2)
ensemble/providers/common/tests/test_utils.py (+2/-5)
ensemble/providers/common/utils.py (+3/-1)
ensemble/providers/ec2/__init__.py (+3/-2)
ensemble/providers/ec2/launch.py (+2/-3)
ensemble/providers/ec2/securitygroup.py (+6/-7)
ensemble/providers/ec2/tests/common.py (+0/-10)
ensemble/providers/ec2/tests/test_connect.py (+5/-7)
ensemble/providers/ec2/tests/test_getmachines.py (+2/-3)
ensemble/providers/ec2/tests/test_launch.py (+3/-4)
ensemble/providers/ec2/tests/test_provider.py (+4/-1)
ensemble/providers/ec2/tests/test_securitygroup.py (+6/-6)
ensemble/providers/orchestra/cobbler.py (+5/-5)
ensemble/providers/orchestra/tests/test_cobbler.py (+14/-9)
ensemble/providers/orchestra/tests/test_connect.py (+4/-4)
ensemble/providers/orchestra/tests/test_launch.py (+14/-6)
ensemble/providers/orchestra/tests/test_provider.py (+4/-2)
ensemble/state/service.py (+2/-1)
ensemble/state/tests/test_security.py (+1/-1)
ensemble/state/tests/test_service.py (+9/-5)
ensemble/tests/test_errors.py (+6/-16)
ensemble/unit/tests/test_formula.py (+2/-1)
To merge this branch: bzr merge lp:~fwereade/pyjuju/cobbler-zk-connect-error-messages
Reviewer Review Type Date Requested Status
Jim Baker (community) Approve
Gustavo Niemeyer (community) Approve
Review via email: mp+72033@code.launchpad.net

Description of the change

Fixed errors as requested in https://code.launchpad.net/~fwereade/ensemble/cobbler-zk-connect/+merge/71734

Also made many assertIn error message checks into assertEquals; improved some error messages; reworked ProviderInteractionError usage, now I understand its original intent.

To post a comment you must log in.
333. By William Reade

merge parent

334. By William Reade

merge parent

335. By William Reade

merge parent

336. By William Reade

merge parent

Revision history for this message
Gustavo Niemeyer (niemeyer) wrote :

Looks generally good, with a few exceptions:

[1]

+ self.name = type(error).__name__ if error else "error"
+ self.action = action or "interacting with provider"
+ self.message = message or str(error)

     def __str__(self):
     - return "ProviderError: Interaction with machine provider failed: %r" \
     - % self.error
     + return "Unexpected %s %s: %s" % (self.name, self.action, self.message)

This sounds somewhat confusing, and quite likely to turn out
in bad error messages. There's no way to make sense, or to
introduce new messages, without looking at the implementation.
Improving on the original error message is good, but please
use something more straightforward here and in the call sites.

[2]

- raise FormulaError(path, "Must be a ZIP-file (%s)." % str(exc))
+ raise FormulaError(path, "must be a zip file (%s)" % exc)

Our error messages start with a capitalized word.

[3]

             raise FormulaError(path,
      - "Archive does not contain required file: "
      - "\"metadata.yaml\".")
      + "archive does not contain required file "
      + "\"metadata.yaml\"")

Same thing.

[4]

- @param master: if True, machine will initialize the ensemble admin
+ `master` if True, machine will initialize the ensemble admin
             and run a provisioning agent.

I suspect this is the first time I see this notation, and our overall comment
style is starting to feel like a soup. We have at least three different kinds
of comments, besides the broken ones. Please revert the changes to parameter
names and raising/returning specifically so that this branch can be merged
and let's talk about styling in a different thread.

review: Approve
Revision history for this message
William Reade (fwereade) wrote :

[error messages]

The only solution I can see to all these issues is to eliminate all error message prefixes, and to write out the full error message for every exception type at every call site... for example, I thought you didn't like the "Colon-joined sentence fragment: Style of error message", but you're asking me to reinstate it in [2] and [3]. WRT [1], people were already using the "simple" form incorrectly, and the same fix applies.

[docstrings]

Reverting; opened lp:831805

Revision history for this message
William Reade (fwereade) wrote :

> [error messages]
>
> "Colon-joined sentence fragment: Style of error message", but you're asking me to
> reinstate it in [2] and [3].

On further inspection, FormulaError(some_path, "some non-capitalized string") really does appear to be the standard, because it results in a capitalised error message without weird interspersed caps, and I'll be leaving them as-is. If I've misunderstood I'll do a separate cleanup branch.

337. By William Reade

merge parent

338. By William Reade

fix ProviderInteractionErrors per review

339. By William Reade

merge parent

Revision history for this message
Gustavo Niemeyer (niemeyer) wrote :

> On further inspection, FormulaError(some_path, "some non-capitalized string")
> really does appear to be the standard, because it results in a capitalised
> error message without weird interspersed caps, and I'll be leaving them as-is.
> If I've misunderstood I'll do a separate cleanup branch.

Sounds good then. Thanks for checking rather than taking the crackful
comment blindly. :-)

review: Approve
Revision history for this message
Jim Baker (jimbaker) wrote :

+1, overall this looks good. Moving to assertEquals is definitely an improvement as well. There are a number of spots where you should consider using %r instead of %s where file names and potentially other strings might be Unicode. There is one case that certainly should be done that way:

     def __str__(self):
- return "Error processing '%s': %s." % (self.path, self.message)
+ return "Error processing '%s': %s" % (self.path, self.message)

review: Approve
Revision history for this message
Jim Baker (jimbaker) wrote :

Interestingly I cannot mark the branch as being approved now that we have hit our quorum of reviewers. Is this because it's stacked? Anyway, someone should take this action if at all possible!

Revision history for this message
William Reade (fwereade) wrote :

> Interestingly I cannot mark the branch as being approved now that we have hit
> our quorum of reviewers. Is this because it's stacked? Anyway, someone should
> take this action if at all possible!

Feels funny approving my own branch :). I'll make your changes and get it in shortly. Thanks for the review :).

340. By William Reade

merge parent

341. By William Reade

fixes per review

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'ensemble/agents/provision.py'
--- ensemble/agents/provision.py 2011-08-12 19:28:37 +0000
+++ ensemble/agents/provision.py 2011-08-26 13:09:07 +0000
@@ -4,7 +4,7 @@
4from zookeeper import NoNodeException4from zookeeper import NoNodeException
55
6from ensemble.environment.config import EnvironmentsConfig6from ensemble.environment.config import EnvironmentsConfig
7from ensemble.errors import MachinesNotFound, ProviderInteractionError7from ensemble.errors import MachinesNotFound, ProviderError
8from ensemble.lib.twistutils import concurrent_execution_guard8from ensemble.lib.twistutils import concurrent_execution_guard
9from ensemble.state.errors import (9from ensemble.state.errors import (
10 MachineStateNotFound, ServiceStateNotFound, ServiceUnitStateNotFound,10 MachineStateNotFound, ServiceStateNotFound, ServiceUnitStateNotFound,
@@ -178,7 +178,7 @@
178 # map of instance_id -> machine178 # map of instance_id -> machine
179 try:179 try:
180 provider_machines = yield self.provider.get_machines()180 provider_machines = yield self.provider.get_machines()
181 except ProviderInteractionError:181 except ProviderError:
182 log.exception("Cannot get machine list")182 log.exception("Cannot get machine list")
183 return183 return
184184
@@ -192,7 +192,7 @@
192 machine_state_id, provider_machines)192 machine_state_id, provider_machines)
193 except (StateChanged,193 except (StateChanged,
194 MachineStateNotFound,194 MachineStateNotFound,
195 ProviderInteractionError):195 ProviderError):
196 log.exception("Cannot process machine %s", machine_state_id)196 log.exception("Cannot process machine %s", machine_state_id)
197 continue197 continue
198 instance_ids.append(instance_id)198 instance_ids.append(instance_id)
@@ -204,7 +204,7 @@
204 machine = provider_machines[instance_id]204 machine = provider_machines[instance_id]
205 try:205 try:
206 yield self.provider.shutdown_machine(machine)206 yield self.provider.shutdown_machine(machine)
207 except ProviderInteractionError:207 except ProviderError:
208 log.exception("Cannot shutdown machine %s", instance_id)208 log.exception("Cannot shutdown machine %s", instance_id)
209 continue209 continue
210210
211211
=== modified file 'ensemble/agents/tests/test_provision.py'
--- ensemble/agents/tests/test_provision.py 2011-08-11 05:59:30 +0000
+++ ensemble/agents/tests/test_provision.py 2011-08-26 13:09:07 +0000
@@ -313,7 +313,7 @@
313313
314 mock_provider = self.mocker.patch(self.agent.provider)314 mock_provider = self.mocker.patch(self.agent.provider)
315 mock_provider.start_machine({"machine-id": 0})315 mock_provider.start_machine({"machine-id": 0})
316 self.mocker.result(fail(ProviderInteractionError(OSError("Bad"))))316 self.mocker.result(fail(ProviderInteractionError()))
317317
318 mock_provider.start_machine({"machine-id": 1})318 mock_provider.start_machine({"machine-id": 1})
319 self.mocker.passthrough()319 self.mocker.passthrough()
@@ -339,7 +339,7 @@
339 mock_provider = self.mocker.patch(self.agent.provider)339 mock_provider = self.mocker.patch(self.agent.provider)
340340
341 mock_provider.shutdown_machine(MATCH_MACHINE)341 mock_provider.shutdown_machine(MATCH_MACHINE)
342 self.mocker.result(fail(ProviderInteractionError("Bad")))342 self.mocker.result(fail(ProviderInteractionError()))
343343
344 mock_provider.shutdown_machine(MATCH_MACHINE)344 mock_provider.shutdown_machine(MATCH_MACHINE)
345 self.mocker.passthrough()345 self.mocker.passthrough()
@@ -368,7 +368,7 @@
368368
369 mock_provider = self.mocker.patch(self.agent.provider)369 mock_provider = self.mocker.patch(self.agent.provider)
370 mock_provider.get_machines()370 mock_provider.get_machines()
371 self.mocker.result(fail(ProviderInteractionError("Bad")))371 self.mocker.result(fail(ProviderInteractionError()))
372372
373 mock_provider.get_machines()373 mock_provider.get_machines()
374 self.mocker.passthrough()374 self.mocker.passthrough()
375375
=== modified file 'ensemble/agents/tests/test_unit.py'
--- ensemble/agents/tests/test_unit.py 2011-07-29 14:42:04 +0000
+++ ensemble/agents/tests/test_unit.py 2011-08-26 13:09:07 +0000
@@ -118,10 +118,10 @@
118 e = self.assertRaises(EnsembleError,118 e = self.assertRaises(EnsembleError,
119 self.agent.configure,119 self.agent.configure,
120 options)120 options)
121 self.assertIn(121 self.assertEquals(
122 ("--unit-name must be provided in the command line,"122 str(e),
123 " or $ENSEMBLE_UNIT_NAME in the environment"),123 "--unit-name must be provided in the command line, or "
124 str(e))124 "$ENSEMBLE_UNIT_NAME in the environment")
125125
126 def test_agent_unit_name_cli_extraction(self):126 def test_agent_unit_name_cli_extraction(self):
127 """The unit agent can parse its unit-name from the cli.127 """The unit agent can parse its unit-name from the cli.
128128
=== modified file 'ensemble/control/status.py'
--- ensemble/control/status.py 2011-07-20 23:35:48 +0000
+++ ensemble/control/status.py 2011-08-26 13:09:07 +0000
@@ -7,7 +7,7 @@
7from twisted.internet.defer import inlineCallbacks, returnValue7from twisted.internet.defer import inlineCallbacks, returnValue
8import yaml8import yaml
99
10from ensemble.errors import ProviderInteractionError10from ensemble.errors import ProviderError
11from ensemble.environment.errors import EnvironmentsConfigError11from ensemble.environment.errors import EnvironmentsConfigError
12from ensemble.state.errors import UnitRelationStateNotFound12from ensemble.state.errors import UnitRelationStateNotFound
13from ensemble.state.formula import FormulaStateManager13from ensemble.state.formula import FormulaStateManager
@@ -264,10 +264,10 @@
264 try:264 try:
265 pm = yield machine_provider.get_machine(instance_id)265 pm = yield machine_provider.get_machine(instance_id)
266 m["dns-name"] = pm.dns_name266 m["dns-name"] = pm.dns_name
267 except ProviderInteractionError:267 except ProviderError:
268 # The provider doesn't have machine information268 # The provider doesn't have machine information
269 log.error("Machine provider information missing: machine %s" % (269 log.error("Machine provider information missing: machine %s" % (
270 machine_state.id))270 machine_state.id))
271271
272 machine_data[machine_state.id] = m272 machine_data[machine_state.id] = m
273273
274274
=== modified file 'ensemble/control/tests/test_status.py'
--- ensemble/control/tests/test_status.py 2011-08-08 21:51:54 +0000
+++ ensemble/control/tests/test_status.py 2011-08-26 13:09:07 +0000
@@ -458,7 +458,6 @@
458 self.assertEqual(state["machines"][7]["instance-id"],458 self.assertEqual(state["machines"][7]["instance-id"],
459 "pending")459 "pending")
460460
461
462 @inlineCallbacks461 @inlineCallbacks
463 def test_render_yaml(self):462 def test_render_yaml(self):
464 yield self.build_topology()463 yield self.build_topology()
@@ -610,7 +609,6 @@
610609
611 self.assertIn("namespace:dummy-1", result)610 self.assertIn("namespace:dummy-1", result)
612611
613
614 def test_render_dot_bad_clustering(self):612 def test_render_dot_bad_clustering(self):
615 """Test around Bug #792448.613 """Test around Bug #792448.
616614
617615
=== modified file 'ensemble/errors.py'
--- ensemble/errors.py 2011-08-17 17:26:19 +0000
+++ ensemble/errors.py 2011-08-26 13:09:07 +0000
@@ -48,7 +48,7 @@
48 self.path = path48 self.path = path
4949
50 def __str__(self):50 def __str__(self):
51 return "File was not found: %s" % (self.path,)51 return "File was not found: %r" % (self.path,)
5252
5353
54class FormulaError(EnsembleError):54class FormulaError(EnsembleError):
@@ -59,7 +59,7 @@
59 self.message = message59 self.message = message
6060
61 def __str__(self):61 def __str__(self):
62 return "Error processing '%s': %s." % (self.path, self.message)62 return "Error processing %r: %s" % (self.path, self.message)
6363
6464
65class FormulaInvocationError(EnsembleError):65class FormulaInvocationError(EnsembleError):
@@ -70,8 +70,8 @@
70 self.exit_code = exit_code70 self.exit_code = exit_code
7171
72 def __str__(self):72 def __str__(self):
73 return "Error processing '%s': exit code %s." % (self.path,73 return "Error processing %r: exit code %s." % (
74 self.exit_code)74 self.path, self.exit_code)
7575
7676
77class FileAlreadyExists(EnsembleError):77class FileAlreadyExists(EnsembleError):
@@ -84,7 +84,7 @@
84 self.path = path84 self.path = path
8585
86 def __str__(self):86 def __str__(self):
87 return "File already exists, won't overwrite: %s" % (self.path,)87 return "File already exists, won't overwrite: %r" % (self.path,)
8888
8989
90class InvalidEnsembleHeaderValue(EnsembleError):90class InvalidEnsembleHeaderValue(EnsembleError):
@@ -101,7 +101,7 @@
101101
102 def __str__(self):102 def __str__(self):
103 return ("Expected a YAML file with an 'ensemble: %s' "103 return ("Expected a YAML file with an 'ensemble: %s' "
104 "header, found 'ensemble: %s': %s"104 "header, found 'ensemble: %s': %r"
105 % (self.expected, self.found, self.path))105 % (self.expected, self.found, self.path))
106106
107107
@@ -130,12 +130,6 @@
130class EnvironmentPending(NoConnection):130class EnvironmentPending(NoConnection):
131 """Raised when the ensemble environment is not accessible."""131 """Raised when the ensemble environment is not accessible."""
132132
133 def __init__(self, info="no details available"):
134 self._info = info
135
136 def __str__(self):
137 return "Ensemble environment is not accessible: %s" % self._info
138
139133
140class ProviderError(EnsembleError):134class ProviderError(EnsembleError):
141 """Raised when an exception occurs in a provider."""135 """Raised when an exception occurs in a provider."""
@@ -154,13 +148,7 @@
154148
155149
156class ProviderInteractionError(ProviderError):150class ProviderInteractionError(ProviderError):
157151 """Raised when an unexpected error occurs interacting with a provider"""
158 def __init__(self, error):
159 self.error = error
160
161 def __str__(self):
162 return "ProviderError: Interaction with machine provider failed: %r" \
163 % self.error
164152
165153
166class CannotTerminateMachine(EnsembleError):154class CannotTerminateMachine(EnsembleError):
167155
=== modified file 'ensemble/formula/bundle.py'
--- ensemble/formula/bundle.py 2011-06-05 20:19:18 +0000
+++ ensemble/formula/bundle.py 2011-08-26 13:09:07 +0000
@@ -18,13 +18,13 @@
18 try:18 try:
19 zf = ZipFile(path, 'r')19 zf = ZipFile(path, 'r')
20 except BadZipfile, exc:20 except BadZipfile, exc:
21 raise FormulaError(path, "Must be a ZIP-file (%s)." % str(exc))21 raise FormulaError(path, "must be a zip file (%s)" % exc)
2222
23 metadata = MetaData()23 metadata = MetaData()
24 if "metadata.yaml" not in zf.namelist():24 if "metadata.yaml" not in zf.namelist():
25 raise FormulaError(path,25 raise FormulaError(path,
26 "Archive does not contain required file: "26 "archive does not contain required file "
27 "\"metadata.yaml\".")27 "\"metadata.yaml\"")
2828
29 content = zf.read("metadata.yaml")29 content = zf.read("metadata.yaml")
30 metadata.parse(content)30 metadata.parse(content)
3131
=== modified file 'ensemble/formula/provider.py'
--- ensemble/formula/provider.py 2010-11-02 16:15:23 +0000
+++ ensemble/formula/provider.py 2011-08-26 13:09:07 +0000
@@ -25,5 +25,5 @@
25 from .directory import FormulaDirectory25 from .directory import FormulaDirectory
26 return FormulaDirectory(specification)26 return FormulaDirectory(specification)
2727
28 raise FormulaError(specification, "Unable to process %s into a formula" % (28 raise FormulaError(specification, "unable to process %s into a formula" % (
29 specification))29 specification))
3030
=== modified file 'ensemble/formula/tests/test_bundle.py'
--- ensemble/formula/tests/test_bundle.py 2011-05-06 04:45:17 +0000
+++ ensemble/formula/tests/test_bundle.py 2011-08-26 13:09:07 +0000
@@ -38,8 +38,10 @@
38 try:38 try:
39 FormulaBundle(filename)39 FormulaBundle(filename)
40 except FormulaError, exc:40 except FormulaError, exc:
41 self.assertIn(filename, str(exc))41 self.assertEquals(
42 self.assertIn("zip", str(exc).lower())42 str(exc),
43 ("Error processing %r: " % filename) +
44 "must be a zip file (File is not a zip file)")
43 return45 return
4446
45 self.fail("Expected formula error.")47 self.fail("Expected formula error.")
@@ -53,8 +55,10 @@
53 try:55 try:
54 FormulaBundle(filename)56 FormulaBundle(filename)
55 except FormulaError, exc:57 except FormulaError, exc:
56 self.assertIn(filename, str(exc))58 self.assertEquals(
57 self.assertIn("metadata.yaml", str(exc).lower())59 str(exc),
60 ("Error processing %r: " % filename) +
61 "archive does not contain required file \"metadata.yaml\"")
58 return62 return
5963
60 self.fail("Expected formula error.")64 self.fail("Expected formula error.")
6165
=== modified file 'ensemble/formula/tests/test_config.py'
--- ensemble/formula/tests/test_config.py 2011-08-24 00:18:27 +0000
+++ ensemble/formula/tests/test_config.py 2011-08-26 13:09:07 +0000
@@ -102,7 +102,7 @@
102102
103 error = self.assertRaises(ServiceConfigError,103 error = self.assertRaises(ServiceConfigError,
104 self.config.validate, dict(username="1234"))104 self.config.validate, dict(username="1234"))
105 self.assertIn(str(error), "Invalid value for username: 1234")105 self.assertEquals(str(error), "Invalid value for username: 1234")
106106
107 data = self.config.validate(dict(username="12345678"))107 data = self.config.validate(dict(username="12345678"))
108 self.assertEqual(data, {"username": "12345678", "title": "My Title"})108 self.assertEqual(data, {"username": "12345678", "title": "My Title"})
@@ -114,15 +114,17 @@
114 error = self.assertRaises(ServiceConfigError,114 error = self.assertRaises(ServiceConfigError,
115 self.config.parse,115 self.config.parse,
116 local_configuration)116 local_configuration)
117 self.assertIn("options.fails.validator: required value not found",117 self.assertEquals(
118 str(error))118 str(error),
119 "Invalid options specification: options.fails.validator: "
120 "required value not found")
119121
120 def test_validate_types(self):122 def test_validate_types(self):
121 self.config.parse(sample_configuration)123 self.config.parse(sample_configuration)
122124
123 error = self.assertRaises(ServiceConfigError,125 error = self.assertRaises(ServiceConfigError,
124 self.config.validate, {"skill-level": "NaN"})126 self.config.validate, {"skill-level": "NaN"})
125 self.assertIn(str(error), "Invalid value for skill-level: NaN")127 self.assertEquals(str(error), "Invalid value for skill-level: NaN")
126128
127 data = self.config.validate({"skill-level": "9001"})129 data = self.config.validate({"skill-level": "9001"})
128 # its over 9000!130 # its over 9000!
129131
=== modified file 'ensemble/formula/tests/test_repository.py'
--- ensemble/formula/tests/test_repository.py 2011-07-15 12:41:01 +0000
+++ ensemble/formula/tests/test_repository.py 2011-08-26 13:09:07 +0000
@@ -85,11 +85,11 @@
85 self.assertTrue(formula.metadata)85 self.assertTrue(formula.metadata)
8686
87 def test_find_formula_by_name_fails(self):87 def test_find_formula_by_name_fails(self):
88 exc = self.assertRaises(88 error = self.assertRaises(
89 FormulaNotFound, self.repository1.find, "missing")89 FormulaNotFound, self.repository1.find, "missing")
90 self.assertIn("missing", str(exc))90 self.assertEquals(str(error),
91 self.assertIn(self.unbundled_repo_path, str(exc),91 "Formula 'missing' not found in repository %s"
92 "Repository path not found in the error message.")92 % self.unbundled_repo_path)
9393
94 def test_find_formula_with_multiple_versions_returns_latest(self):94 def test_find_formula_with_multiple_versions_returns_latest(self):
95 # Copy the repository out of the codebase, so that we can hack it.95 # Copy the repository out of the codebase, so that we can hack it.
9696
=== modified file 'ensemble/hooks/tests/test_arguments.py'
--- ensemble/hooks/tests/test_arguments.py 2011-06-11 02:37:35 +0000
+++ ensemble/hooks/tests/test_arguments.py 2011-08-26 13:09:07 +0000
@@ -52,8 +52,8 @@
52 err = self.capture_stream("stderr")52 err = self.capture_stream("stderr")
53 os.environ.pop("ENSEMBLE_AGENT_SOCKET", None)53 os.environ.pop("ENSEMBLE_AGENT_SOCKET", None)
54 error = self.failUnlessRaises(SystemExit, cli.parse_args)54 error = self.failUnlessRaises(SystemExit, cli.parse_args)
55 self.assertEquals("No ENSEMBLE_AGENT_SOCKET/-s option found",55 self.assertEquals(str(error),
56 str(error))56 "No ENSEMBLE_AGENT_SOCKET/-s option found")
57 self.assertIn("No ENSEMBLE_AGENT_SOCKET/-s option found",57 self.assertIn("No ENSEMBLE_AGENT_SOCKET/-s option found",
58 err.getvalue())58 err.getvalue())
5959
6060
=== modified file 'ensemble/hooks/tests/test_cli.py'
--- ensemble/hooks/tests/test_cli.py 2011-06-29 09:02:33 +0000
+++ ensemble/hooks/tests/test_cli.py 2011-08-26 13:09:07 +0000
@@ -335,12 +335,15 @@
335 # and check an error condition335 # and check an error condition
336 options = ["content=@missing"]336 options = ["content=@missing"]
337 error = self.assertRaises(EnsembleError, parse_keyvalue_pairs, options)337 error = self.assertRaises(EnsembleError, parse_keyvalue_pairs, options)
338 self.assertIn("No such file", str(error))338 self.assertEquals(
339 str(error),
340 "No such file or directory: missing (argument:content)")
339341
340 # and check when fed non-kvpairs the error makes sense342 # and check when fed non-kvpairs the error makes sense
341 options = ["foobar"]343 options = ["foobar"]
342 error = self.assertRaises(EnsembleError, parse_keyvalue_pairs, options)344 error = self.assertRaises(EnsembleError, parse_keyvalue_pairs, options)
343 self.assertIn("Expected `option=value`. Found `foobar`", str(error))345 self.assertEquals(
346 str(error), "Expected `option=value`. Found `foobar`")
344347
345 def test_parse_port_protocol(self):348 def test_parse_port_protocol(self):
346 self.assertEqual(parse_port_protocol("80"), (80, "tcp"))349 self.assertEqual(parse_port_protocol("80"), (80, "tcp"))
347350
=== modified file 'ensemble/hooks/tests/test_executor.py'
--- ensemble/hooks/tests/test_executor.py 2011-07-06 18:00:07 +0000
+++ ensemble/hooks/tests/test_executor.py 2011-08-26 13:09:07 +0000
@@ -326,7 +326,7 @@
326 error = yield self.assertFailure(326 error = yield self.assertFailure(
327 self._executor.run_priority_hook(invoke, "foobar"),327 self._executor.run_priority_hook(invoke, "foobar"),
328 AssertionError)328 AssertionError)
329 self.assertIn("Executor must not be running", str(error))329 self.assertEquals(str(error), "Executor must not be running")
330330
331 @inlineCallbacks331 @inlineCallbacks
332 def test_prioritize_with_queued(self):332 def test_prioritize_with_queued(self):
333333
=== modified file 'ensemble/hooks/tests/test_invoker.py'
--- ensemble/hooks/tests/test_invoker.py 2011-08-16 17:26:09 +0000
+++ ensemble/hooks/tests/test_invoker.py 2011-08-26 13:09:07 +0000
@@ -480,7 +480,7 @@
480 error = self.failUnlessRaises(errors.FormulaError, exe, hook)480 error = self.failUnlessRaises(errors.FormulaError, exe, hook)
481481
482 self.assertEqual(error.path, hook)482 self.assertEqual(error.path, hook)
483 self.assertIn(error.message, "hook is not executable")483 self.assertEqual(error.message, "hook is not executable")
484484
485 @defer.inlineCallbacks485 @defer.inlineCallbacks
486 def test_spawn_success(self):486 def test_spawn_success(self):
487487
=== modified file 'ensemble/lib/tests/test_schema.py'
--- ensemble/lib/tests/test_schema.py 2011-07-27 08:54:46 +0000
+++ ensemble/lib/tests/test_schema.py 2011-08-26 13:09:07 +0000
@@ -183,7 +183,7 @@
183 exp = "([a-"183 exp = "([a-"
184 error = self.assertRaises(184 error = self.assertRaises(
185 SchemaError, Regex().coerce, exp, PATH)185 SchemaError, Regex().coerce, exp, PATH)
186 self.assertIn("expected regex", str(error))186 self.assertEquals(str(error), "<path>: expected regex, got '([a-'")
187187
188188
189class ListTest(TestCase):189class ListTest(TestCase):
190190
=== modified file 'ensemble/machine/tests/test_unit_deployment.py'
--- ensemble/machine/tests/test_unit_deployment.py 2011-02-15 15:15:16 +0000
+++ ensemble/machine/tests/test_unit_deployment.py 2011-08-26 13:09:07 +0000
@@ -115,8 +115,8 @@
115115
116 self.failUnlessFailure(d, UnitDeploymentError)116 self.failUnlessFailure(d, UnitDeploymentError)
117117
118 def validate_result(result):118 def validate_result(error):
119 self.assertIn("No module named magichat", str(result))119 self.assertIn("No module named magichat", str(error))
120120
121 d.addCallback(validate_result)121 d.addCallback(validate_result)
122 return d122 return d
@@ -170,7 +170,7 @@
170 error = self.assertRaises(170 error = self.assertRaises(
171 UnitDeploymentError,171 UnitDeploymentError,
172 self.deployment.start, "0", get_test_zookeeper_address())172 self.deployment.start, "0", get_test_zookeeper_address())
173 self.assertIn("Formula must be unpacked first.", str(error))173 self.assertEquals(str(error), "Formula must be unpacked first.")
174174
175 @inlineCallbacks175 @inlineCallbacks
176 def test_service_unit_destroy(self):176 def test_service_unit_destroy(self):
@@ -269,7 +269,9 @@
269 error = self.assertRaises(269 error = self.assertRaises(
270 UnitDeploymentError,270 UnitDeploymentError,
271 self.deployment.unpack_formula, self.formula)271 self.deployment.unpack_formula, self.formula)
272 self.assertIn("Invalid formula for deployment:", str(error))272 self.assertEquals(
273 str(error),
274 "Invalid formula for deployment: %s" % self.formula.path)
273275
274 def test_is_running_no_pid_file(self):276 def test_is_running_no_pid_file(self):
275 """277 """
276278
=== modified file 'ensemble/machine/unit.py'
--- ensemble/machine/unit.py 2011-02-15 15:15:16 +0000
+++ ensemble/machine/unit.py 2011-08-26 13:09:07 +0000
@@ -123,6 +123,6 @@
123 """Unpack a formula to the service units directory."""123 """Unpack a formula to the service units directory."""
124 if not isinstance(formula, FormulaBundle):124 if not isinstance(formula, FormulaBundle):
125 raise UnitDeploymentError(125 raise UnitDeploymentError(
126 "Invalid formula for deployment: %r" % formula)126 "Invalid formula for deployment: %s" % formula.path)
127127
128 formula.extract_to(os.path.join(self.directory, "formula"))128 formula.extract_to(os.path.join(self.directory, "formula"))
129129
=== modified file 'ensemble/providers/common/connect.py'
--- ensemble/providers/common/connect.py 2011-08-23 08:42:30 +0000
+++ ensemble/providers/common/connect.py 2011-08-26 13:09:07 +0000
@@ -36,7 +36,7 @@
36 for machine in machines:36 for machine in machines:
37 if machine.dns_name:37 if machine.dns_name:
38 return machine38 return machine
39 raise EnvironmentPending("no machines have addresses assigned yet")39 raise EnvironmentPending("No machines have addresses assigned yet")
4040
41 def _connect_to_machine(self, machine, share):41 def _connect_to_machine(self, machine, share):
42 log.info("Connecting to environment.")42 log.info("Connecting to environment.")
@@ -48,7 +48,7 @@
48 def _cannot_connect(self, failure, machine):48 def _cannot_connect(self, failure, machine):
49 failure.trap(NoConnection, ConnectionTimeoutException)49 failure.trap(NoConnection, ConnectionTimeoutException)
50 raise EnvironmentPending(50 raise EnvironmentPending(
51 "machine %s may not be ready (%s)"51 "Cannot connect to machine %s (perhaps still initializing): %s"
52 % (machine.instance_id, str(failure.value)))52 % (machine.instance_id, str(failure.value)))
5353
54 @inlineCallbacks54 @inlineCallbacks
5555
=== modified file 'ensemble/providers/common/findzookeepers.py'
--- ensemble/providers/common/findzookeepers.py 2011-08-16 13:24:41 +0000
+++ ensemble/providers/common/findzookeepers.py 2011-08-26 13:09:07 +0000
@@ -26,5 +26,5 @@
2626
27 if machines:27 if machines:
28 returnValue(machines)28 returnValue(machines)
29 raise EnvironmentNotFound("machines are not running (%s)."29 raise EnvironmentNotFound("machines are not running (%s)"
30 % ", ".join(missing_instance_ids))30 % ", ".join(missing_instance_ids))
3131
=== modified file 'ensemble/providers/common/tests/test_connect.py'
--- ensemble/providers/common/tests/test_connect.py 2011-08-19 16:12:22 +0000
+++ ensemble/providers/common/tests/test_connect.py 2011-08-26 13:09:07 +0000
@@ -59,9 +59,7 @@
5959
60 def check(error):60 def check(error):
61 self.assertEquals(61 self.assertEquals(
62 str(error),62 str(error), "No machines have addresses assigned yet")
63 "Ensemble environment is not accessible: no machines have "
64 "addresses assigned yet")
65 d.addCallback(check)63 d.addCallback(check)
66 return d64 return d
6765
@@ -85,8 +83,8 @@
85 """`NoConnection` errors should become `EnvironmentPending`s"""83 """`NoConnection` errors should become `EnvironmentPending`s"""
86 return self.assert_connect_error(84 return self.assert_connect_error(
87 NoConnection("KABOOM!"), EnvironmentPending,85 NoConnection("KABOOM!"), EnvironmentPending,
88 "Ensemble environment is not accessible: machine i-exist may "86 "Cannot connect to machine i-exist (perhaps still initializing): "
89 "not be ready (KABOOM!)")87 "KABOOM!")
9088
91 def test_txzookeeper_error(self):89 def test_txzookeeper_error(self):
92 """90 """
@@ -94,8 +92,8 @@
94 """92 """
95 return self.assert_connect_error(93 return self.assert_connect_error(
96 ConnectionTimeoutException("SPLAT!"), EnvironmentPending,94 ConnectionTimeoutException("SPLAT!"), EnvironmentPending,
97 "Ensemble environment is not accessible: machine i-exist may "95 "Cannot connect to machine i-exist (perhaps still initializing): "
98 "not be ready (SPLAT!)")96 "SPLAT!")
9997
100 def test_other_error(self):98 def test_other_error(self):
101 """Other errors should propagate"""99 """Other errors should propagate"""
102100
=== modified file 'ensemble/providers/common/tests/test_findzookeepers.py'
--- ensemble/providers/common/tests/test_findzookeepers.py 2011-08-16 13:44:01 +0000
+++ ensemble/providers/common/tests/test_findzookeepers.py 2011-08-26 13:09:07 +0000
@@ -37,12 +37,27 @@
37 provider = self.get_provider(False)37 provider = self.get_provider(False)
38 d = provider.get_zookeeper_machines()38 d = provider.get_zookeeper_machines()
39 self.assertFailure(d, EnvironmentNotFound)39 self.assertFailure(d, EnvironmentNotFound)
40
41 def check(error):
42 self.assertEquals(
43 str(error),
44 "Ensemble environment not found: is the environment "
45 "bootstrapped?")
46 d.addCallback(check)
40 return d47 return d
4148
42 def test_empty_state(self):49 def test_empty_state(self):
43 provider = self.get_provider({})50 provider = self.get_provider({})
44 d = provider.get_zookeeper_machines()51 d = provider.get_zookeeper_machines()
45 self.assertFailure(d, EnvironmentNotFound)52 self.assertFailure(d, EnvironmentNotFound)
53
54 def check(error):
55 self.assertEquals(
56 str(error),
57 "Ensemble environment not found: is the environment "
58 "bootstrapped?")
59 d.addCallback(check)
60 return d
46 return d61 return d
4762
48 def test_get_machine_error_aborts(self):63 def test_get_machine_error_aborts(self):
@@ -56,14 +71,24 @@
56 self.assertFailure(d, SomeError)71 self.assertFailure(d, SomeError)
57 return d72 return d
5873
59 def test_bad_machine(self):74 def test_bad_machines(self):
60 provider = self.get_provider({"zookeeper-instances": ["porter"]})75 provider = self.get_provider({
76 "zookeeper-instances": ["porter", "carter"]})
61 provider.get_machines(["porter"])77 provider.get_machines(["porter"])
62 self.mocker.result(fail(MachinesNotFound(["porter"])))78 self.mocker.result(fail(MachinesNotFound(["porter"])))
79 provider.get_machines(["carter"])
80 self.mocker.result(fail(MachinesNotFound(["carter"])))
63 self.mocker.replay()81 self.mocker.replay()
6482
65 d = provider.get_zookeeper_machines()83 d = provider.get_zookeeper_machines()
66 self.assertFailure(d, EnvironmentNotFound)84 self.assertFailure(d, EnvironmentNotFound)
85
86 def check(error):
87 self.assertEquals(
88 str(error),
89 "Ensemble environment not found: machines are not running "
90 "(porter, carter)")
91 d.addCallback(check)
67 return d92 return d
6893
69 def test_good_machine(self):94 def test_good_machine(self):
7095
=== modified file 'ensemble/providers/common/tests/test_utils.py'
--- ensemble/providers/common/tests/test_utils.py 2011-08-11 22:04:38 +0000
+++ ensemble/providers/common/tests/test_utils.py 2011-08-26 13:09:07 +0000
@@ -63,9 +63,7 @@
63 OSError("Bad"))63 OSError("Bad"))
64 self.assertInstance(error, EnsembleError)64 self.assertInstance(error, EnsembleError)
65 self.assertEqual(65 self.assertEqual(
66 str(error),66 str(error), "Unexpected OSError interacting with provider: Bad")
67 "ProviderError: Interaction with machine provider failed: "
68 "OSError('Bad',)")
6967
70 def test_convert_unknown_error_ignores_ensemble_error(self):68 def test_convert_unknown_error_ignores_ensemble_error(self):
71 error = self.assertRaises(69 error = self.assertRaises(
@@ -87,8 +85,7 @@
87 self.assertInstance(failure.value, ProviderInteractionError)85 self.assertInstance(failure.value, ProviderInteractionError)
88 self.assertEqual(86 self.assertEqual(
89 str(failure.value),87 str(failure.value),
90 "ProviderError: Interaction with machine provider failed: "88 "Unexpected OSError interacting with provider: Bad")
91 "OSError('Bad',)")
9289
9390
94class FormatCloudInitTest(TestCase):91class FormatCloudInitTest(TestCase):
9592
=== modified file 'ensemble/providers/common/utils.py'
--- ensemble/providers/common/utils.py 2011-08-03 15:53:38 +0000
+++ ensemble/providers/common/utils.py 2011-08-26 13:09:07 +0000
@@ -31,7 +31,9 @@
31 error = failure31 error = failure
3232
33 if not isinstance(error, EnsembleError):33 if not isinstance(error, EnsembleError):
34 error = ProviderInteractionError(error)34 message = ("Unexpected %s interacting with provider: %s"
35 % (type(error).__name__, str(error)))
36 error = ProviderInteractionError(message)
3537
36 if isinstance(failure, Failure):38 if isinstance(failure, Failure):
37 return Failure(error)39 return Failure(error)
3840
=== modified file 'ensemble/providers/ec2/__init__.py'
--- ensemble/providers/ec2/__init__.py 2011-08-25 16:41:03 +0000
+++ ensemble/providers/ec2/__init__.py 2011-08-26 13:09:07 +0000
@@ -77,13 +77,14 @@
77 instances = yield self.ec2.describe_instances(*instance_ids)77 instances = yield self.ec2.describe_instances(*instance_ids)
78 except EC2Error as error:78 except EC2Error as error:
79 code = error.get_error_codes()79 code = error.get_error_codes()
80 message = error.get_error_messages()
80 if code == "InvalidInstanceID.NotFound":81 if code == "InvalidInstanceID.NotFound":
81 message = error.get_error_messages()82 message = error.get_error_messages()
82 raise MachinesNotFound(83 raise MachinesNotFound(
83 re.findall(r"\bi-[0-9a-f]{3,15}\b", message))84 re.findall(r"\bi-[0-9a-f]{3,15}\b", message))
84 raise ProviderInteractionError(85 raise ProviderInteractionError(
85 "EC2 error when looking up instances %s: %s"86 "Unexpected EC2Error getting machines %s: %s"
86 % (", ".join(instance_ids), error.get_error_messages()))87 % (", ".join(instance_ids), message))
8788
88 machines = []89 machines = []
89 for instance in instances:90 for instance in instances:
9091
=== modified file 'ensemble/providers/ec2/launch.py'
--- ensemble/providers/ec2/launch.py 2011-08-10 17:23:06 +0000
+++ ensemble/providers/ec2/launch.py 2011-08-26 13:09:07 +0000
@@ -123,9 +123,8 @@
123 log.debug("Cannot delete security group %s: %s",123 log.debug("Cannot delete security group %s: %s",
124 ensemble_machine_group, e)124 ensemble_machine_group, e)
125 raise ProviderInteractionError(125 raise ProviderInteractionError(
126 "EC2 error when attempting to delete "126 "Unexpected EC2Error deleting security group %s: %s"
127 "security group %s: %s" % (127 % (ensemble_machine_group, e.get_error_messages()))
128 ensemble_machine_group, e))
129 log.debug("Creating ensemble machine security group %s",128 log.debug("Creating ensemble machine security group %s",
130 ensemble_machine_group)129 ensemble_machine_group)
131 yield self._provider.ec2.create_security_group(130 yield self._provider.ec2.create_security_group(
132131
=== modified file 'ensemble/providers/ec2/securitygroup.py'
--- ensemble/providers/ec2/securitygroup.py 2011-08-10 17:23:06 +0000
+++ ensemble/providers/ec2/securitygroup.py 2011-08-26 13:09:07 +0000
@@ -38,8 +38,8 @@
38 port, protocol, machine.instance_id)38 port, protocol, machine.instance_id)
39 except EC2Error, e:39 except EC2Error, e:
40 raise ProviderInteractionError(40 raise ProviderInteractionError(
41 "EC2 error when attempting to open %s/%s on machine %s: %s" % (41 "Unexpected EC2Error opening %s/%s on machine %s: %s"
42 port, protocol, machine.instance_id, e))42 % (port, protocol, machine.instance_id, e.get_error_messages()))
4343
4444
45@inlineCallbacks45@inlineCallbacks
@@ -55,8 +55,8 @@
55 port, protocol, machine.instance_id)55 port, protocol, machine.instance_id)
56 except EC2Error, e:56 except EC2Error, e:
57 raise ProviderInteractionError(57 raise ProviderInteractionError(
58 "EC2 error when attempting to close %s/%s on machine %s: %s" % (58 "Unexpected EC2Error closing %s/%s on machine %s: %s"
59 port, protocol, machine.instance_id, e))59 % (port, protocol, machine.instance_id, e.get_error_messages()))
6060
6161
62@inlineCallbacks62@inlineCallbacks
@@ -72,9 +72,8 @@
72 _get_machine_group_name(provider, machine_id))72 _get_machine_group_name(provider, machine_id))
73 except EC2Error, e:73 except EC2Error, e:
74 raise ProviderInteractionError(74 raise ProviderInteractionError(
75 "EC2 error when attempting to get opened ports "75 "Unexpected EC2Error getting open ports on machine %s: %s"
76 "on machine %s: %s" % (76 % (machine.instance_id, e.get_error_messages()))
77 machine.instance_id, e))
7877
79 opened_ports = set() # made up of (port, protocol) pairs78 opened_ports = set() # made up of (port, protocol) pairs
80 for ip_permission in security_groups[0].allowed_ips:79 for ip_permission in security_groups[0].allowed_ips:
8180
=== modified file 'ensemble/providers/ec2/tests/common.py'
--- ensemble/providers/ec2/tests/common.py 2011-08-22 23:03:03 +0000
+++ ensemble/providers/ec2/tests/common.py 2011-08-26 13:09:07 +0000
@@ -59,16 +59,6 @@
59 "<error><Code>1</Code><Message>%s</Message></error>" % message,59 "<error><Code>1</Code><Message>%s</Message></error>" % message,
60 code)60 code)
6161
62 def get_wrapped_ec2_error_text(self, entity_id, reason,
63 format="The instance ID %r does not exist"):
64 """By convention, `EC2Error` is wrapped as a `ProviderError`"""
65 message = format % entity_id
66 return (
67 "ProviderError: Interaction with machine provider failed: "
68 "\"EC2 error when attempting to %s %s: "
69 "Error Message: %s\"" % (
70 reason, entity_id, message))
71
72 def setUp(self):62 def setUp(self):
73 # mock out the aws services63 # mock out the aws services
74 service_factory = self.mocker.replace(64 service_factory = self.mocker.replace(
7565
=== modified file 'ensemble/providers/ec2/tests/test_connect.py'
--- ensemble/providers/ec2/tests/test_connect.py 2011-08-19 16:12:22 +0000
+++ ensemble/providers/ec2/tests/test_connect.py 2011-08-26 13:09:07 +0000
@@ -59,9 +59,7 @@
5959
60 def check_error(error):60 def check_error(error):
61 self.assertEqual(61 self.assertEqual(
62 str(error),62 str(error), "No machines have addresses assigned yet")
63 "Ensemble environment is not accessible: no machines have "
64 "addresses assigned yet")
6563
66 self.assertFailure(d, NoConnection)64 self.assertFailure(d, NoConnection)
67 d.addCallback(check_error)65 d.addCallback(check_error)
@@ -89,8 +87,8 @@
89 """`NoConnection` errors should become `EnvironmentPending`s"""87 """`NoConnection` errors should become `EnvironmentPending`s"""
90 return self.assert_connect_error(88 return self.assert_connect_error(
91 NoConnection("KABOOM!"), EnvironmentPending,89 NoConnection("KABOOM!"), EnvironmentPending,
92 "Ensemble environment is not accessible: machine i-foobar may "90 "Cannot connect to machine i-foobar (perhaps still initializing): "
93 "not be ready (KABOOM!)")91 "KABOOM!")
9492
95 def test_txzookeeper_error(self):93 def test_txzookeeper_error(self):
96 """94 """
@@ -98,8 +96,8 @@
98 """96 """
99 return self.assert_connect_error(97 return self.assert_connect_error(
100 ConnectionTimeoutException("SPLAT!"), EnvironmentPending,98 ConnectionTimeoutException("SPLAT!"), EnvironmentPending,
101 "Ensemble environment is not accessible: machine i-foobar may "99 "Cannot connect to machine i-foobar (perhaps still initializing): "
102 "not be ready (SPLAT!)")100 "SPLAT!")
103101
104 def test_other_error(self):102 def test_other_error(self):
105 """Other errors should propagate"""103 """Other errors should propagate"""
106104
=== modified file 'ensemble/providers/ec2/tests/test_getmachines.py'
--- ensemble/providers/ec2/tests/test_getmachines.py 2011-08-17 08:58:51 +0000
+++ ensemble/providers/ec2/tests/test_getmachines.py 2011-08-26 13:09:07 +0000
@@ -132,9 +132,8 @@
132 def verify(error):132 def verify(error):
133 self.assertEquals(133 self.assertEquals(
134 str(error),134 str(error),
135 "ProviderError: Interaction with machine provider failed: "135 "Unexpected EC2Error getting machines i-brokeit, i-msorry: "
136 "\"EC2 error when looking up instances i-brokeit, i-msorry: "136 "unhelpful noises ('splat! kerpow!')")
137 "unhelpful noises ('splat! kerpow!')\"")
138 d.addCallback(verify)137 d.addCallback(verify)
139 return d138 return d
140139
141140
=== modified file 'ensemble/providers/ec2/tests/test_launch.py'
--- ensemble/providers/ec2/tests/test_launch.py 2011-08-16 13:55:11 +0000
+++ ensemble/providers/ec2/tests/test_launch.py 2011-08-26 13:09:07 +0000
@@ -141,10 +141,9 @@
141 ProviderInteractionError)141 ProviderInteractionError)
142 self.assertEqual(142 self.assertEqual(
143 str(ex),143 str(ex),
144 self.get_wrapped_ec2_error_text(144 "Unexpected EC2Error deleting security group "
145 "ensemble-moon-machine-1", "delete security group",145 "ensemble-moon-machine-1: There are active instances using "
146 "There are active instances using security group %r"146 "security group 'ensemble-moon-machine-1'")
147 ))
148147
149 def test_provider_type_machine_variable(self):148 def test_provider_type_machine_variable(self):
150 """The provider type is available via cloud-init."""149 """The provider type is available via cloud-init."""
151150
=== modified file 'ensemble/providers/ec2/tests/test_provider.py'
--- ensemble/providers/ec2/tests/test_provider.py 2011-08-11 19:49:32 +0000
+++ ensemble/providers/ec2/tests/test_provider.py 2011-08-26 13:09:07 +0000
@@ -127,4 +127,7 @@
127 config["authorized-keys-path"] = "File path"127 config["authorized-keys-path"] = "File path"
128 error = self.assertRaises(EnvironmentsConfigError,128 error = self.assertRaises(EnvironmentsConfigError,
129 MachineProvider, "some-env-name", config)129 MachineProvider, "some-env-name", config)
130 self.assertIn("authorized-keys", str(error))130 self.assertEquals(
131 str(error),
132 "Environment config cannot define both authorized-keys and "
133 "authorized-keys-path. Pick one!")
131134
=== modified file 'ensemble/providers/ec2/tests/test_securitygroup.py'
--- ensemble/providers/ec2/tests/test_securitygroup.py 2011-08-10 17:19:09 +0000
+++ ensemble/providers/ec2/tests/test_securitygroup.py 2011-08-26 13:09:07 +0000
@@ -89,8 +89,8 @@
89 ProviderInteractionError)89 ProviderInteractionError)
90 self.assertEqual(90 self.assertEqual(
91 str(ex),91 str(ex),
92 self.get_wrapped_ec2_error_text(92 "Unexpected EC2Error opening 80/tcp on machine i-foobar: "
93 "i-foobar", "open 80/tcp on machine"))93 "The instance ID 'i-foobar' does not exist")
9494
95 @inlineCallbacks95 @inlineCallbacks
96 def test_close_provider_port_unknown_instance(self):96 def test_close_provider_port_unknown_instance(self):
@@ -108,8 +108,8 @@
108 ProviderInteractionError)108 ProviderInteractionError)
109 self.assertEqual(109 self.assertEqual(
110 str(ex),110 str(ex),
111 self.get_wrapped_ec2_error_text(111 "Unexpected EC2Error closing 80/tcp on machine i-foobar: "
112 "i-foobar", "close 80/tcp on machine"))112 "The instance ID 'i-foobar' does not exist")
113113
114 @inlineCallbacks114 @inlineCallbacks
115 def test_get_provider_opened_ports_unknown_instance(self):115 def test_get_provider_opened_ports_unknown_instance(self):
@@ -125,5 +125,5 @@
125 ProviderInteractionError)125 ProviderInteractionError)
126 self.assertEqual(126 self.assertEqual(
127 str(ex),127 str(ex),
128 self.get_wrapped_ec2_error_text(128 "Unexpected EC2Error getting open ports on machine i-foobar: "
129 "i-foobar", "get opened ports on machine"))129 "The instance ID 'i-foobar' does not exist")
130130
=== modified file 'ensemble/providers/orchestra/cobbler.py'
--- ensemble/providers/orchestra/cobbler.py 2011-08-22 13:01:02 +0000
+++ ensemble/providers/orchestra/cobbler.py 2011-08-26 13:09:07 +0000
@@ -3,8 +3,7 @@
3from twisted.internet.defer import inlineCallbacks, returnValue3from twisted.internet.defer import inlineCallbacks, returnValue
4from twisted.web.xmlrpc import Proxy4from twisted.web.xmlrpc import Proxy
55
6from ensemble.errors import (6from ensemble.errors import MachinesNotFound, ProviderError
7 MachinesNotFound, ProviderError, ProviderInteractionError)
87
98
10class CobblerCaller(object):9class CobblerCaller(object):
@@ -62,7 +61,7 @@
62 def check(actual):61 def check(actual):
63 if actual != expect:62 if actual != expect:
64 raise ProviderError(63 raise ProviderError(
65 "Bad result from call to %s with %s (got %r, expected %r)"64 "Bad result from call to %s with %s: got %r, expected %r"
66 % (name, args, actual, expect))65 % (name, args, actual, expect))
67 return actual66 return actual
6867
@@ -84,8 +83,9 @@
8483
85 def extract_name(systems):84 def extract_name(systems):
86 if len(systems) > 1:85 if len(systems) > 1:
87 raise ProviderInteractionError(86 raise ProviderError(
88 "Got multiple instances with id %s" % instance_id)87 "Got multiple names for machine %s: %s"
88 % (instance_id, ", ".join(systems)))
89 if not systems:89 if not systems:
90 raise MachinesNotFound([instance_id])90 raise MachinesNotFound([instance_id])
91 return systems[0]91 return systems[0]
9292
=== modified file 'ensemble/providers/orchestra/tests/test_cobbler.py'
--- ensemble/providers/orchestra/tests/test_cobbler.py 2011-08-12 21:35:34 +0000
+++ ensemble/providers/orchestra/tests/test_cobbler.py 2011-08-26 13:09:07 +0000
@@ -3,8 +3,7 @@
3from twisted.internet.defer import fail, succeed3from twisted.internet.defer import fail, succeed
4from twisted.web.xmlrpc import Proxy4from twisted.web.xmlrpc import Proxy
55
6from ensemble.errors import (6from ensemble.errors import MachinesNotFound, ProviderError
7 MachinesNotFound, ProviderError, ProviderInteractionError)
8from ensemble.lib.testing import TestCase7from ensemble.lib.testing import TestCase
9from ensemble.providers.orchestra.cobbler import CobblerCaller, CobblerClient8from ensemble.providers.orchestra.cobbler import CobblerCaller, CobblerClient
109
@@ -243,11 +242,14 @@
243 d.addCallback(verify)242 d.addCallback(verify)
244 return d243 return d
245244
246 def check_bad_call(self, d, method):245 def check_bad_call(self, d, method, args):
247 self.assertFailure(d, ProviderError)246 self.assertFailure(d, ProviderError)
248247
249 def verify(error):248 def verify(error):
250 self.assertIn("Bad result from call to %s" % method, str(error))249 self.assertEquals(
250 str(error),
251 "Bad result from call to %s with %s: got False, expected True"
252 % (method, args))
251 d.addCallback(verify)253 d.addCallback(verify)
252 return d254 return d
253255
@@ -261,11 +263,13 @@
261 self.mock_get_name(succeed(["some-name", "another-name"]))263 self.mock_get_name(succeed(["some-name", "another-name"]))
262 self.mocker.replay()264 self.mocker.replay()
263 d = self.call_cobbler_method(method_name, *args)265 d = self.call_cobbler_method(method_name, *args)
264 self.assertFailure(d, ProviderInteractionError)266 self.assertFailure(d, ProviderError)
265267
266 def check_error(error):268 def check_error(error):
267 self.assertIn("Got multiple instances with id some-uid",269 self.assertEquals(
268 str(error))270 str(error),
271 "Got multiple names for machine some-uid: some-name, "
272 "another-name")
269 d.addCallback(check_error)273 d.addCallback(check_error)
270 return d274 return d
271275
@@ -301,7 +305,8 @@
301 self.mock_modify_system(succeed(False), key, value)305 self.mock_modify_system(succeed(False), key, value)
302 self.mocker.replay()306 self.mocker.replay()
303 d = self.call_cobbler_method(method_name, *args)307 d = self.call_cobbler_method(method_name, *args)
304 return self.check_bad_call(d, "modify_system")308 return self.check_bad_call(
309 d, "modify_system", ("some-handle", key, value))
305310
306 def check_modify_system_error(self, key, value, method_name, *args):311 def check_modify_system_error(self, key, value, method_name, *args):
307 self.mock_modify_system(fail(SomeError()), key, value)312 self.mock_modify_system(fail(SomeError()), key, value)
@@ -314,7 +319,7 @@
314 self.mock_save_system(succeed(False))319 self.mock_save_system(succeed(False))
315 self.mocker.replay()320 self.mocker.replay()
316 d = self.call_cobbler_method(method_name, *args)321 d = self.call_cobbler_method(method_name, *args)
317 return self.check_bad_call(d, "save_system")322 return self.check_bad_call(d, "save_system", ("some-handle",))
318323
319 def check_save_system_error(self, method_name, *args):324 def check_save_system_error(self, method_name, *args):
320 self.mock_save_system(fail(SomeError()))325 self.mock_save_system(fail(SomeError()))
321326
=== modified file 'ensemble/providers/orchestra/tests/test_connect.py'
--- ensemble/providers/orchestra/tests/test_connect.py 2011-08-19 16:12:22 +0000
+++ ensemble/providers/orchestra/tests/test_connect.py 2011-08-26 13:09:07 +0000
@@ -62,8 +62,8 @@
62 """`NoConnection` errors should become `EnvironmentPending`s"""62 """`NoConnection` errors should become `EnvironmentPending`s"""
63 return self.assert_connect_error(63 return self.assert_connect_error(
64 NoConnection("KABOOM!"), EnvironmentPending,64 NoConnection("KABOOM!"), EnvironmentPending,
65 "Ensemble environment is not accessible: machine foo may not be "65 "Cannot connect to machine foo (perhaps still initializing): "
66 "ready (KABOOM!)")66 "KABOOM!")
6767
68 def test_txzookeeper_error(self):68 def test_txzookeeper_error(self):
69 """69 """
@@ -71,8 +71,8 @@
71 """71 """
72 return self.assert_connect_error(72 return self.assert_connect_error(
73 ConnectionTimeoutException("SPLAT!"), EnvironmentPending,73 ConnectionTimeoutException("SPLAT!"), EnvironmentPending,
74 "Ensemble environment is not accessible: machine foo may not be "74 "Cannot connect to machine foo (perhaps still initializing): "
75 "ready (SPLAT!)")75 "SPLAT!")
7676
77 def test_other_error(self):77 def test_other_error(self):
78 """Other errors should propagate"""78 """Other errors should propagate"""
7979
=== modified file 'ensemble/providers/orchestra/tests/test_launch.py'
--- ensemble/providers/orchestra/tests/test_launch.py 2011-08-11 23:27:45 +0000
+++ ensemble/providers/orchestra/tests/test_launch.py 2011-08-26 13:09:07 +0000
@@ -30,9 +30,13 @@
3030
31 d = self.get_provider().start_machine({"machine-id": "32767"})31 d = self.get_provider().start_machine({"machine-id": "32767"})
32 self.assertFailure(d, ProviderError)32 self.assertFailure(d, ProviderError)
33 self.assertIn("Could not find any Cobbler systems marked as available "33
34 "and configured for network boot.",34 def verify(error):
35 str(d))35 self.assertEquals(
36 str(error),
37 "Could not find any Cobbler systems marked as available and "
38 "configured for network boot.")
39 d.addCallback(verify)
36 return d40 return d
3741
38 def test_no_acceptable_machines(self):42 def test_no_acceptable_machines(self):
@@ -43,9 +47,13 @@
4347
44 d = self.get_provider().start_machine({"machine-id": "32767"})48 d = self.get_provider().start_machine({"machine-id": "32767"})
45 self.assertFailure(d, ProviderError)49 self.assertFailure(d, ProviderError)
46 self.assertIn("All available Cobbler systems were also marked as "50
47 "acquired (instances: bad-system-uid).",51 def verify(error):
48 str(d))52 self.assertEquals(
53 str(error),
54 "All available Cobbler systems were also marked as acquired "
55 "(instances: bad-system-uid).")
56 d.addCallback(verify)
49 return d57 return d
5058
51 def test_actually_launch(self):59 def test_actually_launch(self):
5260
=== modified file 'ensemble/providers/orchestra/tests/test_provider.py'
--- ensemble/providers/orchestra/tests/test_provider.py 2011-08-23 16:07:09 +0000
+++ ensemble/providers/orchestra/tests/test_provider.py 2011-08-26 13:09:07 +0000
@@ -53,7 +53,10 @@
53 config["authorized-keys-path"] = "File path"53 config["authorized-keys-path"] = "File path"
54 error = self.assertRaises(EnvironmentsConfigError,54 error = self.assertRaises(EnvironmentsConfigError,
55 MachineProvider, "some-env-name", config)55 MachineProvider, "some-env-name", config)
56 self.assertIn("authorized-keys", str(error))56 self.assertEquals(
57 str(error),
58 "Environment config cannot define both authorized-keys and "
59 "authorized-keys-path. Pick one!")
5760
58 @inlineCallbacks61 @inlineCallbacks
59 def test_open_port(self):62 def test_open_port(self):
@@ -75,4 +78,3 @@
75 yield MachineProvider("blah", CONFIG).get_opened_ports(None, None)78 yield MachineProvider("blah", CONFIG).get_opened_ports(None, None)
76 self.assertIn(79 self.assertIn(
77 "Firewalling is not yet implemented in Orchestra", log.getvalue())80 "Firewalling is not yet implemented in Orchestra", log.getvalue())
78
7981
=== modified file 'ensemble/state/service.py'
--- ensemble/state/service.py 2011-08-08 03:22:15 +0000
+++ ensemble/state/service.py 2011-08-26 13:09:07 +0000
@@ -855,7 +855,8 @@
855 cleared.855 cleared.
856 """856 """
857 if not isinstance(hook_names, (list, tuple)):857 if not isinstance(hook_names, (list, tuple)):
858 raise AssertionError("hook names must be a list %r" % hook_names)858 raise AssertionError("Hook names must be a list: got %r"
859 % hook_names)
859860
860 if "*" in hook_names and len(hook_names) > 1:861 if "*" in hook_names and len(hook_names) > 1:
861 msg = "Ambigious to debug all hooks and named hooks %r" % (862 msg = "Ambigious to debug all hooks and named hooks %r" % (
862863
=== modified file 'ensemble/state/tests/test_security.py'
--- ensemble/state/tests/test_security.py 2011-08-05 22:55:52 +0000
+++ ensemble/state/tests/test_security.py 2011-08-26 13:09:07 +0000
@@ -316,7 +316,7 @@
316 principal = Principal("zebra", "zoo")316 principal = Principal("zebra", "zoo")
317 error = yield self.assertFailure(self.db.get(principal.name),317 error = yield self.assertFailure(self.db.get(principal.name),
318 PrincipalNotFound)318 PrincipalNotFound)
319 self.assertIn("zebra", str(error))319 self.assertEquals(str(error), "Principal 'zebra' not found")
320320
321321
322class PolicyTest(TestCase):322class PolicyTest(TestCase):
323323
=== modified file 'ensemble/state/tests/test_service.py'
--- ensemble/state/tests/test_service.py 2011-08-22 23:02:38 +0000
+++ ensemble/state/tests/test_service.py 2011-08-26 13:09:07 +0000
@@ -1111,8 +1111,10 @@
1111 error = yield self.assertFailure(1111 error = yield self.assertFailure(
1112 unit_state.enable_hook_debug(["*", "db-relation-changed"]),1112 unit_state.enable_hook_debug(["*", "db-relation-changed"]),
1113 ValueError)1113 ValueError)
1114 self.assertIn("Ambigious to debug all hooks and named hooks",1114 self.assertEquals(
1115 str(error))1115 str(error),
1116 "Ambigious to debug all hooks and named hooks "
1117 "['*', 'db-relation-changed']")
11161118
1117 @inlineCallbacks1119 @inlineCallbacks
1118 def test_enable_debug_requires_sequence(self):1120 def test_enable_debug_requires_sequence(self):
@@ -1123,7 +1125,7 @@
1123 error = yield self.assertFailure(1125 error = yield self.assertFailure(
1124 unit_state.enable_hook_debug(None),1126 unit_state.enable_hook_debug(None),
1125 AssertionError)1127 AssertionError)
1126 self.assertIn("hook names must be a list", str(error))1128 self.assertEquals(str(error), "Hook names must be a list: got None")
11271129
1128 @inlineCallbacks1130 @inlineCallbacks
1129 def test_enable_named_debug_hook(self):1131 def test_enable_named_debug_hook(self):
@@ -1144,8 +1146,10 @@
1144 """1146 """
1145 unit_state = yield self.get_unit_state()1147 unit_state = yield self.get_unit_state()
1146 yield unit_state.enable_hook_debug(["*"])1148 yield unit_state.enable_hook_debug(["*"])
1147 yield self.assertFailure(unit_state.enable_hook_debug(["*"]),1149 error = yield self.assertFailure(unit_state.enable_hook_debug(["*"]),
1148 ServiceUnitDebugAlreadyEnabled)1150 ServiceUnitDebugAlreadyEnabled)
1151 self.assertEquals(
1152 str(error), "Service unit 'wordpress/0' is already in debug mode.")
11491153
1150 @inlineCallbacks1154 @inlineCallbacks
1151 def test_enable_debug_hook_lifetime(self):1155 def test_enable_debug_hook_lifetime(self):
11521156
=== modified file 'ensemble/tests/test_errors.py'
--- ensemble/tests/test_errors.py 2011-08-17 17:26:19 +0000
+++ ensemble/tests/test_errors.py 2011-08-26 13:09:07 +0000
@@ -23,20 +23,20 @@
2323
24 def test_FileNotFound(self):24 def test_FileNotFound(self):
25 error = FileNotFound("/path")25 error = FileNotFound("/path")
26 self.assertEquals(str(error), "File was not found: /path")26 self.assertEquals(str(error), "File was not found: '/path'")
27 self.assertIsEnsembleError(error)27 self.assertIsEnsembleError(error)
2828
29 def test_FileAlreadyExists(self):29 def test_FileAlreadyExists(self):
30 error = FileAlreadyExists("/path")30 error = FileAlreadyExists("/path")
31 self.assertEquals(str(error),31 self.assertEquals(str(error),
32 "File already exists, won't overwrite: /path")32 "File already exists, won't overwrite: '/path'")
33 self.assertIsEnsembleError(error)33 self.assertIsEnsembleError(error)
3434
35 def test_InvalidEnsembleHeaderValue(self):35 def test_InvalidEnsembleHeaderValue(self):
36 error = InvalidEnsembleHeaderValue("/path", "xpctd", "fnd")36 error = InvalidEnsembleHeaderValue("/path", "xpctd", "fnd")
37 self.assertEquals(str(error),37 self.assertEquals(str(error),
38 "Expected a YAML file with an 'ensemble: xpctd' "38 "Expected a YAML file with an 'ensemble: xpctd' "
39 "header, found 'ensemble: fnd': /path")39 "header, found 'ensemble: fnd': '/path'")
40 self.assertIsEnsembleError(error)40 self.assertIsEnsembleError(error)
4141
42 def test_NoConnection(self):42 def test_NoConnection(self):
@@ -62,12 +62,9 @@
62 self.assertIsEnsembleError(error)62 self.assertIsEnsembleError(error)
6363
64 def test_ProviderInteractionError(self):64 def test_ProviderInteractionError(self):
65 error = ProviderInteractionError(OSError("Bad Stuff"))65 error = ProviderInteractionError("Bad Stuff")
66 self.assertIsEnsembleError(error)66 self.assertIsEnsembleError(error)
67 self.assertEquals(67 self.assertEquals(str(error), "Bad Stuff")
68 str(error),
69 "ProviderError: Interaction with machine provider failed: "
70 "OSError('Bad Stuff',)")
7168
72 def test_CannotTerminateMachine(self):69 def test_CannotTerminateMachine(self):
73 error = CannotTerminateMachine(0, "environment would be destroyed")70 error = CannotTerminateMachine(0, "environment would be destroyed")
@@ -101,11 +98,4 @@
10198
102 def testEnvironmentPendingWithInfo(self):99 def testEnvironmentPendingWithInfo(self):
103 error = EnvironmentPending("problem")100 error = EnvironmentPending("problem")
104 self.assertEquals(str(error),101 self.assertEquals(str(error), "problem")
105 "Ensemble environment is not accessible: problem")
106
107 def testEnvironmentPendingNoInfo(self):
108 error = EnvironmentPending()
109 self.assertEquals(str(error),
110 "Ensemble environment is not accessible: no "
111 "details available")
112102
=== modified file 'ensemble/unit/tests/test_formula.py'
--- ensemble/unit/tests/test_formula.py 2011-08-18 21:33:55 +0000
+++ ensemble/unit/tests/test_formula.py 2011-08-26 13:09:07 +0000
@@ -191,4 +191,5 @@
191 self.client, "local:mickey-21", formula_directory),191 self.client, "local:mickey-21", formula_directory),
192 FormulaStateNotFound)192 FormulaStateNotFound)
193193
194 self.assertIn("Formula 'local:mickey-21' was not found", str(error))194 self.assertEquals(str(error),
195 "Formula 'local:mickey-21' was not found")

Subscribers

People subscribed via source and target branches

to all changes: