Merge lp:~sinzui/juju-ci-tools/bind-single-space into lp:juju-ci-tools

Proposed by Curtis Hovey
Status: Merged
Merged at revision: 1930
Proposed branch: lp:~sinzui/juju-ci-tools/bind-single-space
Merge into: lp:juju-ci-tools
Diff against target: 174 lines (+70/-3)
5 files modified
assess_endpoint_bindings.py (+15/-0)
jujupy/client.py (+3/-1)
jujupy/tests/test_client.py (+6/-0)
tests/test_assess_endpoint_bindings.py (+45/-1)
tests/test_deploy_stack.py (+1/-1)
To merge this branch: bzr merge lp:~sinzui/juju-ci-tools/bind-single-space
Reviewer Review Type Date Requested Status
Christopher Lee (community) Needs Fixing
Review via email: mp+319585@code.launchpad.net

Description of the change

Test global charm bindings.

Bug 1671489 shows that this command fails because the juju is confused by the instruction to bind a space to *all* bindings:
    juju deploy mycharm --bind aspace

Juju is wrongly insisting that the user name each binding the charm has. This branch extends the bindings test to deploy the datastore charm to a single space without specifying the exact charm bindings. The test reads the bundle, then sets up the spaces and machines in the maas. We must use the bundle to test this case.

I made secondary changes to help me test
1. The bundle is now saved to artifacts so that we can see what was deployed
2. I extends ModelClient and the fake bootstrap manager to allow me to pass --bind to deploy.
   I don't actually use --bind because of how the test is setup :(
   IN a future branch, I will explicitly test the command line.

To post a comment you must log in.
Revision history for this message
Curtis Hovey (sinzui) wrote :

PS I hacked
    http://juju-ci.vapour.ws/view/Juju%20Revisions/job/functional-endpoint-bindings-maas-2-1/
to use this branch. develop and 2.1 pass with the fix (and fail without the fix.) When this branch is merged, I will restore the job to use juju-ci-tools.

Revision history for this message
Christopher Lee (veebers) wrote :

In the future it would be safer to clone the job in question to test-run the updated test. That way there is no need to remember to update the actual job (and we limit the risk of tests running old branches).

A couple of comments inline.

review: Needs Fixing
1938. By Curtis Hovey

Remove vestigial comment and move bind arg to end of list.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'assess_endpoint_bindings.py'
2--- assess_endpoint_bindings.py 2017-03-08 23:33:39 +0000
3+++ assess_endpoint_bindings.py 2017-03-10 15:45:36 +0000
4@@ -7,6 +7,7 @@
5 import contextlib
6 import logging
7 import os
8+import shutil
9 import sys
10 import yaml
11
12@@ -226,6 +227,10 @@
13 "constraints": "spaces={},{}".format(space_data, space_public),
14 "series": "xenial",
15 },
16+ "2": {
17+ "constraints": "spaces={},{}".format(space_data, space_public),
18+ "series": "xenial",
19+ },
20 },
21 "services": {
22 "datastore": {
23@@ -247,6 +252,15 @@
24 "datastore": space_data,
25 },
26 },
27+ "monitor": {
28+ "charm": "./xenial/datastore",
29+ "series": "xenial",
30+ "num_units": 1,
31+ "to": ["2"],
32+ "bindings": {
33+ "": space_data,
34+ },
35+ },
36 },
37 "relations": [
38 ["datastore:datastore", "frontend:datastore"],
39@@ -281,6 +295,7 @@
40
41
42 def bootstrap_and_test(bootstrap_manager, bundle_path, machine):
43+ shutil.copy(bundle_path, bootstrap_manager.log_dir)
44 with bootstrap_manager.booted_context(False, no_gui=True):
45 client = bootstrap_manager.client
46 log.info("Deploying bundle.")
47
48=== modified file 'jujupy/client.py'
49--- jujupy/client.py 2017-03-02 20:03:35 +0000
50+++ jujupy/client.py 2017-03-10 15:45:36 +0000
51@@ -2022,7 +2022,7 @@
52
53 def deploy(self, charm, repository=None, to=None, series=None,
54 service=None, force=False, resource=None, num=None,
55- storage=None, constraints=None, alias=None):
56+ storage=None, constraints=None, alias=None, bind=None):
57 args = [charm]
58 if service is not None:
59 args.extend([service])
60@@ -2040,6 +2040,8 @@
61 args.extend(['--storage', storage])
62 if constraints is not None:
63 args.extend(['--constraints', constraints])
64+ if bind is not None:
65+ args.extend(['--bind', bind])
66 if alias is not None:
67 args.extend([alias])
68 return self.juju('deploy', tuple(args))
69
70=== modified file 'jujupy/tests/test_client.py'
71--- jujupy/tests/test_client.py 2017-03-02 16:50:50 +0000
72+++ jujupy/tests/test_client.py 2017-03-10 15:45:36 +0000
73@@ -1233,6 +1233,12 @@
74 mock_juju.assert_called_with(
75 'deploy', ('mondogb', '--constraints', 'virt-type=kvm'))
76
77+ def test_deploy_bind(self):
78+ env = ModelClient(JujuData('foo', {'type': 'local'}), None, None)
79+ with patch.object(env, 'juju') as mock_juju:
80+ env.deploy('mydb', bind='backspace')
81+ mock_juju.assert_called_with('deploy', ('mydb', '--bind', 'backspace'))
82+
83 def test_deploy_aliased(self):
84 env = ModelClient(JujuData('foo', {'type': 'local'}), None, None)
85 with patch.object(env, 'juju') as mock_juju:
86
87=== modified file 'tests/test_assess_endpoint_bindings.py'
88--- tests/test_assess_endpoint_bindings.py 2016-11-24 17:19:37 +0000
89+++ tests/test_assess_endpoint_bindings.py 2017-03-10 15:45:36 +0000
90@@ -1,19 +1,28 @@
91 """Tests for assess_endpoint_bindings module."""
92
93 import logging
94-from mock import Mock, patch
95+from mock import (
96+ Mock,
97+ patch,
98+ )
99+import os
100 import StringIO
101
102 from assess_endpoint_bindings import (
103+ bootstrap_and_test,
104+ create_test_charms,
105 ensure_spaces,
106 parse_args,
107 machine_spaces_for_bundle,
108 main,
109 )
110+from jujupy.client import JujuData
111 from tests import (
112 parse_error,
113 TestCase,
114 )
115+from test_deploy_stack import FakeBootstrapManager
116+from utility import temp_dir
117
118
119 class TestParseArgs(TestCase):
120@@ -152,6 +161,41 @@
121 self.assertEqual(machines, [app_spaces, db_spaces, db_spaces])
122
123
124+class AssessEndpointBindings(TestCase):
125+
126+ def test_create_test_charms(self):
127+ bundle, charms = create_test_charms()
128+ self.assertEqual(
129+ ['0', '1', '2'],
130+ sorted(bundle['machines'].keys()))
131+ self.assertEqual(
132+ ['datastore', 'frontend', 'monitor'],
133+ sorted(bundle['services'].keys()))
134+ self.assertEqual('datastore', charms[0].metadata['name'])
135+ self.assertEqual('frontend', charms[1].metadata['name'])
136+
137+ def test_bootstrap_and_test(self):
138+ juju_data = JujuData(
139+ 'foo', {'type': 'bar', 'region': 'region'}, juju_home='baz')
140+ client = Mock(
141+ spec=['bootstrap', 'kill_controller', 'deploy',
142+ 'wait_for_started', 'wait_for_workloads'],
143+ env=juju_data)
144+ bootstrap_manager = FakeBootstrapManager(client)
145+ with temp_dir() as bundle_dir:
146+ bundle_path = os.path.join(bundle_dir, 'bundle.yaml')
147+ with open(bundle_path, 'w') as bf:
148+ bf.write('bundle')
149+ with temp_dir() as log_dir:
150+ bootstrap_manager.log_dir = log_dir
151+ bootstrap_and_test(bootstrap_manager, bundle_path, None)
152+ archived_bundle = os.path.join(log_dir, 'bundle.yaml')
153+ self.assertIsTrue(os.path.exists(archived_bundle))
154+ client.deploy.assert_called_once_with(bundle_path)
155+ client.wait_for_started.assert_called_once_with()
156+ client.wait_for_workloads.assert_called_once_with()
157+
158+
159 class TestMain(TestCase):
160
161 def test_main(self):
162
163=== modified file 'tests/test_deploy_stack.py'
164--- tests/test_deploy_stack.py 2017-03-01 19:02:24 +0000
165+++ tests/test_deploy_stack.py 2017-03-10 15:45:36 +0000
166@@ -1052,7 +1052,7 @@
167 self.torn_down = True
168
169 @contextmanager
170- def booted_context(self, upload_tools):
171+ def booted_context(self, upload_tools, **kwargs):
172 with self.top_context() as machines:
173 with self.bootstrap_context(machines):
174 self.client.bootstrap(upload_tools)

Subscribers

People subscribed via source and target branches