Merge lp:~billy-olsen/charms/trusty/neutron-api/public-endpoint-host into lp:~openstack-charmers-archive/charms/trusty/neutron-api/next

Proposed by Billy Olsen
Status: Merged
Merged at revision: 118
Proposed branch: lp:~billy-olsen/charms/trusty/neutron-api/public-endpoint-host
Merge into: lp:~openstack-charmers-archive/charms/trusty/neutron-api/next
Diff against target: 259 lines (+98/-51)
3 files modified
config.yaml (+12/-0)
hooks/charmhelpers/contrib/openstack/ip.py (+49/-44)
unit_tests/test_neutron_api_hooks.py (+37/-7)
To merge this branch: bzr merge lp:~billy-olsen/charms/trusty/neutron-api/public-endpoint-host
Reviewer Review Type Date Requested Status
Corey Bryant Approve
Review via email: mp+261007@code.launchpad.net

Description of the change

Provides a config option which allows the user to specify the public hostname used to advertise to keystone when creating endpoints.

To post a comment you must log in.
Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #5045 neutron-api-next for billy-olsen mp261007
    LINT OK: passed

Build: http://10.245.162.77:8080/job/charm_lint_check/5045/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #4725 neutron-api-next for billy-olsen mp261007
    UNIT OK: passed

Build: http://10.245.162.77:8080/job/charm_unit_test/4725/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_amulet_test #4451 neutron-api-next for billy-olsen mp261007
    AMULET OK: passed

Build: http://10.245.162.77:8080/job/charm_amulet_test/4451/

117. By Billy Olsen

merge with /next

118. By Billy Olsen

c-h sync

119. By Billy Olsen

Fix unit test error from c-h sync

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #5069 neutron-api-next for billy-olsen mp261007
    LINT OK: passed

Build: http://10.245.162.77:8080/job/charm_lint_check/5069/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #4748 neutron-api-next for billy-olsen mp261007
    UNIT OK: passed

Build: http://10.245.162.77:8080/job/charm_unit_test/4748/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_amulet_test #4476 neutron-api-next for billy-olsen mp261007
    AMULET OK: passed

Build: http://10.245.162.77:8080/job/charm_amulet_test/4476/

Revision history for this message
Corey Bryant (corey.bryant) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'config.yaml'
2--- config.yaml 2015-05-21 15:02:07 +0000
3+++ config.yaml 2015-06-04 23:28:32 +0000
4@@ -235,6 +235,18 @@
5 192.168.0.0/24)
6 .
7 This network will be used for public endpoints.
8+ os-public-hostname:
9+ type: string
10+ default:
11+ description: |
12+ The hostname or address of the public endpoints created for neutron-api
13+ in the keystone identity provider.
14+ .
15+ This value will be used for public endpoints. For example, an
16+ os-public-hostname set to 'neutron-api.example.com' with ssl enabled
17+ will create the following endpoint for neutron-api:
18+ .
19+ https://neutron-api.example.com:9696/
20 ssl_cert:
21 type: string
22 default:
23
24=== modified file 'hooks/charmhelpers/contrib/openstack/ip.py'
25--- hooks/charmhelpers/contrib/openstack/ip.py 2015-03-16 14:16:02 +0000
26+++ hooks/charmhelpers/contrib/openstack/ip.py 2015-06-04 23:28:32 +0000
27@@ -17,6 +17,7 @@
28 from charmhelpers.core.hookenv import (
29 config,
30 unit_get,
31+ service_name,
32 )
33 from charmhelpers.contrib.network.ip import (
34 get_address_in_network,
35@@ -26,8 +27,6 @@
36 )
37 from charmhelpers.contrib.hahelpers.cluster import is_clustered
38
39-from functools import partial
40-
41 PUBLIC = 'public'
42 INTERNAL = 'int'
43 ADMIN = 'admin'
44@@ -35,15 +34,18 @@
45 ADDRESS_MAP = {
46 PUBLIC: {
47 'config': 'os-public-network',
48- 'fallback': 'public-address'
49+ 'fallback': 'public-address',
50+ 'override': 'os-public-hostname',
51 },
52 INTERNAL: {
53 'config': 'os-internal-network',
54- 'fallback': 'private-address'
55+ 'fallback': 'private-address',
56+ 'override': 'os-internal-hostname',
57 },
58 ADMIN: {
59 'config': 'os-admin-network',
60- 'fallback': 'private-address'
61+ 'fallback': 'private-address',
62+ 'override': 'os-admin-hostname',
63 }
64 }
65
66@@ -57,15 +59,50 @@
67 :param endpoint_type: str endpoint type to resolve.
68 :param returns: str base URL for services on the current service unit.
69 """
70- scheme = 'http'
71- if 'https' in configs.complete_contexts():
72- scheme = 'https'
73+ scheme = _get_scheme(configs)
74+
75 address = resolve_address(endpoint_type)
76 if is_ipv6(address):
77 address = "[{}]".format(address)
78+
79 return '%s://%s' % (scheme, address)
80
81
82+def _get_scheme(configs):
83+ """Returns the scheme to use for the url (either http or https)
84+ depending upon whether https is in the configs value.
85+
86+ :param configs: OSTemplateRenderer config templating object to inspect
87+ for a complete https context.
88+ :returns: either 'http' or 'https' depending on whether https is
89+ configured within the configs context.
90+ """
91+ scheme = 'http'
92+ if configs and 'https' in configs.complete_contexts():
93+ scheme = 'https'
94+ return scheme
95+
96+
97+def _get_address_override(endpoint_type=PUBLIC):
98+ """Returns any address overrides that the user has defined based on the
99+ endpoint type.
100+
101+ Note: this function allows for the service name to be inserted into the
102+ address if the user specifies {service_name}.somehost.org.
103+
104+ :param endpoint_type: the type of endpoint to retrieve the override
105+ value for.
106+ :returns: any endpoint address or hostname that the user has overridden
107+ or None if an override is not present.
108+ """
109+ override_key = ADDRESS_MAP[endpoint_type]['override']
110+ addr_override = config(override_key)
111+ if not addr_override:
112+ return None
113+ else:
114+ return addr_override.format(service_name=service_name())
115+
116+
117 def resolve_address(endpoint_type=PUBLIC):
118 """Return unit address depending on net config.
119
120@@ -77,7 +114,10 @@
121
122 :param endpoint_type: Network endpoing type
123 """
124- resolved_address = None
125+ resolved_address = _get_address_override(endpoint_type)
126+ if resolved_address:
127+ return resolved_address
128+
129 vips = config('vip')
130 if vips:
131 vips = vips.split()
132@@ -109,38 +149,3 @@
133 "clustered=%s)" % (net_type, clustered))
134
135 return resolved_address
136-
137-
138-def endpoint_url(configs, url_template, port, endpoint_type=PUBLIC,
139- override=None):
140- """Returns the correct endpoint URL to advertise to Keystone.
141-
142- This method provides the correct endpoint URL which should be advertised to
143- the keystone charm for endpoint creation. This method allows for the url to
144- be overridden to force a keystone endpoint to have specific URL for any of
145- the defined scopes (admin, internal, public).
146-
147- :param configs: OSTemplateRenderer config templating object to inspect
148- for a complete https context.
149- :param url_template: str format string for creating the url template. Only
150- two values will be passed - the scheme+hostname
151- returned by the canonical_url and the port.
152- :param endpoint_type: str endpoint type to resolve.
153- :param override: str the name of the config option which overrides the
154- endpoint URL defined by the charm itself. None will
155- disable any overrides (default).
156- """
157- if override:
158- # Return any user-defined overrides for the keystone endpoint URL.
159- user_value = config(override)
160- if user_value:
161- return user_value.strip()
162-
163- return url_template % (canonical_url(configs, endpoint_type), port)
164-
165-
166-public_endpoint = partial(endpoint_url, endpoint_type=PUBLIC)
167-
168-internal_endpoint = partial(endpoint_url, endpoint_type=INTERNAL)
169-
170-admin_endpoint = partial(endpoint_url, endpoint_type=ADMIN)
171
172=== modified file 'unit_tests/test_neutron_api_hooks.py'
173--- unit_tests/test_neutron_api_hooks.py 2015-04-23 08:49:03 +0000
174+++ unit_tests/test_neutron_api_hooks.py 2015-06-04 23:28:32 +0000
175@@ -25,7 +25,6 @@
176 'api_port',
177 'apt_update',
178 'apt_install',
179- 'canonical_url',
180 'config',
181 'CONFIGS',
182 'check_call',
183@@ -319,8 +318,9 @@
184 self._call_hook('amqp-relation-broken')
185 self.assertTrue(self.CONFIGS.write_all.called)
186
187- def test_identity_joined(self):
188- self.canonical_url.return_value = 'http://127.0.0.1'
189+ @patch.object(hooks, 'canonical_url')
190+ def test_identity_joined(self, _canonical_url):
191+ _canonical_url.return_value = 'http://127.0.0.1'
192 self.api_port.return_value = '9696'
193 self.test_config.set('region', 'region1')
194 _neutron_url = 'http://127.0.0.1:9696'
195@@ -337,6 +337,34 @@
196 relation_settings=_endpoints
197 )
198
199+ @patch('charmhelpers.contrib.openstack.ip.service_name',
200+ lambda *args: 'neutron-api')
201+ @patch('charmhelpers.contrib.openstack.ip.unit_get')
202+ @patch('charmhelpers.contrib.openstack.ip.is_clustered')
203+ @patch('charmhelpers.contrib.openstack.ip.config')
204+ def test_identity_changed_public_name(self, _config, _is_clustered,
205+ _unit_get):
206+ _unit_get.return_value = '127.0.0.1'
207+ _is_clustered.return_value = False
208+ _config.side_effect = self.test_config.get
209+ self.api_port.return_value = '9696'
210+ self.test_config.set('region', 'region1')
211+ self.test_config.set('os-public-hostname',
212+ 'neutron-api.example.com')
213+ self._call_hook('identity-service-relation-joined')
214+ _neutron_url = 'http://127.0.0.1:9696'
215+ _endpoints = {
216+ 'quantum_service': 'quantum',
217+ 'quantum_region': 'region1',
218+ 'quantum_public_url': 'http://neutron-api.example.com:9696',
219+ 'quantum_admin_url': _neutron_url,
220+ 'quantum_internal_url': _neutron_url,
221+ }
222+ self.relation_set.assert_called_with(
223+ relation_id=None,
224+ relation_settings=_endpoints
225+ )
226+
227 def test_identity_changed_partial_ctxt(self):
228 self.CONFIGS.complete_contexts.return_value = []
229 _api_rel_joined = self.patch('neutron_api_relation_joined')
230@@ -353,12 +381,13 @@
231 self.assertTrue(self.CONFIGS.write.called_with(NEUTRON_CONF))
232 self.assertTrue(_api_rel_joined.called)
233
234- def test_neutron_api_relation_no_id_joined(self):
235+ @patch.object(hooks, 'canonical_url')
236+ def test_neutron_api_relation_no_id_joined(self, _canonical_url):
237 host = 'http://127.0.0.1'
238 port = 1234
239 _id_rel_joined = self.patch('identity_joined')
240 self.relation_ids.side_effect = self._fake_relids
241- self.canonical_url.return_value = host
242+ _canonical_url.return_value = host
243 self.api_port.return_value = port
244 self.is_relation_made = False
245 neutron_url = '%s:%s' % (host, port)
246@@ -381,10 +410,11 @@
247 **_relation_data
248 )
249
250- def test_neutron_api_relation_joined(self):
251+ @patch.object(hooks, 'canonical_url')
252+ def test_neutron_api_relation_joined(self, _canonical_url):
253 host = 'http://127.0.0.1'
254 port = 1234
255- self.canonical_url.return_value = host
256+ _canonical_url.return_value = host
257 self.api_port.return_value = port
258 self.is_relation_made = True
259 neutron_url = '%s:%s' % (host, port)

Subscribers

People subscribed via source and target branches