Merge lp:~timkuhlman/juju-deployer/storage-support into lp:juju-deployer

Proposed by Tim Kuhlman
Status: Merged
Merged at revision: 207
Proposed branch: lp:~timkuhlman/juju-deployer/storage-support
Merge into: lp:juju-deployer
Diff against target: 226 lines (+66/-8)
10 files modified
deployer/action/importer.py (+1/-0)
deployer/env/base.py (+8/-1)
deployer/service.py (+4/-0)
deployer/tests/test_charm.py (+2/-2)
deployer/tests/test_data/wiki-storage.yaml (+13/-0)
deployer/tests/test_goenv.py (+2/-1)
deployer/tests/test_guiserver.py (+2/-2)
deployer/tests/test_importer.py (+19/-1)
deployer/tests/test_service.py (+4/-1)
doc/config.rst (+11/-0)
To merge this branch: bzr merge lp:~timkuhlman/juju-deployer/storage-support
Reviewer Review Type Date Requested Status
Tim Van Steenburgh (community) Approve
Review via email: mp+313849@code.launchpad.net

Description of the change

This adds support for Juju storage on initial application setup.

The addition to the integration test of the postgresql charm with storage support requires that this fix to the postgresql charm, https://code.launchpad.net/~timkuhlman/postgresql-charm/+git/storage-fix/+merge/313845

To post a comment you must log in.
Revision history for this message
Tim Van Steenburgh (tvansteenburgh) wrote :

LGTM. Will proceed with merge since integration tests won't block the build.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'deployer/action/importer.py'
2--- deployer/action/importer.py 2016-11-03 13:00:27 +0000
3+++ deployer/action/importer.py 2016-12-23 18:56:57 +0000
4@@ -201,6 +201,7 @@
5 charm.repo_path or self.deployment.repo_path,
6 svc.config,
7 svc.constraints,
8+ svc.storage,
9 num_units,
10 placement.get(0),
11 charm.series or self.deployment.series,
12
13=== modified file 'deployer/env/base.py'
14--- deployer/env/base.py 2016-07-12 23:43:08 +0000
15+++ deployer/env/base.py 2016-12-23 18:56:57 +0000
16@@ -4,6 +4,7 @@
17 from ..utils import (
18 AlternateKeyDict,
19 ErrorExit,
20+ DeploymentError,
21 yaml_load,
22 yaml_dump,
23 temp_file,
24@@ -68,7 +69,7 @@
25 self.log.info(" Bootstrap complete")
26
27 def deploy(self, name, charm_url, repo=None, config=None,
28- constraints=None, num_units=1, force_machine=None,
29+ constraints=None, storage=None, num_units=1, force_machine=None,
30 series=None):
31 params = self._named_env(["juju", "deploy"])
32 with temp_file() as fh:
33@@ -84,6 +85,12 @@
34 '{}={}'.format(k, v) for k, v in constraints.items()
35 ])
36 params.extend(['--constraints', constraints])
37+ if storage:
38+ if not isinstance(storage, dict):
39+ raise DeploymentError("storage must be specified as a dictionary")
40+ params.append("--storage")
41+ for key, value in storage.items():
42+ params.append("{}={}".format(key, value))
43 if num_units not in (1, None):
44 params.extend(["--num-units", str(num_units)])
45 if charm_url.startswith('local'):
46
47=== modified file 'deployer/service.py'
48--- deployer/service.py 2016-11-08 19:05:04 +0000
49+++ deployer/service.py 2016-12-23 18:56:57 +0000
50@@ -55,6 +55,10 @@
51 return int(self.svc_data.get('num_units', 1))
52
53 @property
54+ def storage(self):
55+ return self.svc_data.get('storage', None)
56+
57+ @property
58 def unit_placement(self):
59 # Separate checks to support machine 0 placement.
60 value = self.svc_data.get('to')
61
62=== modified file 'deployer/tests/test_charm.py'
63--- deployer/tests/test_charm.py 2016-11-04 00:22:12 +0000
64+++ deployer/tests/test_charm.py 2016-12-23 18:56:57 +0000
65@@ -137,7 +137,7 @@
66 "scratch", self.repo_path, "precise", params)
67
68 charm.fetch()
69- self.assertEqual(charm.metadata['name'], 'couchdb')
70+ self.assertEqual(charm.metadata['name'], 'couchdb')
71 self.assertEqual(charm.vcs.get_cur_rev(), '3')
72
73 charm.rev = '2'
74@@ -286,7 +286,7 @@
75 charm = Charm.from_service(
76 "scratch", self.repo_path, "precise", params)
77 charm.fetch()
78- self.assertEqual(charm.metadata['name'], 'couchdb')
79+ self.assertEqual(charm.metadata['name'], 'couchdb')
80 HEAD = charm.vcs.get_cur_rev()
81
82 self.assertFalse(charm.is_modified())
83
84=== added file 'deployer/tests/test_data/wiki-storage.yaml'
85--- deployer/tests/test_data/wiki-storage.yaml 1970-01-01 00:00:00 +0000
86+++ deployer/tests/test_data/wiki-storage.yaml 2016-12-23 18:56:57 +0000
87@@ -0,0 +1,13 @@
88+wiki:
89+ series: precise
90+ services:
91+ wiki:
92+ charm: cs:precise/mediawiki
93+ options:
94+ name: $hi_world _are_you_there? {guess_who}
95+ storage:
96+ web-data: "cinder,10G,1"
97+ db:
98+ charm: cs:precise/mysql
99+ relations:
100+ - [wiki, db]
101\ No newline at end of file
102
103=== modified file 'deployer/tests/test_goenv.py'
104--- deployer/tests/test_goenv.py 2016-07-12 02:29:52 +0000
105+++ deployer/tests/test_goenv.py 2016-12-23 18:56:57 +0000
106@@ -59,6 +59,7 @@
107 self.env.deploy("test-blog", "cs:precise/wordpress")
108 self.env.deploy("test-db", "cs:precise/mysql")
109 self.env.add_relation("test-db", "test-blog")
110+ self.env.deploy("test-db2", "cs:postgresql", storage={"pgdata": "rootfs,10M"}, series="xenial")
111 self.env.add_units('test-blog', 1)
112
113 # Sleep because juju core watches are eventually consistent (5s window)
114@@ -67,7 +68,7 @@
115 self.env.wait_for_units(timeout=800)
116 status = self.env.status()
117
118- services = ["test-blog", "test-db"]
119+ services = ["test-blog", "test-db", "test-db2"]
120 self.assertEqual(
121 sorted(status['services'].keys()),
122 services)
123
124=== modified file 'deployer/tests/test_guiserver.py'
125--- deployer/tests/test_guiserver.py 2016-10-27 18:41:34 +0000
126+++ deployer/tests/test_guiserver.py 2016-12-23 18:56:57 +0000
127@@ -283,14 +283,14 @@
128 mock.call.status(),
129 mock.call.deploy(
130 'mysql', 'cs:precise/mysql-28', '', None,
131- {'arch': 'i386', 'cpu-cores': 4, 'mem': '4G'}, 2, None,
132+ {'arch': 'i386', 'cpu-cores': 4, 'mem': '4G'}, None, 2, None,
133 'precise'),
134 mock.call.set_annotation(
135 'mysql', {'gui-y': '164.547', 'gui-x': '494.347'}),
136 mock.call.deploy(
137 'wordpress', 'cs:precise/wordpress-20', '',
138 {'debug': 'no', 'engine': 'nginx', 'tuning': 'single'},
139- None, 1, None, 'precise'),
140+ None, None, 1, None, 'precise'),
141 mock.call.set_annotation(
142 'wordpress', {'gui-y': '414.547', 'gui-x': '425.347'}),
143 mock.call.add_units('mysql', 2),
144
145=== modified file 'deployer/tests/test_importer.py'
146--- deployer/tests/test_importer.py 2016-10-27 18:41:34 +0000
147+++ deployer/tests/test_importer.py 2016-12-23 18:56:57 +0000
148@@ -63,7 +63,25 @@
149 env.method_calls[3], mock.call.deploy(
150 'wiki', 'cs:precise/mediawiki',
151 os.environ.get("JUJU_REPOSITORY", ""),
152- config, None, 1, None, 'precise'))
153+ config, None, None, 1, None, 'precise'))
154+ env.add_relation.assert_called_once_with('wiki', 'db')
155+
156+ @skip_if_offline
157+ @mock.patch('deployer.action.importer.time')
158+ def test_importer_with_storage(self, mock_time):
159+ mock_time.time.return_value = 0
160+ stack = ConfigStack([os.path.join(self.test_data_dir, 'wiki-storage.yaml')])
161+ deploy = stack.get('wiki')
162+ env = mock.MagicMock()
163+ importer = Importer(env, deploy, self.options)
164+ importer.run()
165+
166+ config = {'name': '$hi_world _are_you_there? {guess_who}'}
167+ self.assertEqual(
168+ env.method_calls[3], mock.call.deploy(
169+ 'wiki', 'cs:precise/mediawiki',
170+ os.environ.get("JUJU_REPOSITORY", ""),
171+ config, None, {"web-data": "cinder,10G,1"}, 1, None, 'precise'))
172 env.add_relation.assert_called_once_with('wiki', 'db')
173
174 @skip_if_offline
175
176=== modified file 'deployer/tests/test_service.py'
177--- deployer/tests/test_service.py 2016-05-07 23:02:56 +0000
178+++ deployer/tests/test_service.py 2016-12-23 18:56:57 +0000
179@@ -14,15 +14,18 @@
180 self.assertEqual(s.num_units, 1)
181 self.assertEqual(s.constraints, None)
182 self.assertEqual(s.config, None)
183+ self.assertEqual(s.storage, None)
184
185 data = {
186 'branch': 'lp:precise/mysql',
187 'constraints': "instance-type=m1.small",
188 'options': {"services": "include-file://stack-include.yaml"},
189- 'num_units': 10}
190+ 'num_units': 10,
191+ 'storage': {"data": "ebs,10G,1"}}
192 s = Service('db', data)
193 self.assertEquals(s.num_units, 10)
194 self.assertEquals(s.constraints, "instance-type=m1.small")
195 self.assertEquals(
196 s.config,
197 {"services": "include-file://stack-include.yaml"})
198+ self.assertEquals(s.storage, {"data": "ebs,10G,1"})
199
200=== modified file 'doc/config.rst'
201--- doc/config.rst 2015-01-22 15:22:18 +0000
202+++ doc/config.rst 2016-12-23 18:56:57 +0000
203@@ -36,6 +36,8 @@
204 tuning: optimized
205 engine: apache
206 icon: include-base64://file.ico
207+ storage:
208+ data-block: "ebs,1024G,3"
209
210
211 The service's charm name will be infered from the vcs branch name if
212@@ -52,6 +54,15 @@
213 include-base64://path-to-file. Relative paths are resolved
214 relative to the config file.
215
216+Service storage is specified as a dictionary with keys as the label
217+and the value being the pool,size,count string that should be passed
218+to Juju. This matches the Juju cli syntax,
219+`juju deploy <charm> --storage <label>=<pool>,<size>,<count>`. Also
220+like the cli, size and count are optional parameters. NOTE: storage
221+status is not displayed in the diff command as isn't in the the Juju
222+status data. For this same reason storage is only specified for new
223+services and is not added to already existing services.
224+
225 Relations
226 =========
227

Subscribers

People subscribed via source and target branches