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
=== modified file 'deployer/action/importer.py'
--- deployer/action/importer.py 2016-11-03 13:00:27 +0000
+++ deployer/action/importer.py 2016-12-23 18:56:57 +0000
@@ -201,6 +201,7 @@
201 charm.repo_path or self.deployment.repo_path,201 charm.repo_path or self.deployment.repo_path,
202 svc.config,202 svc.config,
203 svc.constraints,203 svc.constraints,
204 svc.storage,
204 num_units,205 num_units,
205 placement.get(0),206 placement.get(0),
206 charm.series or self.deployment.series,207 charm.series or self.deployment.series,
207208
=== modified file 'deployer/env/base.py'
--- deployer/env/base.py 2016-07-12 23:43:08 +0000
+++ deployer/env/base.py 2016-12-23 18:56:57 +0000
@@ -4,6 +4,7 @@
4from ..utils import (4from ..utils import (
5 AlternateKeyDict,5 AlternateKeyDict,
6 ErrorExit,6 ErrorExit,
7 DeploymentError,
7 yaml_load,8 yaml_load,
8 yaml_dump,9 yaml_dump,
9 temp_file,10 temp_file,
@@ -68,7 +69,7 @@
68 self.log.info(" Bootstrap complete")69 self.log.info(" Bootstrap complete")
6970
70 def deploy(self, name, charm_url, repo=None, config=None,71 def deploy(self, name, charm_url, repo=None, config=None,
71 constraints=None, num_units=1, force_machine=None,72 constraints=None, storage=None, num_units=1, force_machine=None,
72 series=None):73 series=None):
73 params = self._named_env(["juju", "deploy"])74 params = self._named_env(["juju", "deploy"])
74 with temp_file() as fh:75 with temp_file() as fh:
@@ -84,6 +85,12 @@
84 '{}={}'.format(k, v) for k, v in constraints.items()85 '{}={}'.format(k, v) for k, v in constraints.items()
85 ])86 ])
86 params.extend(['--constraints', constraints])87 params.extend(['--constraints', constraints])
88 if storage:
89 if not isinstance(storage, dict):
90 raise DeploymentError("storage must be specified as a dictionary")
91 params.append("--storage")
92 for key, value in storage.items():
93 params.append("{}={}".format(key, value))
87 if num_units not in (1, None):94 if num_units not in (1, None):
88 params.extend(["--num-units", str(num_units)])95 params.extend(["--num-units", str(num_units)])
89 if charm_url.startswith('local'):96 if charm_url.startswith('local'):
9097
=== modified file 'deployer/service.py'
--- deployer/service.py 2016-11-08 19:05:04 +0000
+++ deployer/service.py 2016-12-23 18:56:57 +0000
@@ -55,6 +55,10 @@
55 return int(self.svc_data.get('num_units', 1))55 return int(self.svc_data.get('num_units', 1))
5656
57 @property57 @property
58 def storage(self):
59 return self.svc_data.get('storage', None)
60
61 @property
58 def unit_placement(self):62 def unit_placement(self):
59 # Separate checks to support machine 0 placement.63 # Separate checks to support machine 0 placement.
60 value = self.svc_data.get('to')64 value = self.svc_data.get('to')
6165
=== modified file 'deployer/tests/test_charm.py'
--- deployer/tests/test_charm.py 2016-11-04 00:22:12 +0000
+++ deployer/tests/test_charm.py 2016-12-23 18:56:57 +0000
@@ -137,7 +137,7 @@
137 "scratch", self.repo_path, "precise", params)137 "scratch", self.repo_path, "precise", params)
138138
139 charm.fetch()139 charm.fetch()
140 self.assertEqual(charm.metadata['name'], 'couchdb')140 self.assertEqual(charm.metadata['name'], 'couchdb')
141 self.assertEqual(charm.vcs.get_cur_rev(), '3')141 self.assertEqual(charm.vcs.get_cur_rev(), '3')
142142
143 charm.rev = '2'143 charm.rev = '2'
@@ -286,7 +286,7 @@
286 charm = Charm.from_service(286 charm = Charm.from_service(
287 "scratch", self.repo_path, "precise", params)287 "scratch", self.repo_path, "precise", params)
288 charm.fetch()288 charm.fetch()
289 self.assertEqual(charm.metadata['name'], 'couchdb')289 self.assertEqual(charm.metadata['name'], 'couchdb')
290 HEAD = charm.vcs.get_cur_rev()290 HEAD = charm.vcs.get_cur_rev()
291291
292 self.assertFalse(charm.is_modified())292 self.assertFalse(charm.is_modified())
293293
=== added file 'deployer/tests/test_data/wiki-storage.yaml'
--- deployer/tests/test_data/wiki-storage.yaml 1970-01-01 00:00:00 +0000
+++ deployer/tests/test_data/wiki-storage.yaml 2016-12-23 18:56:57 +0000
@@ -0,0 +1,13 @@
1wiki:
2 series: precise
3 services:
4 wiki:
5 charm: cs:precise/mediawiki
6 options:
7 name: $hi_world _are_you_there? {guess_who}
8 storage:
9 web-data: "cinder,10G,1"
10 db:
11 charm: cs:precise/mysql
12 relations:
13 - [wiki, db]
0\ No newline at end of file14\ No newline at end of file
115
=== modified file 'deployer/tests/test_goenv.py'
--- deployer/tests/test_goenv.py 2016-07-12 02:29:52 +0000
+++ deployer/tests/test_goenv.py 2016-12-23 18:56:57 +0000
@@ -59,6 +59,7 @@
59 self.env.deploy("test-blog", "cs:precise/wordpress")59 self.env.deploy("test-blog", "cs:precise/wordpress")
60 self.env.deploy("test-db", "cs:precise/mysql")60 self.env.deploy("test-db", "cs:precise/mysql")
61 self.env.add_relation("test-db", "test-blog")61 self.env.add_relation("test-db", "test-blog")
62 self.env.deploy("test-db2", "cs:postgresql", storage={"pgdata": "rootfs,10M"}, series="xenial")
62 self.env.add_units('test-blog', 1)63 self.env.add_units('test-blog', 1)
6364
64 # Sleep because juju core watches are eventually consistent (5s window)65 # Sleep because juju core watches are eventually consistent (5s window)
@@ -67,7 +68,7 @@
67 self.env.wait_for_units(timeout=800)68 self.env.wait_for_units(timeout=800)
68 status = self.env.status()69 status = self.env.status()
6970
70 services = ["test-blog", "test-db"]71 services = ["test-blog", "test-db", "test-db2"]
71 self.assertEqual(72 self.assertEqual(
72 sorted(status['services'].keys()),73 sorted(status['services'].keys()),
73 services)74 services)
7475
=== modified file 'deployer/tests/test_guiserver.py'
--- deployer/tests/test_guiserver.py 2016-10-27 18:41:34 +0000
+++ deployer/tests/test_guiserver.py 2016-12-23 18:56:57 +0000
@@ -283,14 +283,14 @@
283 mock.call.status(),283 mock.call.status(),
284 mock.call.deploy(284 mock.call.deploy(
285 'mysql', 'cs:precise/mysql-28', '', None,285 'mysql', 'cs:precise/mysql-28', '', None,
286 {'arch': 'i386', 'cpu-cores': 4, 'mem': '4G'}, 2, None,286 {'arch': 'i386', 'cpu-cores': 4, 'mem': '4G'}, None, 2, None,
287 'precise'),287 'precise'),
288 mock.call.set_annotation(288 mock.call.set_annotation(
289 'mysql', {'gui-y': '164.547', 'gui-x': '494.347'}),289 'mysql', {'gui-y': '164.547', 'gui-x': '494.347'}),
290 mock.call.deploy(290 mock.call.deploy(
291 'wordpress', 'cs:precise/wordpress-20', '',291 'wordpress', 'cs:precise/wordpress-20', '',
292 {'debug': 'no', 'engine': 'nginx', 'tuning': 'single'},292 {'debug': 'no', 'engine': 'nginx', 'tuning': 'single'},
293 None, 1, None, 'precise'),293 None, None, 1, None, 'precise'),
294 mock.call.set_annotation(294 mock.call.set_annotation(
295 'wordpress', {'gui-y': '414.547', 'gui-x': '425.347'}),295 'wordpress', {'gui-y': '414.547', 'gui-x': '425.347'}),
296 mock.call.add_units('mysql', 2),296 mock.call.add_units('mysql', 2),
297297
=== modified file 'deployer/tests/test_importer.py'
--- deployer/tests/test_importer.py 2016-10-27 18:41:34 +0000
+++ deployer/tests/test_importer.py 2016-12-23 18:56:57 +0000
@@ -63,7 +63,25 @@
63 env.method_calls[3], mock.call.deploy(63 env.method_calls[3], mock.call.deploy(
64 'wiki', 'cs:precise/mediawiki',64 'wiki', 'cs:precise/mediawiki',
65 os.environ.get("JUJU_REPOSITORY", ""),65 os.environ.get("JUJU_REPOSITORY", ""),
66 config, None, 1, None, 'precise'))66 config, None, None, 1, None, 'precise'))
67 env.add_relation.assert_called_once_with('wiki', 'db')
68
69 @skip_if_offline
70 @mock.patch('deployer.action.importer.time')
71 def test_importer_with_storage(self, mock_time):
72 mock_time.time.return_value = 0
73 stack = ConfigStack([os.path.join(self.test_data_dir, 'wiki-storage.yaml')])
74 deploy = stack.get('wiki')
75 env = mock.MagicMock()
76 importer = Importer(env, deploy, self.options)
77 importer.run()
78
79 config = {'name': '$hi_world _are_you_there? {guess_who}'}
80 self.assertEqual(
81 env.method_calls[3], mock.call.deploy(
82 'wiki', 'cs:precise/mediawiki',
83 os.environ.get("JUJU_REPOSITORY", ""),
84 config, None, {"web-data": "cinder,10G,1"}, 1, None, 'precise'))
67 env.add_relation.assert_called_once_with('wiki', 'db')85 env.add_relation.assert_called_once_with('wiki', 'db')
6886
69 @skip_if_offline87 @skip_if_offline
7088
=== modified file 'deployer/tests/test_service.py'
--- deployer/tests/test_service.py 2016-05-07 23:02:56 +0000
+++ deployer/tests/test_service.py 2016-12-23 18:56:57 +0000
@@ -14,15 +14,18 @@
14 self.assertEqual(s.num_units, 1)14 self.assertEqual(s.num_units, 1)
15 self.assertEqual(s.constraints, None)15 self.assertEqual(s.constraints, None)
16 self.assertEqual(s.config, None)16 self.assertEqual(s.config, None)
17 self.assertEqual(s.storage, None)
1718
18 data = {19 data = {
19 'branch': 'lp:precise/mysql',20 'branch': 'lp:precise/mysql',
20 'constraints': "instance-type=m1.small",21 'constraints': "instance-type=m1.small",
21 'options': {"services": "include-file://stack-include.yaml"},22 'options': {"services": "include-file://stack-include.yaml"},
22 'num_units': 10}23 'num_units': 10,
24 'storage': {"data": "ebs,10G,1"}}
23 s = Service('db', data)25 s = Service('db', data)
24 self.assertEquals(s.num_units, 10)26 self.assertEquals(s.num_units, 10)
25 self.assertEquals(s.constraints, "instance-type=m1.small")27 self.assertEquals(s.constraints, "instance-type=m1.small")
26 self.assertEquals(28 self.assertEquals(
27 s.config,29 s.config,
28 {"services": "include-file://stack-include.yaml"})30 {"services": "include-file://stack-include.yaml"})
31 self.assertEquals(s.storage, {"data": "ebs,10G,1"})
2932
=== modified file 'doc/config.rst'
--- doc/config.rst 2015-01-22 15:22:18 +0000
+++ doc/config.rst 2016-12-23 18:56:57 +0000
@@ -36,6 +36,8 @@
36 tuning: optimized36 tuning: optimized
37 engine: apache37 engine: apache
38 icon: include-base64://file.ico38 icon: include-base64://file.ico
39 storage:
40 data-block: "ebs,1024G,3"
39 41
4042
41The service's charm name will be infered from the vcs branch name if43The service's charm name will be infered from the vcs branch name if
@@ -52,6 +54,15 @@
52include-base64://path-to-file. Relative paths are resolved54include-base64://path-to-file. Relative paths are resolved
53relative to the config file.55relative to the config file.
5456
57Service storage is specified as a dictionary with keys as the label
58and the value being the pool,size,count string that should be passed
59to Juju. This matches the Juju cli syntax,
60`juju deploy <charm> --storage <label>=<pool>,<size>,<count>`. Also
61like the cli, size and count are optional parameters. NOTE: storage
62status is not displayed in the diff command as isn't in the the Juju
63status data. For this same reason storage is only specified for new
64services and is not added to already existing services.
65
55Relations66Relations
56=========67=========
5768

Subscribers

People subscribed via source and target branches