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
=== modified file 'hooks/common.py'
--- hooks/common.py 2013-11-19 12:39:44 +0000
+++ hooks/common.py 2014-06-13 15:44:07 +0000
@@ -1,6 +1,7 @@
1import os1import os
2import sys2import sys
3import json3import json
4from glob import glob
4from pwd import getpwnam5from pwd import getpwnam
5from subprocess import check_output6from subprocess import check_output
67
@@ -52,13 +53,19 @@
52 def __init__(self):53 def __init__(self):
53 self.config = Configuration()54 self.config = Configuration()
5455
55 def update_client_config(self, service_config):56 def update_client_config(self, service_config, try_to_register=True):
56 """Update the client config.57 """Update the client config.
5758
58 @param service_config: A dict containing the config items to be59 @param service_config: A dict containing the config items to be
59 updated. Dashes in the key values will be converted to60 updated. Dashes in the key values will be converted to
60 underscore, to match the Landscape configuration.61 underscore, to match the Landscape configuration.
6162
63 @param try_to_register: Should we attempt to register after
64 updating the client configuration? (default True). No need
65 to show warnings if we are updating the configuration to
66 be deleted (as is the case when exiting a relation, for
67 example).
68
62 An attempt to register the client will be made, if the client wasn't69 An attempt to register the client will be made, if the client wasn't
63 configured before.70 configured before.
64 """71 """
@@ -74,8 +81,12 @@
74 is_configured_enough = all([81 is_configured_enough = all([
75 self.config.get("account_name"),82 self.config.get("account_name"),
76 self.config.get("computer_title"),83 self.config.get("computer_title"),
77 os.path.exists(84 get_juju_info_filenames(self.juju_directory)])
78 os.path.join(self.config.data_path, "juju-info.json"))])85 if not try_to_register:
86 # We don't need to further check the configuration if we are
87 # deleting it.
88 return 0
89
79 if is_configured_enough:90 if is_configured_enough:
80 return self.try_to_register()91 return self.try_to_register()
81 else:92 else:
@@ -83,6 +94,13 @@
83 " proceed, skipping")94 " proceed, skipping")
84 return 095 return 0
8596
97 @property
98 def juju_directory(self):
99 try:
100 return self.config.juju_directory
101 except AttributeError: # older landscape-client versions
102 return os.path.join(self.config.data_path, "juju-info.d")
103
86 def clear_registration(self):104 def clear_registration(self):
87 """105 """
88 Do steps necessary to clear the client registration, so that next time106 Do steps necessary to clear the client registration, so that next time
@@ -153,3 +171,7 @@
153 """Dump content in JSON format to the specified file."""171 """Dump content in JSON format to the specified file."""
154 with open(filename, "w") as dumpfile:172 with open(filename, "w") as dumpfile:
155 json.dump(content, dumpfile)173 json.dump(content, dumpfile)
174
175
176def get_juju_info_filenames(juju_directory):
177 return glob("%s/*.json" % juju_directory)
156178
=== modified file 'hooks/hooks.py'
--- hooks/hooks.py 2014-05-30 05:59:47 +0000
+++ hooks/hooks.py 2014-06-13 15:44:07 +0000
@@ -14,7 +14,9 @@
14from shutil import rmtree14from shutil import rmtree
15from subprocess import CalledProcessError15from subprocess import CalledProcessError
1616
17from common import write_json_file, JujuBroker, LandscapeBroker, chown17from common import (
18 write_json_file, JujuBroker, LandscapeBroker, chown,
19 get_juju_info_filenames)
18from ceph import (20from ceph import (
19 get_ceph_client_path, write_ceph_client_keyring, write_ceph_client_config)21 get_ceph_client_path, write_ceph_client_keyring, write_ceph_client_config)
2022
@@ -52,7 +54,7 @@
52 data_path])54 data_path])
5355
5456
55@hooks.hook("registration-relation-joined","registration-relation-changed")57@hooks.hook("registration-relation-joined", "registration-relation-changed")
56def registration_relation(juju_broker=JUJU_BROKER,58def registration_relation(juju_broker=JUJU_BROKER,
57 landscape_broker=LANDSCAPE_BROKER):59 landscape_broker=LANDSCAPE_BROKER):
58 data = juju_broker.get_relation_config()60 data = juju_broker.get_relation_config()
@@ -95,15 +97,28 @@
95 landscape_broker=LANDSCAPE_BROKER):97 landscape_broker=LANDSCAPE_BROKER):
96 landscape_broker.config.reload()98 landscape_broker.config.reload()
97 relation_conf = juju_broker.get_relation_config()99 relation_conf = juju_broker.get_relation_config()
100 remote_unit_name = juju_broker.environment.get("JUJU_REMOTE_UNIT")
98 # We use the remote unit for the unit name, since we want to associate this101 # We use the remote unit for the unit name, since we want to associate this
99 # client with the unit it's managing, not its own unit.102 # client with the unit it's managing, not its own unit.
100 juju_info = {103 juju_info = {
101 "environment-uuid": juju_broker.environment.get("JUJU_ENV_UUID"),104 "environment-uuid": juju_broker.environment.get("JUJU_ENV_UUID"),
102 "unit-name": juju_broker.environment.get("JUJU_REMOTE_UNIT"),105 "unit-name": remote_unit_name,
103 "api-addresses": juju_broker.environment.get("JUJU_API_ADDRESSES"),106 "api-addresses": juju_broker.environment.get("JUJU_API_ADDRESSES"),
104 "private-address": relation_conf.get("private-address")}107 "private-address": relation_conf.get("private-address")}
105 juju_info_file = os.path.join(108
106 landscape_broker.config.data_path, "juju-info.json")109 # Let's not use any "/" in a filename.
110 unit_name = remote_unit_name.replace("/", "-")
111 juju_file = "%s.json" % unit_name
112
113 juju_info_dir = landscape_broker.juju_directory
114
115 try:
116 os.mkdir(juju_info_dir)
117 except OSError:
118 pass # The file already exists.
119
120 juju_info_file = os.path.join(juju_info_dir, juju_file)
121
107 write_json_file(juju_info_file, juju_info)122 write_json_file(juju_info_file, juju_info)
108 exit_code = landscape_broker.update_client_config(123 exit_code = landscape_broker.update_client_config(
109 {"computer-title": socket.gethostname()})124 {"computer-title": socket.gethostname()})
@@ -119,12 +134,14 @@
119 computer title unset and the juju info file removed, so that we134 computer title unset and the juju info file removed, so that we
120 won't try to register again when the config-changed hook is fired.135 won't try to register again when the config-changed hook is fired.
121 """136 """
122 landscape_broker.clear_registration(),137 landscape_broker.clear_registration()
123 juju_info_path = os.path.join(138
124 landscape_broker.config.data_path, "juju-info.json")139 # Delete all of the juju-info files.
125 if os.path.exists(juju_info_path):140 files_to_delete = get_juju_info_filenames(landscape_broker.juju_directory)
126 os.remove(juju_info_path)141 for to_delete in files_to_delete:
127 landscape_broker.update_client_config({"computer-title": ""})142 os.remove(to_delete)
143 landscape_broker.update_client_config(
144 {"computer-title": ""}, try_to_register=False)
128145
129146
130@hooks.hook("ceph-client-relation-changed")147@hooks.hook("ceph-client-relation-changed")
131148
=== modified file 'hooks/test_hooks.py'
--- hooks/test_hooks.py 2014-05-30 05:59:47 +0000
+++ hooks/test_hooks.py 2014-06-13 15:44:07 +0000
@@ -5,6 +5,7 @@
5from tempfile import mkdtemp5from tempfile import mkdtemp
6from unittest import TestCase6from unittest import TestCase
7from uuid import uuid47from uuid import uuid4
8from glob import glob
89
9from landscape.deployment import Configuration10from landscape.deployment import Configuration
10from landscape.lib.fs import read_file11from landscape.lib.fs import read_file
@@ -59,6 +60,13 @@
59 self.landscape_broker.config.write()60 self.landscape_broker.config.write()
60 self.juju_broker = FakeJujuBroker()61 self.juju_broker = FakeJujuBroker()
6162
63 def touch_example_juju_info_file(self):
64 if not os.path.exists(self.landscape_broker.juju_directory):
65 os.mkdir(self.landscape_broker.juju_directory)
66 filename = os.path.join(self.landscape_broker.juju_directory,
67 "whatever.json")
68 write_json_file(filename=filename, content={})
69
62 def mkdtemp(self):70 def mkdtemp(self):
63 directory = mkdtemp(prefix=self.__class__.__name__)71 directory = mkdtemp(prefix=self.__class__.__name__)
64 self.addCleanup(rmtree, directory)72 self.addCleanup(rmtree, directory)
@@ -165,8 +173,10 @@
165 "private-address": "10.0.0.99"}173 "private-address": "10.0.0.99"}
166 hooks.container_relation_joined(juju_broker=self.juju_broker,174 hooks.container_relation_joined(juju_broker=self.juju_broker,
167 landscape_broker=self.landscape_broker)175 landscape_broker=self.landscape_broker)
176
168 juju_info_path = os.path.join(177 juju_info_path = os.path.join(
169 self.landscape_broker.config.data_path, "juju-info.json")178 self.landscape_broker.juju_directory, "unit-0.json")
179
170 juju_info = json.loads(read_file(juju_info_path))180 juju_info = json.loads(read_file(juju_info_path))
171 self.assertEqual(181 self.assertEqual(
172 {"environment-uuid": "uuid1",182 {"environment-uuid": "uuid1",
@@ -184,9 +194,10 @@
184 registration_attempts = []194 registration_attempts = []
185195
186 def record_registration_attempt():196 def record_registration_attempt():
187 juju_info_path = os.path.join(197 juju_directory = self.landscape_broker.juju_directory
188 self.landscape_broker.config.data_path, "juju-info.json")198 juju_file_list = glob("%s/*.json" % juju_directory)
189 registration_attempts.append(os.path.exists(juju_info_path))199 for _ in juju_file_list:
200 registration_attempts.append(True)
190201
191 self.landscape_broker.try_to_register = record_registration_attempt202 self.landscape_broker.try_to_register = record_registration_attempt
192 hooks.container_relation_joined(juju_broker=self.juju_broker,203 hooks.container_relation_joined(juju_broker=self.juju_broker,
@@ -199,7 +210,8 @@
199 The client adds the hostname as the "computer-title" field of the210 The client adds the hostname as the "computer-title" field of the
200 landscape broker config.211 landscape broker config.
201 """212 """
202 self.hooks.run("container-relation-joined")213 hooks.container_relation_joined(juju_broker=self.juju_broker,
214 landscape_broker=self.landscape_broker)
203 result = self.landscape_broker.config.computer_title215 result = self.landscape_broker.config.computer_title
204 self.assertEqual(result, socket.gethostname())216 self.assertEqual(result, socket.gethostname())
205217
@@ -234,7 +246,11 @@
234 now gone).246 now gone).
235 """247 """
236 juju_info_path = os.path.join(248 juju_info_path = os.path.join(
237 self.landscape_broker.config.data_path, "juju-info.json")249 self.landscape_broker.juju_directory, "unit-0.json")
250
251 if not os.path.exists(self.landscape_broker.juju_directory):
252 os.mkdir(self.landscape_broker.juju_directory)
253
238 juju_info = {"environment-uuid": "uuid1",254 juju_info = {"environment-uuid": "uuid1",
239 "unit-name": "unit/0",255 "unit-name": "unit/0",
240 "api-addresses": "10.0.0.1:1234",256 "api-addresses": "10.0.0.1:1234",
@@ -384,6 +400,9 @@
384400
385 def setUp(self):401 def setUp(self):
386 super(ConfigChangedTest, self).setUp()402 super(ConfigChangedTest, self).setUp()
403 self.landscape_broker.config.account_name = "account1"
404 self.landscape_broker.config.computer_title = "title"
405 self.touch_example_juju_info_file()
387 self.addCleanup(setattr, hooks, "CERT_FILE", hooks.CERT_FILE)406 self.addCleanup(setattr, hooks, "CERT_FILE", hooks.CERT_FILE)
388 tmp_dir = self.mkdtemp()407 tmp_dir = self.mkdtemp()
389 hooks.CERT_FILE = "%s/cert" % tmp_dir408 hooks.CERT_FILE = "%s/cert" % tmp_dir
@@ -410,6 +429,9 @@
410429
411 def setUp(self):430 def setUp(self):
412 super(RegistrationRelationJoinedTest, self).setUp()431 super(RegistrationRelationJoinedTest, self).setUp()
432 self.landscape_broker.config.account_name = "account1"
433 self.landscape_broker.config.computer_title = "title"
434 self.touch_example_juju_info_file()
413 self.addCleanup(setattr, hooks, "CERT_FILE", hooks.CERT_FILE)435 self.addCleanup(setattr, hooks, "CERT_FILE", hooks.CERT_FILE)
414 tmp_dir = self.mkdtemp()436 tmp_dir = self.mkdtemp()
415 hooks.CERT_FILE = "%s/cert" % tmp_dir437 hooks.CERT_FILE = "%s/cert" % tmp_dir

Subscribers

People subscribed via source and target branches