Merge lp:~hopem/charm-helpers/fix-lp1425999 into lp:charm-helpers

Proposed by Edward Hope-Morley
Status: Merged
Merged at revision: 327
Proposed branch: lp:~hopem/charm-helpers/fix-lp1425999
Merge into: lp:charm-helpers
Diff against target: 168 lines (+65/-15)
2 files modified
charmhelpers/contrib/database/mysql.py (+17/-12)
tests/contrib/database/test_mysql.py (+48/-3)
To merge this branch: bzr merge lp:~hopem/charm-helpers/fix-lp1425999
Reviewer Review Type Date Requested Status
Jorge Niedbalski (community) Approve
Review via email: mp+251158@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Jorge Niedbalski (niedbalski) wrote :

Hello Edward.

I found out that there is a few other places on which similar host<->ip logic
is being used. I just re-factored/moved this to the contrib.network.ip module, which
in my opinion is a better place for having this.

The proposal: https://code.launchpad.net/~niedbalski/charm-helpers/ip-host-translation/+merge/251189

I would suggest to review that and integrate your code according to the inline comment.

review: Needs Fixing
325. By Edward Hope-Morley

sync trunk

326. By Edward Hope-Morley

switch to ip.get_host_ip()

Revision history for this message
Edward Hope-Morley (hopem) wrote :

@jorge Fixed.

Revision history for this message
Jorge Niedbalski (niedbalski) wrote :

Hello Ed,

I fixed a few lint errors:

charmhelpers/contrib/database/mysql.py:3:1: F401 'socket' imported but unused
charmhelpers/contrib/database/mysql.py:17:1: F401 'WARNING' imported but unused
tests/contrib/database/test_mysql.py:72:66: W291 trailing whitespace

Merged.

Revision history for this message
Jorge Niedbalski (niedbalski) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'charmhelpers/contrib/database/mysql.py'
--- charmhelpers/contrib/database/mysql.py 2015-02-26 16:05:44 +0000
+++ charmhelpers/contrib/database/mysql.py 2015-02-27 10:03:09 +0000
@@ -15,14 +15,15 @@
15 write_file15 write_file
16)16)
17from charmhelpers.core.hookenv import (17from charmhelpers.core.hookenv import (
18 config as config_get,
18 relation_get,19 relation_get,
19 related_units,20 related_units,
20 unit_get,21 unit_get,
21 log,22 log,
22 DEBUG,23 DEBUG,
23 INFO,24 INFO,
25 WARNING,
24)26)
25from charmhelpers.core.hookenv import config as config_get
26from charmhelpers.fetch import (27from charmhelpers.fetch import (
27 apt_install,28 apt_install,
28 apt_update,29 apt_update,
@@ -32,6 +33,7 @@
32 peer_store,33 peer_store,
33 peer_retrieve,34 peer_retrieve,
34)35)
36from charmhelpers.contrib.network.ip import get_host_ip
3537
36try:38try:
37 import MySQLdb39 import MySQLdb
@@ -220,6 +222,18 @@
220 """Retrieve or generate mysql root password for service units."""222 """Retrieve or generate mysql root password for service units."""
221 return self.get_mysql_password(username=None, password=password)223 return self.get_mysql_password(username=None, password=password)
222224
225 def normalize_address(self, hostname):
226 """Ensure that address returned is an IP address (i.e. not fqdn)"""
227 if config_get('prefer-ipv6'):
228 # TODO: add support for ipv6 dns
229 return hostname
230
231 if hostname != unit_get('private-address'):
232 return get_host_ip(hostname, fallback=hostname)
233
234 # Otherwise assume localhost
235 return '127.0.0.1'
236
223 def get_allowed_units(self, database, username, relation_id=None):237 def get_allowed_units(self, database, username, relation_id=None):
224 """Get list of units with access grants for database with username.238 """Get list of units with access grants for database with username.
225239
@@ -247,6 +261,7 @@
247261
248 if hosts:262 if hosts:
249 for host in hosts:263 for host in hosts:
264 host = self.normalize_address(host)
250 if self.grant_exists(database, username, host):265 if self.grant_exists(database, username, host):
251 log("Grant exists for host '%s' on db '%s'" %266 log("Grant exists for host '%s' on db '%s'" %
252 (host, database), level=DEBUG)267 (host, database), level=DEBUG)
@@ -262,21 +277,11 @@
262277
263 def configure_db(self, hostname, database, username, admin=False):278 def configure_db(self, hostname, database, username, admin=False):
264 """Configure access to database for username from hostname."""279 """Configure access to database for username from hostname."""
265 if config_get('prefer-ipv6'):
266 remote_ip = hostname
267 elif hostname != unit_get('private-address'):
268 try:
269 remote_ip = socket.gethostbyname(hostname)
270 except Exception:
271 # socket.gethostbyname doesn't support ipv6
272 remote_ip = hostname
273 else:
274 remote_ip = '127.0.0.1'
275
276 self.connect(password=self.get_mysql_root_password())280 self.connect(password=self.get_mysql_root_password())
277 if not self.database_exists(database):281 if not self.database_exists(database):
278 self.create_database(database)282 self.create_database(database)
279283
284 remote_ip = self.normalize_address(hostname)
280 password = self.get_mysql_password(username)285 password = self.get_mysql_password(username)
281 if not self.grant_exists(database, username, remote_ip):286 if not self.grant_exists(database, username, remote_ip):
282 if not admin:287 if not admin:
283288
=== modified file 'tests/contrib/database/test_mysql.py'
--- tests/contrib/database/test_mysql.py 2015-02-25 19:15:53 +0000
+++ tests/contrib/database/test_mysql.py 2015-02-27 10:03:09 +0000
@@ -11,6 +11,7 @@
11 def setUp(self):11 def setUp(self):
12 super(MysqlTests, self).setUp()12 super(MysqlTests, self).setUp()
1313
14 @mock.patch.object(mysql.MySQLHelper, 'normalize_address')
14 @mock.patch.object(mysql.MySQLHelper, 'get_mysql_password')15 @mock.patch.object(mysql.MySQLHelper, 'get_mysql_password')
15 @mock.patch.object(mysql.MySQLHelper, 'grant_exists')16 @mock.patch.object(mysql.MySQLHelper, 'grant_exists')
16 @mock.patch.object(mysql, 'relation_get')17 @mock.patch.object(mysql, 'relation_get')
@@ -19,7 +20,11 @@
19 def test_get_allowed_units(self, mock_log, mock_related_units,20 def test_get_allowed_units(self, mock_log, mock_related_units,
20 mock_relation_get,21 mock_relation_get,
21 mock_grant_exists,22 mock_grant_exists,
22 mock_get_password):23 mock_get_password,
24 mock_normalize_address):
25
26 # echo
27 mock_normalize_address.side_effect = lambda addr: addr
2328
24 def mock_rel_get(unit, rid):29 def mock_rel_get(unit, rid):
25 if unit == 'unit/0':30 if unit == 'unit/0':
@@ -54,6 +59,44 @@
54 helper.grant_exists.assert_has_calls(calls)59 helper.grant_exists.assert_has_calls(calls)
55 self.assertEqual(units, set(['unit/0', 'unit/1', 'unit/2']))60 self.assertEqual(units, set(['unit/0', 'unit/1', 'unit/2']))
5661
62 @mock.patch('charmhelpers.contrib.network.ip.socket')
63 @mock.patch.object(mysql, 'unit_get')
64 @mock.patch.object(mysql, 'config_get')
65 @mock.patch.object(mysql, 'log')
66 def test_normalize_address(self, mock_log, mock_config_get, mock_unit_get,
67 mock_socket):
68 helper = mysql.MySQLHelper('foo', 'bar', host='hostA')
69 # prefer-ipv6
70 mock_config_get.return_value = False
71 # echo
72 mock_socket.gethostbyname.side_effect = lambda addr: addr
73
74 mock_unit_get.return_value = '10.0.0.1'
75 out = helper.normalize_address('10.0.0.1')
76 self.assertEqual('127.0.0.1', out)
77 mock_config_get.assert_called_with('prefer-ipv6')
78
79 mock_unit_get.return_value = '10.0.0.1'
80 out = helper.normalize_address('10.0.0.2')
81 self.assertEqual('10.0.0.2', out)
82 mock_config_get.assert_called_with('prefer-ipv6')
83
84 out = helper.normalize_address('2001:db8:1::1')
85 self.assertEqual('2001:db8:1::1', out)
86 mock_config_get.assert_called_with('prefer-ipv6')
87
88 mock_socket.gethostbyname.side_effect = Exception
89 out = helper.normalize_address('unresolvable')
90 self.assertEqual('unresolvable', out)
91 mock_config_get.assert_called_with('prefer-ipv6')
92
93 # prefer-ipv6
94 mock_config_get.return_value = True
95 mock_socket.gethostbyname.side_effect = 'other'
96 out = helper.normalize_address('unresolvable')
97 self.assertEqual('unresolvable', out)
98 mock_config_get.assert_called_with('prefer-ipv6')
99
57100
58class PerconaTests(unittest.TestCase):101class PerconaTests(unittest.TestCase):
59102
@@ -62,7 +105,8 @@
62105
63 @mock.patch.object(mysql.PerconaClusterHelper, 'get_mem_total')106 @mock.patch.object(mysql.PerconaClusterHelper, 'get_mem_total')
64 @mock.patch.object(mysql, 'config_get')107 @mock.patch.object(mysql, 'config_get')
65 def test_parse_config_innodb_pool_fixed(self, config, mem):108 @mock.patch.object(mysql, 'log')
109 def test_parse_config_innodb_pool_fixed(self, log, config, mem):
66 mem.return_value = "100G"110 mem.return_value = "100G"
67 config.return_value = {111 config.return_value = {
68 'innodb-buffer-pool-size': "50%",112 'innodb-buffer-pool-size': "50%",
@@ -76,7 +120,8 @@
76120
77 @mock.patch.object(mysql.PerconaClusterHelper, 'get_mem_total')121 @mock.patch.object(mysql.PerconaClusterHelper, 'get_mem_total')
78 @mock.patch.object(mysql, 'config_get')122 @mock.patch.object(mysql, 'config_get')
79 def test_parse_config_innodb_pool_not_set(self, config, mem):123 @mock.patch.object(mysql, 'log')
124 def test_parse_config_innodb_pool_not_set(self, mog, config, mem):
80 mem.return_value = "100G"125 mem.return_value = "100G"
81 config.return_value = {126 config.return_value = {
82 'innodb-buffer-pool-size': '',127 'innodb-buffer-pool-size': '',

Subscribers

People subscribed via source and target branches