Merge lp:~jimbaker/pyjuju/env-origin into lp:pyjuju

Proposed by Jim Baker
Status: Merged
Approved by: Gustavo Niemeyer
Approved revision: 380
Merged at revision: 382
Proposed branch: lp:~jimbaker/pyjuju/env-origin
Merge into: lp:pyjuju
Diff against target: 608 lines (+337/-27)
19 files modified
docs/source/provider-configuration-ec2.rst (+9/-3)
juju/providers/common/cloudinit.py (+78/-2)
juju/providers/common/launch.py (+9/-2)
juju/providers/common/tests/data/cloud_init_bootstrap (+0/-2)
juju/providers/common/tests/data/cloud_init_bootstrap_zookeepers (+0/-2)
juju/providers/common/tests/data/cloud_init_branch_trunk (+17/-0)
juju/providers/common/tests/data/cloud_init_normal (+0/-2)
juju/providers/common/tests/data/cloud_init_ppa (+15/-0)
juju/providers/common/tests/test_cloudinit.py (+109/-3)
juju/providers/ec2/tests/common.py (+1/-0)
juju/providers/ec2/tests/data/bootstrap_cloud_init (+0/-2)
juju/providers/ec2/tests/data/launch_cloud_init (+0/-2)
juju/providers/ec2/tests/data/launch_cloud_init_branch (+20/-0)
juju/providers/ec2/tests/data/launch_cloud_init_ppa (+15/-0)
juju/providers/ec2/tests/test_bootstrap.py (+1/-0)
juju/providers/ec2/tests/test_launch.py (+60/-2)
juju/providers/orchestra/tests/common.py (+3/-1)
juju/providers/orchestra/tests/data/bootstrap_user_data (+0/-2)
juju/providers/orchestra/tests/data/launch_user_data (+0/-2)
To merge this branch: bzr merge lp:~jimbaker/pyjuju/env-origin
Reviewer Review Type Date Requested Status
Gustavo Niemeyer Approve
William Reade (community) Approve
Review via email: mp+75823@code.launchpad.net

Description of the change

Implements optional environment settings juju-origin (which replaces juju-branch).

Does not implement juju-version or support for deb repositories, per attached bug.

Functionally tested for not setting juju-origin, setting it to the standard PPA (the only one supported now), and LP branches.

To post a comment you must log in.
Revision history for this message
Gustavo Niemeyer (niemeyer) wrote :

[1]

The documentation must be changed accordingly.

[2]

Please drop the version support. Without pinning, this doesn't guarantee that
the version will stay as suggested, and we shouldn't be looking into pinning
right now.

[3]

238 + # XXX needed for python-txzookeeper dependency
239 return ["ppa:juju/pkgs"]

That's a *major* one. Why? Please synchronize with SpamapS and ensure that's not
needed anymore.

[4]

213 + # Classify origins so the proper install script is later selected
214 + if origin is None:
215 + self._origin_type = _DISTRO
216 + elif (origin.startswith("deb ") or \
217 + origin.startswith("ppa:") or \
218 + origin.startswith("http:") or \
219 + origin.startswith("https:")):
220 + self._origin_type = _DEBIAN
221 + elif origin.startswith("lp:"):
222 + self._origin_type = _BRANCH

Why is this changing? The original version of this logic was significantly
simpler and cleaner, and seems to support all the cases we're trying to
support right now.

[5]

I'm _very_ concerned about your summary. The support for other package sources
besides branches is precisely what this branch is introducing, and you seem to
claim this wasn't tested at all.

Please do make sure this stuff is tested.

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

[0]

+ :type branch: str or None

two of these, should be "origin" and "version" instead of "branch"

[1]

+ version=str(config.get("juju-version")))

Won't that lead to version being "None" rather than None? If so, maybe add a test for that path.

Otherwise looks very nice, +1.

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

[6]

+ PPA (use a `ppa:` prefix, eg `ppa:juju/pkgs`). Otherwise, the
+ utilized source will be based on the machine running the
+ bootstrap command (distribution, PPA, or branch).

s/eg/e.g./

In the following sentence, please use this wording:

  Otherwise, juju will attempt to detect the correct origin based on
  its run location and the installed juju package.

Also this should be fixed according to the rest of this review.

[7]

+ def _parse_policy(self, output):
(...)
+ def get_default_origin(self):
(...)

Neither of these methods seem to need any information from "self",
which means they are actually independent functions rather than
methods.

[8]

+ if k != "juju":
+ # Sanity check: no record at all, the only possibility is that
+ # this being run as a branch
+ return "lp:juju"
+ for k, v in parse:
+ if k == "Installed" and v == "(none)":
+ return _PPA
+ if k == "Version table":
+ break
+ for _, version_info in parse:
+ if "ppa.launchpad.net" in version_info:
+ return _PPA

As we talked yesterday online, all of this logic is idempotent, and should
be part of a single function, called parse_juju_origin(data) or similar,
and not part of the same function that interacts with the system (calling
"apt-cache policy juju").

[9]

+cat <<EOF
+juju:
+ Installed: (none)
+ Candidate: good-magic-1.0
+ Version table:
+ *** good-magic-1.0
+ 500 http://us.archive.ubuntu.com/ubuntu/ natty/main amd64 Packages
+ 100 /var/lib/dpkg/status
+EOF

This is testing the idempotent parse_juju_origin(data) function. Put the
data inside the test file, and test the function trivially:

    def test_foo(self):
        origin, source = parse_juju_policy(data)
 self.assertEquals(origin, "whatever")
 self.assertEquals(source, "whatever else")

It's really that simple! :-)

Kill most of these apt-cache dummies, please. You only need one test
of these, to ensure that the system interaction is really working as
it should. All the variations should be tested in the above fashion.

[10]

+ elif origin.startswith("ppa:"):
+ cloud_init.set_juju_source(ppa=True)

This is bogus. This should be `if origin == "ppa":`, otherwise you're
promising something and delivering something else. Please fix the
branch and documentation.

[11]

+class OriginPolicyTestMixin(object):
+
+ def setup_origin_policy(self, name, is_branch=False):
(...)
+class EC2MachineLaunchTest(EC2TestMixin, EC2MachineLaunchMixin,
+ OriginPolicyTestMixin, TestCase):

Ouch!

Please drop the mixin.. this is a single simple function,
so let's handle it as such.

[12]

--- juju/providers/ec2/tests/data/launch_cloud_init_branch 1970-01-01 00:00:00 +0000

The number of these files and the way we copy them blindly on every
minor detail we want to test is pretty sad. That's fine for this
branch, but it'd be awesome to figure a better way to test this in
the future.

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

[13]

+ juju-origin:
+ The origin of juju deployed to machines within an environment
+ is set by this option. This option can be set to a bzr branch
+ pushed to Launchpad (use a `lp:` prefix, e.g., `lp:juju`); to
+ the PPA by using `ppa`; or to the juju distribution by using
+ `distro`. If this option cannot be parsed, the distribution is
+ used.

This sentence is not reading correctly in a few ways (e.g. the
juju _origin_ is not really deployed, and there's no such thing
as a juju distribution.. it's the Ubuntu distribution).

Please use this:

    juju-origin:
        Defines where juju should be obtained for installing in
 machines. Can be set to a "lp..." branch url, to "ppa" for
 getting packages from the official juju PPA, or to "distro"
 for using packages from the official Ubuntu repositories.

[14]

Jim, please read this excerpt from our conversation again, *carefully*:

<niemeyer> 1) Grab the installed version from the "Installed:" line
<niemeyer> 2) If this is "(none)" return "branch"
<niemeyer> 3) Otherwise, store the version in a variable, and keep parsing
<niemeyer> 4) Find the version table, and find the installed version
<niemeyer> 5) For each line in the given version, if it contains "ppa.launchpad.net/juju/pkgs", return "ppa"
<niemeyer> 6) If you reach the end of the installed version, return "distro"

Compare to what is in the branch right now.

[15]

+ if k == "Installed" and v == "(none)":
+ return "ppa", None

Compare with the summary above.

If there's no juju package installed in the system, it means the
user is not using the ppa.

[16]

+ for _, version_info in parse:
+ if "ppa.launchpad.net" in version_info:
+ return "ppa", None

Compare with the summary above.

Which version is this? The existence of _any_ version that comes from
a PPA in the apt cache is not an indication that the _installed_
version comes from a PPA. The indication that it comes from _a_ ppa
is not an indication that it comes from _our_ ppa either.

[17]

+ def test_distro_not_installed(self):
+ data = (
+ "juju:\n"
+ " Installed: (none)\n"
+ " Candidate: good-magic-1.0\n"

Much better, thank you.

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

I do not see my reply that I emailed to the lp gateway last night, so I'm reposting:

I have made the desired changes, merged trunk, and retested against EC2 for
the various combinations (other than distro, of course).

Please note that some of the branches that were recently merged into trunk
have broken it, as indicated here: http://wtf.labix.org/. I will certainly
remerge trunk as soon as that's fixed.

- Jim

On Wed, Sep 28, 2011 at 7:18 PM, Gustavo Niemeyer <email address hidden>wrote:

> Review: Needs Fixing
>
> [13]
>
> + juju-origin:
> + The origin of juju deployed to machines within an environment
> + is set by this option. This option can be set to a bzr branch
> + pushed to Launchpad (use a `lp:` prefix, e.g., `lp:juju`); to
> + the PPA by using `ppa`; or to the juju distribution by using
> + `distro`. If this option cannot be parsed, the distribution is
> + used.
>
> This sentence is not reading correctly in a few ways (e.g. the
> juju _origin_ is not really deployed, and there's no such thing
> as a juju distribution.. it's the Ubuntu distribution).
>
> Please use this:
>
> juju-origin:
> Defines where juju should be obtained for installing in
> machines. Can be set to a "lp..." branch url, to "ppa" for
> getting packages from the official juju PPA, or to "distro"
> for using packages from the official Ubuntu repositories.
>
>
Used this text as suggested.

>
> [14]
>
> Jim, please read this excerpt from our conversation again, *carefully*:
>
> <niemeyer> 1) Grab the installed version from the "Installed:" line
> <niemeyer> 2) If this is "(none)" return "branch"
> <niemeyer> 3) Otherwise, store the version in a variable, and keep parsing
> <niemeyer> 4) Find the version table, and find the installed version
> <niemeyer> 5) For each line in the given version, if it contains "
> ppa.launchpad.net/juju/pkgs", return "ppa"
> <niemeyer> 6) If you reach the end of the installed version, return
> "distro"
>
> Compare to what is in the branch right now.
>
>
> [15]
>
> + if k == "Installed" and v == "(none)":
> + return "ppa", None
>
> Compare with the summary above.
>
> If there's no juju package installed in the system, it means the
> user is not using the ppa.
>

Changed the logic above and the impacted test

>
>
> [16]
>
> + for _, version_info in parse:
> + if "ppa.launchpad.net" in version_info:
> + return "ppa", None
>
> Compare with the summary above.
>
> Which version is this? The existence of _any_ version that comes from
> a PPA in the apt cache is not an indication that the _installed_
> version comes from a PPA. The indication that it comes from _a_ ppa
> is not an indication that it comes from _our_ ppa either.
>
>
Got it. It's now using the precise test as you specified earlier. Sorry
about that.

>
> [17]
>
> + def test_distro_not_installed(self):
> + data = (
> + "juju:\n"
> + " Installed: (none)\n"
> + " Candidate: good-magic-1.0\n"
>
> Much better, thank you.
>
>
Thanks!

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

<jimbaker> niemeyer, hi
<niemeyer> jimbaker: Hi
<niemeyer> jimbaker: Please re-read points 3, 4 and 5
<niemeyer> jimbaker: and compare to the implementation
<jimbaker> niemeyer, ok
<niemeyer> jimbaker: Is there anything missing there?
<niemeyer> jimbaker: Maybe I'm just missing.. where's that: 3) Otherwise, store the version in a variable, and keep parsing
<jimbaker> niemeyer, #3 - python-txzookeeper dependency is no longer relevant; #4, it uses the original implementation; #5, there is no attempt to test deb repositories, since they are no longer supported
<niemeyer> jimbaker: 4) Find the version table, and find the installed version
<niemeyer> ?
* ejat has quit (Remote host closed the connection)
<jimbaker> niemeyer, ok, i'm referring to the review points. you are referring to a list from irc
<niemeyer> jimbaker: yeah
<jimbaker> looking at that now
<jimbaker> niemeyer, ok, i believe what you are saying here is that 6) refers to the installed version, which was stored earlier in 3), is that correct?
<niemeyer> 1) Grab the installed version from the "Installed:" line
<niemeyer> 2) If this is "(none)" return "branch"
<niemeyer> 3) Otherwise, store the version in a variable, and keep parsing
<niemeyer> 4) Find the version table, and find the installed version
<niemeyer> jimbaker: Is there any ambiguity here?
<jimbaker> niemeyer, correct, there is no ambiguity. the version table has more information than i have assumed, and this parse needs to take it in account

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

> <niemeyer> 1) Grab the installed version from the "Installed:" line
> <niemeyer> 2) If this is "(none)" return "branch"
> <niemeyer> 3) Otherwise, store the version in a variable, and keep parsing
> <niemeyer> 4) Find the version table, and find the installed version
> <niemeyer> jimbaker: Is there any ambiguity here?
> <jimbaker> niemeyer, correct, there is no ambiguity. the version table has
> more information than i have assumed, and this parse needs to take it in
> account

The algorithm in parse_juju_origin, and its helper function, has been reworked as described.

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

[18]

345 + " *** 0.5+bzr366-1juju1~natty1 0\n"
346 + " 500 http://ppa.launchpad.net/juju/pkgs/ubuntu/ "
347 + "natty/main amd64 Packages\n"
348 + " *** 0.5+bzr356-1juju1~natty1 0\n"
349 + " 500 http://ppa.launchpad.net/juju/pkgs/ubuntu/ "

Your multiple versions test has the PPA both in the installed and in the
non-installed version, so it's not really verifying the bug that you have
just fixed.

Change the URL in the non-installed version in this test so it doesn't come
from the PPA so that we ensure that it's really testing the installed version.
Also add a non-installed version that comes from the ppa in the distro test,
to ensure it's not being considered.

Please ensure tests pass with this and that a real interaction passes as well
before merging.

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

I'm taking this over after a conversation on IRC.

Pushed the following changes onto lp:~niemeyer/juju/env-origin, reviewed by Kapil:

- Implementation redone completely.
- Do not crash on missing apt-cache.
- Exported and tested get_default_origin.
- Tests tweaked to explore edge cases.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'docs/source/provider-configuration-ec2.rst'
--- docs/source/provider-configuration-ec2.rst 2011-09-15 17:41:55 +0000
+++ docs/source/provider-configuration-ec2.rst 2011-09-29 23:50:28 +0000
@@ -24,9 +24,15 @@
24 An S3 bucket unique to the environment, where some runtime metadata and24 An S3 bucket unique to the environment, where some runtime metadata and
25 charms are stored.25 charms are stored.
2626
27 juju-branch:27 juju-origin:
28 Allow a juju bzr branch to be utilized for all machines within an28 Defines where juju should be obtained for installing in
29 environment.29 machines. Can be set to a "lp:..." branch url, to "ppa" for
30 getting packages from the official juju PPA, or to "distro"
31 for using packages from the official Ubuntu repositories.
32
33 If this option is not set, juju will attempt to detect the
34 correct origin based on its run location and the installed
35 juju package.
3036
31 default-instance-type:37 default-instance-type:
32 The instance type to be used for machines launched within the juju38 The instance type to be used for machines launched within the juju
3339
=== modified file 'juju/providers/common/cloudinit.py'
--- juju/providers/common/cloudinit.py 2011-09-23 20:35:02 +0000
+++ juju/providers/common/cloudinit.py 2011-09-29 23:50:28 +0000
@@ -1,3 +1,5 @@
1from subprocess import Popen, PIPE
2
1from juju.errors import CloudInitError3from juju.errors import CloudInitError
2from juju.providers.common.utils import format_cloud_init4from juju.providers.common.utils import format_cloud_init
3from juju.state.auth import make_identity5from juju.state.auth import make_identity
@@ -54,6 +56,80 @@
54 % zookeeper_hosts]56 % zookeeper_hosts]
5557
5658
59def _get_apt_cache_policy():
60 return Popen(["apt-cache", "policy", "juju"], stdout=PIPE).\
61 communicate()[0]
62
63
64def _parse_apt_cache_policy(data):
65 """Flatten apt-cache policy output to generate (key, value) pairs."""
66
67 # Need to parse in two different phases, so set up iterator now
68 data = iter(data.split("\n"))
69
70 # Parse preamble
71 for row in data:
72 split = row.split(":", 1)
73 if len(split) != 2:
74 yield None, None
75 k, v = split[0].strip(), split[1].strip()
76 yield k, v
77 if k == "Version table":
78 break
79
80 # Parse version table into tag, priorities
81 tag = None
82 for row in data:
83 row = row.strip()
84 if row.startswith("***"):
85 tag = row
86 elif tag:
87 yield tag, row
88
89
90def parse_juju_origin(data):
91 """Parse output of apt-cache to determine how juju was installed."""
92 parse = _parse_apt_cache_policy(data)
93 k, _ = parse.next()
94 if k != "juju":
95 # Sanity check: no record at all, the only possibility is that
96 # this being run as a branch
97 return "branch", "lp:juju"
98
99 version = None
100 for k, v in parse:
101 if k == "Installed":
102 if v == "(none)":
103 return "branch", "lp:juju"
104 version = v
105 if k == "Version table":
106 break
107
108 for tag, priority in parse:
109 if (version in tag and
110 "http://ppa.launchpad.net/juju/pkgs/" in priority):
111 return "ppa", None
112
113 return "distro", None
114
115
116def _get_default_origin():
117 """Select the best fit for running juju on cloudinit.
118
119 Used if not otherwise specified by juju-origin.
120 """
121 import juju
122 if not juju.__file__.startswith("/usr/"):
123 return "lp:juju"
124 origin, source = parse_juju_origin(_get_apt_cache_policy())
125 if origin == "branch":
126 return source
127 elif origin == "ppa":
128 return _PPA
129 else:
130 return _DISTRO
131
132
57class CloudInit(object):133class CloudInit(object):
58 """Encapsulates juju-specific machine initialisation.134 """Encapsulates juju-specific machine initialisation.
59135
@@ -65,7 +141,7 @@
65 self._machine_id = None141 self._machine_id = None
66 self._instance_id = None142 self._instance_id = None
67 self._provider_type = None143 self._provider_type = None
68 self._source = _PPA144 self._source = _get_default_origin()
69 self._ssh_keys = []145 self._ssh_keys = []
70 self._provision = False146 self._provision = False
71 self._zookeeper = False147 self._zookeeper = False
@@ -103,7 +179,7 @@
103 or fewer than one options, are specified.179 or fewer than one options, are specified.
104180
105 Note that you don't need to call this method; the juju source181 Note that you don't need to call this method; the juju source
106 defaults to the juju PPA.182 defaults to what is returned by `get_default_origin`.
107 """183 """
108 if len(filter(None, (branch, ppa, distro))) != 1:184 if len(filter(None, (branch, ppa, distro))) != 1:
109 raise CloudInitError("Please specify one source")185 raise CloudInitError("Please specify one source")
110186
=== modified file 'juju/providers/common/launch.py'
--- juju/providers/common/launch.py 2011-09-22 13:23:00 +0000
+++ juju/providers/common/launch.py 2011-09-29 23:50:28 +0000
@@ -76,8 +76,15 @@
76 cloud_init.add_ssh_key(get_user_authorized_keys(config))76 cloud_init.add_ssh_key(get_user_authorized_keys(config))
77 cloud_init.set_machine_id(machine_id)77 cloud_init.set_machine_id(machine_id)
78 cloud_init.set_zookeeper_machines(zookeepers)78 cloud_init.set_zookeeper_machines(zookeepers)
79 if config.get("juju-branch"):79 origin = config.get("juju-origin")
80 cloud_init.set_juju_source(config["juju-branch"])80 if origin:
81 if origin.startswith("lp:"):
82 cloud_init.set_juju_source(branch=origin)
83 elif origin == "ppa":
84 cloud_init.set_juju_source(ppa=True)
85 else:
86 # Ignore other values, just use the distro for sanity
87 cloud_init.set_juju_source(distro=True)
81 if self._master:88 if self._master:
82 cloud_init.enable_bootstrap()89 cloud_init.enable_bootstrap()
83 cloud_init.set_zookeeper_secret(config["admin-secret"])90 cloud_init.set_zookeeper_secret(config["admin-secret"])
8491
=== modified file 'juju/providers/common/tests/data/cloud_init_bootstrap'
--- juju/providers/common/tests/data/cloud_init_bootstrap 2011-09-23 20:35:02 +0000
+++ juju/providers/common/tests/data/cloud_init_bootstrap 2011-09-29 23:50:28 +0000
@@ -1,8 +1,6 @@
1#cloud-config1#cloud-config
2apt-update: true2apt-update: true
3apt-upgrade: true3apt-upgrade: true
4apt_sources:
5- {source: 'ppa:juju/pkgs'}
6machine-data: {juju-provider-type: dummy, juju-zookeeper-hosts: 'localhost:2181',4machine-data: {juju-provider-type: dummy, juju-zookeeper-hosts: 'localhost:2181',
7 machine-id: passport}5 machine-id: passport}
8output: {all: '| tee -a /var/log/cloud-init-output.log'}6output: {all: '| tee -a /var/log/cloud-init-output.log'}
97
=== modified file 'juju/providers/common/tests/data/cloud_init_bootstrap_zookeepers'
--- juju/providers/common/tests/data/cloud_init_bootstrap_zookeepers 2011-09-23 20:35:02 +0000
+++ juju/providers/common/tests/data/cloud_init_bootstrap_zookeepers 2011-09-29 23:50:28 +0000
@@ -1,8 +1,6 @@
1#cloud-config1#cloud-config
2apt-update: true2apt-update: true
3apt-upgrade: true3apt-upgrade: true
4apt_sources:
5- {source: 'ppa:juju/pkgs'}
6machine-data: {juju-provider-type: dummy, juju-zookeeper-hosts: 'cotswold:2181,longleat:2181,localhost:2181',4machine-data: {juju-provider-type: dummy, juju-zookeeper-hosts: 'cotswold:2181,longleat:2181,localhost:2181',
7 machine-id: passport}5 machine-id: passport}
8output: {all: '| tee -a /var/log/cloud-init-output.log'}6output: {all: '| tee -a /var/log/cloud-init-output.log'}
97
=== added file 'juju/providers/common/tests/data/cloud_init_branch_trunk'
--- juju/providers/common/tests/data/cloud_init_branch_trunk 1970-01-01 00:00:00 +0000
+++ juju/providers/common/tests/data/cloud_init_branch_trunk 2011-09-29 23:50:28 +0000
@@ -0,0 +1,17 @@
1#cloud-config
2apt-update: true
3apt-upgrade: true
4apt_sources:
5- {source: 'ppa:juju/pkgs'}
6machine-data: {juju-provider-type: dummy, juju-zookeeper-hosts: 'cotswold:2181,longleat:2181',
7 machine-id: passport}
8output: {all: '| tee -a /var/log/cloud-init-output.log'}
9packages: [bzr, byobu, tmux, python-setuptools, python-twisted, python-argparse, python-txaws,
10 python-zookeeper]
11runcmd: [sudo apt-get install -y python-txzookeeper, sudo mkdir -p /usr/lib/juju,
12 'cd /usr/lib/juju && sudo /usr/bin/bzr co lp:juju juju',
13 cd /usr/lib/juju/juju && sudo python setup.py develop, sudo mkdir -p /var/lib/juju,
14 sudo mkdir -p /var/log/juju, 'JUJU_MACHINE_ID=passport JUJU_ZOOKEEPER=cotswold:2181,longleat:2181
15 python -m juju.agents.machine -n --logfile=/var/log/juju/machine-agent.log
16 --pidfile=/var/run/juju/machine-agent.pid']
17ssh_authorized_keys: [chubb]
018
=== modified file 'juju/providers/common/tests/data/cloud_init_normal'
--- juju/providers/common/tests/data/cloud_init_normal 2011-09-15 19:29:57 +0000
+++ juju/providers/common/tests/data/cloud_init_normal 2011-09-29 23:50:28 +0000
@@ -1,8 +1,6 @@
1#cloud-config1#cloud-config
2apt-update: true2apt-update: true
3apt-upgrade: true3apt-upgrade: true
4apt_sources:
5- {source: 'ppa:juju/pkgs'}
6machine-data: {juju-provider-type: dummy, juju-zookeeper-hosts: 'cotswold:2181,longleat:2181',4machine-data: {juju-provider-type: dummy, juju-zookeeper-hosts: 'cotswold:2181,longleat:2181',
7 machine-id: passport}5 machine-id: passport}
8output: {all: '| tee -a /var/log/cloud-init-output.log'}6output: {all: '| tee -a /var/log/cloud-init-output.log'}
97
=== added file 'juju/providers/common/tests/data/cloud_init_ppa'
--- juju/providers/common/tests/data/cloud_init_ppa 1970-01-01 00:00:00 +0000
+++ juju/providers/common/tests/data/cloud_init_ppa 2011-09-29 23:50:28 +0000
@@ -0,0 +1,15 @@
1#cloud-config
2apt-update: true
3apt-upgrade: true
4apt_sources:
5- {'source': 'ppa:juju/pkgs'}
6machine-data: {juju-provider-type: dummy, juju-zookeeper-hosts: 'cotswold:2181,longleat:2181',
7 machine-id: passport}
8output: {all: '| tee -a /var/log/cloud-init-output.log'}
9packages: [bzr, byobu, tmux, python-setuptools, python-twisted, python-argparse, python-txaws,
10 python-zookeeper]
11runcmd: [sudo apt-get -y install juju, sudo mkdir -p /var/lib/juju, sudo mkdir
12 -p /var/log/juju, 'JUJU_MACHINE_ID=passport JUJU_ZOOKEEPER=cotswold:2181,longleat:2181
13 python -m juju.agents.machine -n --logfile=/var/log/juju/machine-agent.log
14 --pidfile=/var/run/juju/machine-agent.pid']
15ssh_authorized_keys: [chubb]
016
=== modified file 'juju/providers/common/tests/test_cloudinit.py'
--- juju/providers/common/tests/test_cloudinit.py 2011-09-22 13:23:00 +0000
+++ juju/providers/common/tests/test_cloudinit.py 2011-09-29 23:50:28 +0000
@@ -1,12 +1,14 @@
1import os1import os
2import stat
23
3import yaml4import yaml
45
5from juju.errors import CloudInitError6from juju.errors import CloudInitError
6from juju.lib.testing import TestCase7from juju.lib.testing import TestCase
7from juju.providers.common.cloudinit import CloudInit8from juju.providers.common.cloudinit import CloudInit, parse_juju_origin
8from juju.providers.dummy import DummyMachine9from juju.providers.dummy import DummyMachine
910
11
10DATA_DIR = os.path.join(os.path.abspath(os.path.dirname(__file__)), "data")12DATA_DIR = os.path.join(os.path.abspath(os.path.dirname(__file__)), "data")
1113
1214
@@ -30,6 +32,7 @@
30 cloud_init.set_provider_type("dummy")32 cloud_init.set_provider_type("dummy")
31 cloud_init.set_instance_id_accessor("token")33 cloud_init.set_instance_id_accessor("token")
32 cloud_init.set_zookeeper_secret("seekrit")34 cloud_init.set_zookeeper_secret("seekrit")
35 cloud_init.set_juju_source(distro=True)
33 if with_zookeepers:36 if with_zookeepers:
34 cloud_init.set_zookeeper_machines([37 cloud_init.set_zookeeper_machines([
35 DummyMachine("blah", "blah", "cotswold"),38 DummyMachine("blah", "blah", "cotswold"),
@@ -74,12 +77,34 @@
74 self.assertEquals(str(error), "Please specify one source")77 self.assertEquals(str(error), "Please specify one source")
7578
76 def test_render_normal(self):79 def test_render_normal(self):
77 self.assert_render(self.construct_normal(), "cloud_init_normal")80 path = os.environ.get("PATH", "")
81 alt_apt_cache_path = self.makeDir()
82 filename = os.path.join(alt_apt_cache_path, "apt-cache")
83 with open(filename, "w") as f:
84 f.write(
85 "#!/bin/bash\n"
86 "cat <<EOF\n"
87 "juju:\n"
88 " Installed: good-magic-1.0\n"
89 " Candidate: good-magic-1.0\n"
90 " Version table:\n"
91 " *** good-magic-1.0\n"
92 " 500 http://us.archive.ubuntu.com/ubuntu/ "
93 "natty/main amd64 Packages\n"
94 " 100 /var/lib/dpkg/status\n"
95 "EOF\n")
96 os.chmod(filename, stat.S_IEXEC | stat.S_IREAD)
97 updated_path = alt_apt_cache_path + ":" + path
98 self.change_environment(PATH=updated_path)
99 import juju
100 self.patch(juju, "__file__",
101 "/usr/lib/pymodules/python2.7/juju/__init__.pyc")
102 self.assert_render(self.construct_normal(), "cloud_init_distro")
78103
79 def test_render_ppa_source(self):104 def test_render_ppa_source(self):
80 cloud_init = self.construct_normal()105 cloud_init = self.construct_normal()
81 cloud_init.set_juju_source(ppa=True)106 cloud_init.set_juju_source(ppa=True)
82 self.assert_render(cloud_init, "cloud_init_normal")107 self.assert_render(cloud_init, "cloud_init_ppa")
83108
84 def test_render_distro_source(self):109 def test_render_distro_source(self):
85 cloud_init = self.construct_normal()110 cloud_init = self.construct_normal()
@@ -91,9 +116,90 @@
91 cloud_init.set_juju_source(branch="lp:blah/juju/blah-blah")116 cloud_init.set_juju_source(branch="lp:blah/juju/blah-blah")
92 self.assert_render(cloud_init, "cloud_init_branch")117 self.assert_render(cloud_init, "cloud_init_branch")
93118
119 def test_render_branch_source_if_not_installed(self):
120 import juju
121 self.patch(juju, "__file__", "/not/installed/under/usr")
122 cloud_init = self.construct_normal()
123 self.assert_render(cloud_init, "cloud_init_branch_trunk")
124
94 def test_render_bootstrap(self):125 def test_render_bootstrap(self):
95 self.assert_render(self.construct_bootstrap(), "cloud_init_bootstrap")126 self.assert_render(self.construct_bootstrap(), "cloud_init_bootstrap")
96127
97 def test_render_bootstrap_with_zookeepers(self):128 def test_render_bootstrap_with_zookeepers(self):
98 self.assert_render(129 self.assert_render(
99 self.construct_bootstrap(True), "cloud_init_bootstrap_zookeepers")130 self.construct_bootstrap(True), "cloud_init_bootstrap_zookeepers")
131
132
133class ParseJujuOriginTest(TestCase):
134
135 def test_distro_installed(self):
136 data = (
137 "juju:\n"
138 " Installed: good-magic-1.0\n"
139 " Candidate: good-magic-1.0\n"
140 " Version table:\n"
141 " *** good-magic-1.0 0\n"
142 " 500 http://us.archive.ubuntu.com/ubuntu/ "
143 "natty/main amd64 Packages\n"
144 " 100 /var/lib/dpkg/status\n")
145
146 origin, source = parse_juju_origin(data)
147 self.assertEqual(origin, "distro")
148 self.assertEqual(source, None)
149
150 def test_multiple_versions_available(self):
151 data = (
152 "juju:\n"
153 " Installed: 0.5+bzr366-1juju1~natty1\n"
154 " Candidate: 0.5+bzr366-1juju1~natty1\n"
155 " Version table:\n"
156 " *** bad-magic-0.5 0\n"
157 " 500 http://us.archive.ubuntu.com/ubuntu/ "
158 "natty/main amd64 Packages\n"
159 " 100 /var/lib/dpkg/status\n"
160 " *** 0.5+bzr366-1juju1~natty1 0\n"
161 " 500 http://ppa.launchpad.net/juju/pkgs/ubuntu/ "
162 "natty/main amd64 Packages\n"
163 " *** 0.5+bzr356-1juju1~natty1 0\n"
164 " 500 http://ppa.launchpad.net/juju/pkgs/ubuntu/ "
165 "natty/main amd64 Packages\n")
166
167 origin, source = parse_juju_origin(data)
168 self.assertEqual(origin, "ppa")
169 self.assertEqual(source, None)
170
171 def test_distro_not_installed(self):
172 data = (
173 "juju:\n"
174 " Installed: (none)\n"
175 " Candidate: good-magic-1.0\n"
176 " Version table:\n"
177 " *** good-magic-1.0 0\n"
178 " 500 http://us.archive.ubuntu.com/ubuntu/ "
179 "natty/main amd64 Packages\n"
180 " 100 /var/lib/dpkg/status\n")
181
182 origin, source = parse_juju_origin(data)
183 self.assertEqual(origin, "branch")
184 self.assertEqual(source, "lp:juju")
185
186 def test_ppa_installed(self):
187 data = (
188 "juju:\n"
189 " Installed: 0.5+bzr356-1juju1~natty1\n"
190 " Candidate: 0.5+bzr356-1juju1~natty1\n"
191 " Version table:\n"
192 " *** 0.5+bzr356-1juju1~natty1 0\n"
193 " 500 http://ppa.launchpad.net/juju/pkgs/ubuntu/ "
194 "natty/main amd64 Packages\n"
195 " 100 /var/lib/dpkg/status\n")
196
197 origin, source = parse_juju_origin(data)
198 self.assertEqual(origin, "ppa")
199 self.assertEqual(source, None)
200
201 def test_juju_package_is_unknown(self):
202 data = "N: Unable to locate package juju"
203 origin, source = parse_juju_origin(data)
204 self.assertEqual(origin, "branch")
205 self.assertEqual(source, "lp:juju")
100206
=== modified file 'juju/providers/ec2/tests/common.py'
--- juju/providers/ec2/tests/common.py 2011-09-22 13:23:00 +0000
+++ juju/providers/ec2/tests/common.py 2011-09-29 23:50:28 +0000
@@ -22,6 +22,7 @@
2222
23 def get_config(self):23 def get_config(self):
24 return {"type": "ec2",24 return {"type": "ec2",
25 "juju-origin": "distro",
25 "admin-secret": "magic-beans",26 "admin-secret": "magic-beans",
26 "access-key": "0f62e973d5f8",27 "access-key": "0f62e973d5f8",
27 "secret-key": "3e5a7c653f59",28 "secret-key": "3e5a7c653f59",
2829
=== modified file 'juju/providers/ec2/tests/data/bootstrap_cloud_init'
--- juju/providers/ec2/tests/data/bootstrap_cloud_init 2011-09-23 20:35:02 +0000
+++ juju/providers/ec2/tests/data/bootstrap_cloud_init 2011-09-29 23:50:28 +0000
@@ -1,8 +1,6 @@
1#cloud-config1#cloud-config
2apt-update: true2apt-update: true
3apt-upgrade: true3apt-upgrade: true
4apt_sources:
5- {source: 'ppa:juju/pkgs'}
6machine-data: {juju-provider-type: ec2, juju-zookeeper-hosts: 'localhost:2181',4machine-data: {juju-provider-type: ec2, juju-zookeeper-hosts: 'localhost:2181',
7 machine-id: '0'}5 machine-id: '0'}
8output: {all: '| tee -a /var/log/cloud-init-output.log'}6output: {all: '| tee -a /var/log/cloud-init-output.log'}
97
=== modified file 'juju/providers/ec2/tests/data/launch_cloud_init'
--- juju/providers/ec2/tests/data/launch_cloud_init 2011-09-15 19:29:57 +0000
+++ juju/providers/ec2/tests/data/launch_cloud_init 2011-09-29 23:50:28 +0000
@@ -1,8 +1,6 @@
1#cloud-config1#cloud-config
2apt-update: true2apt-update: true
3apt-upgrade: true3apt-upgrade: true
4apt_sources:
5- {source: 'ppa:juju/pkgs'}
6machine-data: {juju-provider-type: ec2, juju-zookeeper-hosts: 'es.example.internal:2181',4machine-data: {juju-provider-type: ec2, juju-zookeeper-hosts: 'es.example.internal:2181',
7 machine-id: '1'}5 machine-id: '1'}
8output: {all: '| tee -a /var/log/cloud-init-output.log'}6output: {all: '| tee -a /var/log/cloud-init-output.log'}
97
=== added file 'juju/providers/ec2/tests/data/launch_cloud_init_branch'
--- juju/providers/ec2/tests/data/launch_cloud_init_branch 1970-01-01 00:00:00 +0000
+++ juju/providers/ec2/tests/data/launch_cloud_init_branch 2011-09-29 23:50:28 +0000
@@ -0,0 +1,20 @@
1#cloud-config
2apt-update: true
3apt-upgrade: true
4apt_sources:
5- {source: 'ppa:juju/pkgs'}
6machine-data: {juju-provider-type: ec2, juju-zookeeper-hosts: 'es.example.internal:2181',
7 machine-id: '1'}
8output: {all: '| tee -a /var/log/cloud-init-output.log'}
9packages: [bzr, byobu, tmux, python-setuptools, python-twisted, python-argparse, python-txaws,
10 python-zookeeper]
11runcmd: [sudo apt-get install -y python-txzookeeper,
12 sudo mkdir -p /usr/lib/juju,
13 'cd /usr/lib/juju && sudo /usr/bin/bzr co lp:~wizard/juju-juicebar juju',
14 cd /usr/lib/juju/juju && sudo python setup.py develop,
15 sudo mkdir -p /var/lib/juju,
16 sudo mkdir -p /var/log/juju,
17 'JUJU_MACHINE_ID=1 JUJU_ZOOKEEPER=es.example.internal:2181
18 python -m juju.agents.machine -n --logfile=/var/log/juju/machine-agent.log
19 --pidfile=/var/run/juju/machine-agent.pid']
20ssh_authorized_keys: [zebra]
021
=== added file 'juju/providers/ec2/tests/data/launch_cloud_init_ppa'
--- juju/providers/ec2/tests/data/launch_cloud_init_ppa 1970-01-01 00:00:00 +0000
+++ juju/providers/ec2/tests/data/launch_cloud_init_ppa 2011-09-29 23:50:28 +0000
@@ -0,0 +1,15 @@
1#cloud-config
2apt-update: true
3apt-upgrade: true
4apt_sources:
5- {source: 'ppa:juju/pkgs'}
6machine-data: {juju-provider-type: ec2, juju-zookeeper-hosts: 'es.example.internal:2181',
7 machine-id: '1'}
8output: {all: '| tee -a /var/log/cloud-init-output.log'}
9packages: [bzr, byobu, tmux, python-setuptools, python-twisted, python-argparse, python-txaws,
10 python-zookeeper]
11runcmd: [sudo apt-get -y install juju, sudo mkdir -p /var/lib/juju, sudo mkdir
12 -p /var/log/juju, 'JUJU_MACHINE_ID=1 JUJU_ZOOKEEPER=es.example.internal:2181
13 python -m juju.agents.machine -n --logfile=/var/log/juju/machine-agent.log
14 --pidfile=/var/run/juju/machine-agent.pid']
15ssh_authorized_keys: [zebra]
016
=== modified file 'juju/providers/ec2/tests/test_bootstrap.py'
--- juju/providers/ec2/tests/test_bootstrap.py 2011-09-22 13:23:00 +0000
+++ juju/providers/ec2/tests/test_bootstrap.py 2011-09-29 23:50:28 +0000
@@ -13,6 +13,7 @@
1313
14from .common import EC2TestMixin, EC2MachineLaunchMixin14from .common import EC2TestMixin, EC2MachineLaunchMixin
1515
16
16DATA_DIR = os.path.join(os.path.abspath(os.path.dirname(__file__)), "data")17DATA_DIR = os.path.join(os.path.abspath(os.path.dirname(__file__)), "data")
1718
1819
1920
=== modified file 'juju/providers/ec2/tests/test_launch.py'
--- juju/providers/ec2/tests/test_launch.py 2011-09-16 00:36:31 +0000
+++ juju/providers/ec2/tests/test_launch.py 2011-09-29 23:50:28 +0000
@@ -21,10 +21,11 @@
21class EC2MachineLaunchTest(EC2TestMixin, EC2MachineLaunchMixin, TestCase):21class EC2MachineLaunchTest(EC2TestMixin, EC2MachineLaunchMixin, TestCase):
2222
23 def _mock_launch(self, instance, expect_ami="ami-default",23 def _mock_launch(self, instance, expect_ami="ami-default",
24 expect_instance_type="m1.small"):24 expect_instance_type="m1.small",
25 cloud_init="launch_cloud_init"):
2526
26 def verify_user_data(data):27 def verify_user_data(data):
27 expect_path = os.path.join(DATA_DIR, "launch_cloud_init")28 expect_path = os.path.join(DATA_DIR, cloud_init)
28 with open(expect_path) as f:29 with open(expect_path) as f:
29 expect_cloud_init = yaml.load(f.read())30 expect_cloud_init = yaml.load(f.read())
30 self.assertEquals(yaml.load(data), expect_cloud_init)31 self.assertEquals(yaml.load(data), expect_cloud_init)
@@ -75,6 +76,63 @@
75 return d76 return d
7677
77 @inlineCallbacks78 @inlineCallbacks
79 def test_provider_launch_using_branch(self):
80 """Can use a juju branch to launch a machine"""
81 self.ec2.describe_security_groups()
82 self.mocker.result(succeed([]))
83 self._mock_create_group()
84 self._mock_create_machine_group("1")
85 self._mock_launch_utils(region="us-east-1")
86 self._mock_get_zookeeper_hosts()
87 self._mock_launch(
88 self.get_instance("i-foobar"),
89 cloud_init="launch_cloud_init_branch")
90 self.mocker.replay()
91
92 provider = self.get_provider()
93 provider.config["juju-origin"] = "lp:~wizard/juju-juicebar"
94 machines = yield provider.start_machine({"machine-id": "1"})
95 self.assert_machine(machines[0], "i-foobar", "")
96
97 @inlineCallbacks
98 def test_provider_launch_using_ppa(self):
99 """Can use the juju ppa to launch a machine"""
100 self.ec2.describe_security_groups()
101 self.mocker.result(succeed([]))
102 self._mock_create_group()
103 self._mock_create_machine_group("1")
104 self._mock_launch_utils(region="us-east-1")
105 self._mock_get_zookeeper_hosts()
106 self._mock_launch(
107 self.get_instance("i-foobar"),
108 cloud_init="launch_cloud_init_ppa")
109 self.mocker.replay()
110
111 provider = self.get_provider()
112 provider.config["juju-origin"] = "ppa"
113 machines = yield provider.start_machine({"machine-id": "1"})
114 self.assert_machine(machines[0], "i-foobar", "")
115
116 @inlineCallbacks
117 def test_provider_launch_using_explicit_distro(self):
118 """Can set juju-origin explicitly to `distro`"""
119 self.ec2.describe_security_groups()
120 self.mocker.result(succeed([]))
121 self._mock_create_group()
122 self._mock_create_machine_group("1")
123 self._mock_launch_utils(region="us-east-1")
124 self._mock_get_zookeeper_hosts()
125 self._mock_launch(
126 self.get_instance("i-foobar"),
127 cloud_init="launch_cloud_init")
128 self.mocker.replay()
129
130 provider = self.get_provider()
131 provider.config["juju-origin"] = "distro"
132 machines = yield provider.start_machine({"machine-id": "1"})
133 self.assert_machine(machines[0], "i-foobar", "")
134
135 @inlineCallbacks
78 def test_provider_launch_existing_security_group(self):136 def test_provider_launch_existing_security_group(self):
79 """Verify that the launch works if the env security group exists"""137 """Verify that the launch works if the env security group exists"""
80 instance = Instance("i-foobar", "running", dns_name="x1.example.com")138 instance = Instance("i-foobar", "running", dns_name="x1.example.com")
81139
=== modified file 'juju/providers/orchestra/tests/common.py'
--- juju/providers/orchestra/tests/common.py 2011-09-22 13:23:00 +0000
+++ juju/providers/orchestra/tests/common.py 2011-09-29 23:50:28 +0000
@@ -13,7 +13,9 @@
1313
14DATA_DIR = os.path.join(os.path.abspath(os.path.dirname(__file__)), "data")14DATA_DIR = os.path.join(os.path.abspath(os.path.dirname(__file__)), "data")
1515
16CONFIG = {"orchestra-server": "somewhe.re",16CONFIG = {"type": "orchestra",
17 "juju-origin": "distro",
18 "orchestra-server": "somewhe.re",
17 "orchestra-user": "user",19 "orchestra-user": "user",
18 "orchestra-pass": "pass",20 "orchestra-pass": "pass",
19 "acquired-mgmt-class": "acquired",21 "acquired-mgmt-class": "acquired",
2022
=== modified file 'juju/providers/orchestra/tests/data/bootstrap_user_data'
--- juju/providers/orchestra/tests/data/bootstrap_user_data 2011-09-23 20:35:02 +0000
+++ juju/providers/orchestra/tests/data/bootstrap_user_data 2011-09-29 23:50:28 +0000
@@ -1,8 +1,6 @@
1#cloud-config1#cloud-config
2apt-update: true2apt-update: true
3apt-upgrade: true3apt-upgrade: true
4apt_sources:
5- {source: 'ppa:juju/pkgs'}
6machine-data: {juju-provider-type: orchestra, juju-zookeeper-hosts: 'localhost:2181',4machine-data: {juju-provider-type: orchestra, juju-zookeeper-hosts: 'localhost:2181',
7 machine-id: '0'}5 machine-id: '0'}
8output: {all: '| tee -a /var/log/cloud-init-output.log'}6output: {all: '| tee -a /var/log/cloud-init-output.log'}
97
=== modified file 'juju/providers/orchestra/tests/data/launch_user_data'
--- juju/providers/orchestra/tests/data/launch_user_data 2011-09-16 14:07:03 +0000
+++ juju/providers/orchestra/tests/data/launch_user_data 2011-09-29 23:50:28 +0000
@@ -1,8 +1,6 @@
1#cloud-config1#cloud-config
2apt-update: true2apt-update: true
3apt-upgrade: true3apt-upgrade: true
4apt_sources:
5- {source: 'ppa:juju/pkgs'}
6machine-data: {juju-provider-type: orchestra, juju-zookeeper-hosts: 'jennifer:2181',4machine-data: {juju-provider-type: orchestra, juju-zookeeper-hosts: 'jennifer:2181',
7 machine-id: '42'}5 machine-id: '42'}
8output: {all: '| tee -a /var/log/cloud-init-output.log'}6output: {all: '| tee -a /var/log/cloud-init-output.log'}

Subscribers

People subscribed via source and target branches

to status/vote changes: