Merge lp:~hazmat/pyjuju/deploy-invalid-conf into lp:pyjuju

Proposed by Kapil Thangavelu
Status: Merged
Approved by: Jim Baker
Approved revision: 448
Merged at revision: 455
Proposed branch: lp:~hazmat/pyjuju/deploy-invalid-conf
Merge into: lp:pyjuju
Diff against target: 82 lines (+28/-8)
2 files modified
juju/control/deploy.py (+9/-7)
juju/control/tests/test_deploy.py (+19/-1)
To merge this branch: bzr merge lp:~hazmat/pyjuju/deploy-invalid-conf
Reviewer Review Type Date Requested Status
Jim Baker (community) Approve
Review via email: mp+90321@code.launchpad.net

Description of the change

Validate config options before deploying.

It was previously possible to deploy a service with an invalid config, which
would result in a service with no units active in the environment. With the
change on invalid config with deploy, no service will be created in the
environment.

https://codereview.appspot.com/5572068/

To post a comment you must log in.
Revision history for this message
Kapil Thangavelu (hazmat) wrote :
Download full text (4.2 KiB)

Reviewers: mp+90321_code.launchpad.net,

Message:
Please take a look.

Description:
It was previously possible to deploy a service with an invalid config,
which
would result in a service with no units active in the environment. With
the
change on invalid config with deploy, no service will be created in the
environment.

https://code.launchpad.net/~hazmat/juju/deploy-invalid-conf/+merge/90321

(do not edit description out of merge proposal)

Please review this at https://codereview.appspot.com/5572068/

Affected files:
   M juju/control/deploy.py
   M juju/control/tests/test_deploy.py

Index: juju/control/deploy.py
=== <email address hidden> >
<email address hidden>
=== modified file 'juju/control/deploy.py'
--- juju/control/deploy.py 2011-12-07 02:26:56 +0000
+++ juju/control/deploy.py 2012-01-26 19:39:06 +0000
@@ -65,7 +65,7 @@
          num_units=options.num_units)

-def parse_config_options(config_file, service_name):
+def parse_config_options(config_file, service_name, charm):
      if not os.path.exists(config_file) or \
              not os.access(config_file, os.R_OK):
          raise ServiceConfigValueError(
@@ -77,8 +77,9 @@
          raise ServiceConfigValueError(
              "Invalid options file passed to --config.\n"
              "Expected a YAML dict with service name (%r)." % service_name)
- # remove the service name prefix for application to state
- return options[service_name]
+
+ # Validate and type service options and return
+ return charm.config.validate(options[service_name])

  @inlineCallbacks
@@ -93,14 +94,15 @@
      repo, charm_url = resolve(
          charm_name, repository_path, environment.default_series)

+ charm = yield repo.find(charm_url)
+ charm_id = str(charm_url.with_revision(charm.get_revision()))
+
      # Validate config options prior to deployment attempt
      service_options = {}
      service_name = service_name or charm_url.name
      if config_file:
- service_options = parse_config_options(config_file, service_name)
-
- charm = yield repo.find(charm_url)
- charm_id = str(charm_url.with_revision(charm.get_revision()))
+ service_options = parse_config_options(
+ config_file, service_name, charm)

      provider = environment.get_machine_provider()
      placement_policy = provider.get_placement_policy()

Index: juju/control/tests/test_deploy.py
=== <email address hidden> >
<email address hidden>
=== modified file 'juju/control/tests/test_deploy.py'
--- juju/control/tests/test_deploy.py 2011-11-29 20:49:04 +0000
+++ juju/control/tests/test_deploy.py 2012-01-26 19:39:06 +0000
@@ -8,7 +8,7 @@
  from juju.environment.config import EnvironmentsConfig
  from juju.charm.errors import ServiceConfigValueError
  from juju.state.environment import EnvironmentStateManager
-from juju.state.errors import ServiceStateNameInUse
+from juju.state.errors import ServiceStateNameInUse, ServiceStateNotFound
  from juju.state.service import ServiceStateManager
  from juju.state.relation import RelationSta...

Read more...

Revision history for this message
Benjamin Saller (bcsaller) wrote :
Download full text (4.6 KiB)

LGTM +1

On Thu, Jan 26, 2012 at 11:50 AM, Kapil Thangavelu
<email address hidden> wrote:
> Reviewers: mp+90321_code.launchpad.net,
>
> Message:
> Please take a look.
>
> Description:
> It was previously possible to deploy a service with an invalid config,
> which
> would result in a service with no units active in the environment. With
> the
> change on invalid config with deploy, no service will be created in the
> environment.
>
> https://code.launchpad.net/~hazmat/juju/deploy-invalid-conf/+merge/90321
>
> (do not edit description out of merge proposal)
>
>
> Please review this at https://codereview.appspot.com/5572068/
>
> Affected files:
>   M juju/control/deploy.py
>   M juju/control/tests/test_deploy.py
>
>
> Index: juju/control/deploy.py
> === <email address hidden> >
> <email address hidden>
> === modified file 'juju/control/deploy.py'
> --- juju/control/deploy.py      2011-12-07 02:26:56 +0000
> +++ juju/control/deploy.py      2012-01-26 19:39:06 +0000
> @@ -65,7 +65,7 @@
>          num_units=options.num_units)
>
>
> -def parse_config_options(config_file, service_name):
> +def parse_config_options(config_file, service_name, charm):
>      if not os.path.exists(config_file) or \
>              not os.access(config_file, os.R_OK):
>          raise ServiceConfigValueError(
> @@ -77,8 +77,9 @@
>          raise ServiceConfigValueError(
>              "Invalid options file passed to --config.\n"
>              "Expected a YAML dict with service name (%r)." % service_name)
> -    # remove the service name prefix for application to state
> -    return options[service_name]
> +
> +    # Validate and type service options and return
> +    return charm.config.validate(options[service_name])
>
>
>  @inlineCallbacks
> @@ -93,14 +94,15 @@
>      repo, charm_url = resolve(
>          charm_name, repository_path, environment.default_series)
>
> +    charm = yield repo.find(charm_url)
> +    charm_id = str(charm_url.with_revision(charm.get_revision()))
> +
>      # Validate config options prior to deployment attempt
>      service_options = {}
>      service_name = service_name or charm_url.name
>      if config_file:
> -        service_options = parse_config_options(config_file, service_name)
> -
> -    charm = yield repo.find(charm_url)
> -    charm_id = str(charm_url.with_revision(charm.get_revision()))
> +        service_options = parse_config_options(
> +            config_file, service_name, charm)
>
>      provider = environment.get_machine_provider()
>      placement_policy = provider.get_placement_policy()
>
>
> Index: juju/control/tests/test_deploy.py
> === <email address hidden> >
> <email address hidden>
> === modified file 'juju/control/tests/test_deploy.py'
> --- juju/control/tests/test_deploy.py   2011-11-29 20:49:04 +0000
> +++ juju/control/tests/test_deploy.py   2012-01-26 19:39:06 +0000
> @@ -8,7 +8,7 @@
>  from juju.environment.config import EnvironmentsConfig
>  from juju.charm.errors import ServiceConfigValueError
>  from juju.state.environment import Environmen...

Read more...

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

+1, looks good to me. Nearly a trivial.

Looks like Ben should have marked his comment approved too, so I'll will approve the branch too.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'juju/control/deploy.py'
2--- juju/control/deploy.py 2011-12-07 02:26:56 +0000
3+++ juju/control/deploy.py 2012-01-26 19:46:25 +0000
4@@ -65,7 +65,7 @@
5 num_units=options.num_units)
6
7
8-def parse_config_options(config_file, service_name):
9+def parse_config_options(config_file, service_name, charm):
10 if not os.path.exists(config_file) or \
11 not os.access(config_file, os.R_OK):
12 raise ServiceConfigValueError(
13@@ -77,8 +77,9 @@
14 raise ServiceConfigValueError(
15 "Invalid options file passed to --config.\n"
16 "Expected a YAML dict with service name (%r)." % service_name)
17- # remove the service name prefix for application to state
18- return options[service_name]
19+
20+ # Validate and type service options and return
21+ return charm.config.validate(options[service_name])
22
23
24 @inlineCallbacks
25@@ -93,14 +94,15 @@
26 repo, charm_url = resolve(
27 charm_name, repository_path, environment.default_series)
28
29+ charm = yield repo.find(charm_url)
30+ charm_id = str(charm_url.with_revision(charm.get_revision()))
31+
32 # Validate config options prior to deployment attempt
33 service_options = {}
34 service_name = service_name or charm_url.name
35 if config_file:
36- service_options = parse_config_options(config_file, service_name)
37-
38- charm = yield repo.find(charm_url)
39- charm_id = str(charm_url.with_revision(charm.get_revision()))
40+ service_options = parse_config_options(
41+ config_file, service_name, charm)
42
43 provider = environment.get_machine_provider()
44 placement_policy = provider.get_placement_policy()
45
46=== modified file 'juju/control/tests/test_deploy.py'
47--- juju/control/tests/test_deploy.py 2011-11-29 20:49:04 +0000
48+++ juju/control/tests/test_deploy.py 2012-01-26 19:46:25 +0000
49@@ -8,7 +8,7 @@
50 from juju.environment.config import EnvironmentsConfig
51 from juju.charm.errors import ServiceConfigValueError
52 from juju.state.environment import EnvironmentStateManager
53-from juju.state.errors import ServiceStateNameInUse
54+from juju.state.errors import ServiceStateNameInUse, ServiceStateNotFound
55 from juju.state.service import ServiceStateManager
56 from juju.state.relation import RelationStateManager
57
58@@ -290,6 +290,24 @@
59 "Expected a YAML dict with service name ('myblog').", str(error))
60
61 @inlineCallbacks
62+ def test_deploy_with_invalid_config(self):
63+ """Can't deploy with config that doesn't pass charm validation."""
64+ config_file = self.makeFile(
65+ yaml.dump(dict(myblog=dict(application_file="foo"))))
66+ environment = self.config.get("firstenv")
67+
68+ failure = deploy.deploy(
69+ self.config, environment, self.unbundled_repo_path, "local:sample",
70+ "myblog", logging.getLogger("deploy"), config_file)
71+ error = yield self.assertFailure(failure, ServiceConfigValueError)
72+ self.assertIn(
73+ "application_file is not a valid configuration option",
74+ str(error))
75+ yield self.assertFailure(
76+ ServiceStateManager(self.client).get_service_state("myblog"),
77+ ServiceStateNotFound)
78+
79+ @inlineCallbacks
80 def test_deploy_with_config(self):
81 """Valid config options should be available to the deployed
82 service."""

Subscribers

People subscribed via source and target branches

to status/vote changes: