Merge lp:~adam-collard/charms/trusty/landscape-client/landscape-client-multiple-juju-files into lp:charms/trusty/landscape-client

Proposed by Adam Collard
Status: Merged
Approved by: Adam Collard
Approved revision: 46
Merged at revision: 39
Proposed branch: lp:~adam-collard/charms/trusty/landscape-client/landscape-client-multiple-juju-files
Merge into: lp:charms/trusty/landscape-client
Diff against target: 241 lines (+81/-20)
3 files modified
hooks/common.py (+25/-3)
hooks/hooks.py (+28/-11)
hooks/test_hooks.py (+28/-6)
To merge this branch: bzr merge lp:~adam-collard/charms/trusty/landscape-client/landscape-client-multiple-juju-files
Reviewer Review Type Date Requested Status
Данило Шеган (community) Approve
Geoff Teale (community) Approve
Adam Collard Abstain
Review via email: mp+223040@code.launchpad.net

This proposal supersedes a proposal from 2014-06-12.

Commit message

Let the charm output several juju-info JSON files instead of a single file, since the landscape client charm can be deployed to several machines that are "hulk-smashed" together on the same physical machine.

Description of the change

This branch lets the charm output several juju-info JSON files instead of a single file, since the landscape client charm can be deployed to several machines that are "hulk-smashed" together on the same physical machine.

I forked it from lp:~tribaal/charms/trusty/landscape-client/landscape-client-multiple-juju-files because it's blocking my work on lp:1326261

For testing you can do something like this:

PYTHONPATH=~/src/landscape-client/13.07/ make test

To post a comment you must log in.
Revision history for this message
Adam Collard (adam-collard) wrote : Posted in a previous version of this proposal

Looks good! Inline comment below, but otherwise +1

review: Approve
Revision history for this message
Adam Collard (adam-collard) wrote : Posted in a previous version of this proposal

Some typoes (inline)

Revision history for this message
Adam Collard (adam-collard) wrote : Posted in a previous version of this proposal

temporary abstain until I get a chance to test it in anger

review: Abstain
Revision history for this message
Adam Collard (adam-collard) wrote : Posted in a previous version of this proposal

As discussed in IRC, we need the charm to continue working with released landscape-client code (in precise/ and trusty/ not just in $series-updates).

review: Needs Fixing
Revision history for this message
Adam Collard (adam-collard) :
review: Abstain
Revision history for this message
Chris Glass (tribaal) wrote :

FWIW Adam's changes look good - but I won't +1 here since it's a take over from my own branch

Revision history for this message
Geoff Teale (tealeg) wrote :

+1

Check the inline comments below.

review: Approve
Revision history for this message
Adam Collard (adam-collard) wrote :

Thanks for the review, I've opted not to address the concerns you raised. Replied inline :)

Revision history for this message
Данило Шеган (danilo) wrote :

Looks good, even the tests pass. Only one comment regarding "delete" as argument name.

review: Approve
46. By Adam Collard

Rename delete=False to try_to_register=True (danilo's review)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'hooks/common.py'
2--- hooks/common.py 2013-11-19 12:39:44 +0000
3+++ hooks/common.py 2014-06-13 15:44:07 +0000
4@@ -1,6 +1,7 @@
5 import os
6 import sys
7 import json
8+from glob import glob
9 from pwd import getpwnam
10 from subprocess import check_output
11
12@@ -52,13 +53,19 @@
13 def __init__(self):
14 self.config = Configuration()
15
16- def update_client_config(self, service_config):
17+ def update_client_config(self, service_config, try_to_register=True):
18 """Update the client config.
19
20 @param service_config: A dict containing the config items to be
21 updated. Dashes in the key values will be converted to
22 underscore, to match the Landscape configuration.
23
24+ @param try_to_register: Should we attempt to register after
25+ updating the client configuration? (default True). No need
26+ to show warnings if we are updating the configuration to
27+ be deleted (as is the case when exiting a relation, for
28+ example).
29+
30 An attempt to register the client will be made, if the client wasn't
31 configured before.
32 """
33@@ -74,8 +81,12 @@
34 is_configured_enough = all([
35 self.config.get("account_name"),
36 self.config.get("computer_title"),
37- os.path.exists(
38- os.path.join(self.config.data_path, "juju-info.json"))])
39+ get_juju_info_filenames(self.juju_directory)])
40+ if not try_to_register:
41+ # We don't need to further check the configuration if we are
42+ # deleting it.
43+ return 0
44+
45 if is_configured_enough:
46 return self.try_to_register()
47 else:
48@@ -83,6 +94,13 @@
49 " proceed, skipping")
50 return 0
51
52+ @property
53+ def juju_directory(self):
54+ try:
55+ return self.config.juju_directory
56+ except AttributeError: # older landscape-client versions
57+ return os.path.join(self.config.data_path, "juju-info.d")
58+
59 def clear_registration(self):
60 """
61 Do steps necessary to clear the client registration, so that next time
62@@ -153,3 +171,7 @@
63 """Dump content in JSON format to the specified file."""
64 with open(filename, "w") as dumpfile:
65 json.dump(content, dumpfile)
66+
67+
68+def get_juju_info_filenames(juju_directory):
69+ return glob("%s/*.json" % juju_directory)
70
71=== modified file 'hooks/hooks.py'
72--- hooks/hooks.py 2014-05-30 05:59:47 +0000
73+++ hooks/hooks.py 2014-06-13 15:44:07 +0000
74@@ -14,7 +14,9 @@
75 from shutil import rmtree
76 from subprocess import CalledProcessError
77
78-from common import write_json_file, JujuBroker, LandscapeBroker, chown
79+from common import (
80+ write_json_file, JujuBroker, LandscapeBroker, chown,
81+ get_juju_info_filenames)
82 from ceph import (
83 get_ceph_client_path, write_ceph_client_keyring, write_ceph_client_config)
84
85@@ -52,7 +54,7 @@
86 data_path])
87
88
89-@hooks.hook("registration-relation-joined","registration-relation-changed")
90+@hooks.hook("registration-relation-joined", "registration-relation-changed")
91 def registration_relation(juju_broker=JUJU_BROKER,
92 landscape_broker=LANDSCAPE_BROKER):
93 data = juju_broker.get_relation_config()
94@@ -95,15 +97,28 @@
95 landscape_broker=LANDSCAPE_BROKER):
96 landscape_broker.config.reload()
97 relation_conf = juju_broker.get_relation_config()
98+ remote_unit_name = juju_broker.environment.get("JUJU_REMOTE_UNIT")
99 # We use the remote unit for the unit name, since we want to associate this
100 # client with the unit it's managing, not its own unit.
101 juju_info = {
102 "environment-uuid": juju_broker.environment.get("JUJU_ENV_UUID"),
103- "unit-name": juju_broker.environment.get("JUJU_REMOTE_UNIT"),
104+ "unit-name": remote_unit_name,
105 "api-addresses": juju_broker.environment.get("JUJU_API_ADDRESSES"),
106 "private-address": relation_conf.get("private-address")}
107- juju_info_file = os.path.join(
108- landscape_broker.config.data_path, "juju-info.json")
109+
110+ # Let's not use any "/" in a filename.
111+ unit_name = remote_unit_name.replace("/", "-")
112+ juju_file = "%s.json" % unit_name
113+
114+ juju_info_dir = landscape_broker.juju_directory
115+
116+ try:
117+ os.mkdir(juju_info_dir)
118+ except OSError:
119+ pass # The file already exists.
120+
121+ juju_info_file = os.path.join(juju_info_dir, juju_file)
122+
123 write_json_file(juju_info_file, juju_info)
124 exit_code = landscape_broker.update_client_config(
125 {"computer-title": socket.gethostname()})
126@@ -119,12 +134,14 @@
127 computer title unset and the juju info file removed, so that we
128 won't try to register again when the config-changed hook is fired.
129 """
130- landscape_broker.clear_registration(),
131- juju_info_path = os.path.join(
132- landscape_broker.config.data_path, "juju-info.json")
133- if os.path.exists(juju_info_path):
134- os.remove(juju_info_path)
135- landscape_broker.update_client_config({"computer-title": ""})
136+ landscape_broker.clear_registration()
137+
138+ # Delete all of the juju-info files.
139+ files_to_delete = get_juju_info_filenames(landscape_broker.juju_directory)
140+ for to_delete in files_to_delete:
141+ os.remove(to_delete)
142+ landscape_broker.update_client_config(
143+ {"computer-title": ""}, try_to_register=False)
144
145
146 @hooks.hook("ceph-client-relation-changed")
147
148=== modified file 'hooks/test_hooks.py'
149--- hooks/test_hooks.py 2014-05-30 05:59:47 +0000
150+++ hooks/test_hooks.py 2014-06-13 15:44:07 +0000
151@@ -5,6 +5,7 @@
152 from tempfile import mkdtemp
153 from unittest import TestCase
154 from uuid import uuid4
155+from glob import glob
156
157 from landscape.deployment import Configuration
158 from landscape.lib.fs import read_file
159@@ -59,6 +60,13 @@
160 self.landscape_broker.config.write()
161 self.juju_broker = FakeJujuBroker()
162
163+ def touch_example_juju_info_file(self):
164+ if not os.path.exists(self.landscape_broker.juju_directory):
165+ os.mkdir(self.landscape_broker.juju_directory)
166+ filename = os.path.join(self.landscape_broker.juju_directory,
167+ "whatever.json")
168+ write_json_file(filename=filename, content={})
169+
170 def mkdtemp(self):
171 directory = mkdtemp(prefix=self.__class__.__name__)
172 self.addCleanup(rmtree, directory)
173@@ -165,8 +173,10 @@
174 "private-address": "10.0.0.99"}
175 hooks.container_relation_joined(juju_broker=self.juju_broker,
176 landscape_broker=self.landscape_broker)
177+
178 juju_info_path = os.path.join(
179- self.landscape_broker.config.data_path, "juju-info.json")
180+ self.landscape_broker.juju_directory, "unit-0.json")
181+
182 juju_info = json.loads(read_file(juju_info_path))
183 self.assertEqual(
184 {"environment-uuid": "uuid1",
185@@ -184,9 +194,10 @@
186 registration_attempts = []
187
188 def record_registration_attempt():
189- juju_info_path = os.path.join(
190- self.landscape_broker.config.data_path, "juju-info.json")
191- registration_attempts.append(os.path.exists(juju_info_path))
192+ juju_directory = self.landscape_broker.juju_directory
193+ juju_file_list = glob("%s/*.json" % juju_directory)
194+ for _ in juju_file_list:
195+ registration_attempts.append(True)
196
197 self.landscape_broker.try_to_register = record_registration_attempt
198 hooks.container_relation_joined(juju_broker=self.juju_broker,
199@@ -199,7 +210,8 @@
200 The client adds the hostname as the "computer-title" field of the
201 landscape broker config.
202 """
203- self.hooks.run("container-relation-joined")
204+ hooks.container_relation_joined(juju_broker=self.juju_broker,
205+ landscape_broker=self.landscape_broker)
206 result = self.landscape_broker.config.computer_title
207 self.assertEqual(result, socket.gethostname())
208
209@@ -234,7 +246,11 @@
210 now gone).
211 """
212 juju_info_path = os.path.join(
213- self.landscape_broker.config.data_path, "juju-info.json")
214+ self.landscape_broker.juju_directory, "unit-0.json")
215+
216+ if not os.path.exists(self.landscape_broker.juju_directory):
217+ os.mkdir(self.landscape_broker.juju_directory)
218+
219 juju_info = {"environment-uuid": "uuid1",
220 "unit-name": "unit/0",
221 "api-addresses": "10.0.0.1:1234",
222@@ -384,6 +400,9 @@
223
224 def setUp(self):
225 super(ConfigChangedTest, self).setUp()
226+ self.landscape_broker.config.account_name = "account1"
227+ self.landscape_broker.config.computer_title = "title"
228+ self.touch_example_juju_info_file()
229 self.addCleanup(setattr, hooks, "CERT_FILE", hooks.CERT_FILE)
230 tmp_dir = self.mkdtemp()
231 hooks.CERT_FILE = "%s/cert" % tmp_dir
232@@ -410,6 +429,9 @@
233
234 def setUp(self):
235 super(RegistrationRelationJoinedTest, self).setUp()
236+ self.landscape_broker.config.account_name = "account1"
237+ self.landscape_broker.config.computer_title = "title"
238+ self.touch_example_juju_info_file()
239 self.addCleanup(setattr, hooks, "CERT_FILE", hooks.CERT_FILE)
240 tmp_dir = self.mkdtemp()
241 hooks.CERT_FILE = "%s/cert" % tmp_dir

Subscribers

People subscribed via source and target branches