diff --git a/src/config.yaml b/src/config.yaml index c585659..e2b3fe5 100644 --- a/src/config.yaml +++ b/src/config.yaml @@ -51,4 +51,10 @@ options: type: string default: stable description: >- - The snap channel to install from. \ No newline at end of file + The snap channel to install from. + dns-ha-access-record: + type: string + default: + description: | + DNS record to use for DNS HA with MAAS. Do not use vip setting + if this is set. diff --git a/src/reactive/vault.py b/src/reactive/vault.py index eb01e34..3c246ec 100644 --- a/src/reactive/vault.py +++ b/src/reactive/vault.py @@ -16,6 +16,7 @@ from charmhelpers.contrib.charmsupport.nrpe import ( from charmhelpers.core.hookenv import ( DEBUG, + ERROR, config, log, open_port, @@ -404,6 +405,29 @@ def nagios_servicegroups_changed(): remove_state('vault.nrpe.configured') +@when('ha.connected') +def cluster_connected(hacluster): + """Configure HA resources in corosync""" + vip = config('vip') + dns_record = config('dns-ha-access-record') + if vip and dns_record: + set_flag('config.dns_vip.invalid') + log("Unsupported configuration. vip and dns-ha cannot both be set", + level=ERROR) + return + else: + clear_flag('config.dns_vip.invalid') + if vip: + hacluster.add_vip('vault', vip) + elif dns_record: + try: + ip = network_get_primary_address('access') + except NotImplementedError: + ip = unit_private_ip() + hacluster.add_dnsha('vault', ip, dns_record, 'access') + hacluster.bind_resources() + + @when('snap.installed.vault') def prime_assess_status(): atexit(_assess_status) @@ -492,14 +516,6 @@ def _assess_interface_groups(interfaces, optional, ) -@when('ha.connected') -def cluster_connected(hacluster): - """Configure HA resources in corosync""" - vip = config('vip') - hacluster.add_vip('vault', vip) - hacluster.bind_resources() - - def _assess_status(): """Assess status of relations and services for local unit""" if is_flag_set('snap.channel.invalid'): @@ -507,6 +523,10 @@ def _assess_status(): 'Invalid snap channel ' 'configured: {}'.format(config('channel'))) return + if is_flag_set('config.dns_vip.invalid'): + status_set('blocked', + 'vip and dns-ha-access-record configured') + return health = None if service_running('vault'): diff --git a/unit_tests/test_vault.py b/unit_tests/test_vault.py index 04105ba..f38a9a3 100644 --- a/unit_tests/test_vault.py +++ b/unit_tests/test_vault.py @@ -53,6 +53,7 @@ class TestHandlers(unittest.TestCase): 'endpoint_from_flag', 'is_state', 'log', + 'network_get_primary_address', 'open_port', 'service_restart', 'service_running', @@ -325,13 +326,6 @@ class TestHandlers(unittest.TestCase): self.assertEqual(handlers.get_cluster_url(), 'http://1.2.3.4:8201') self.network_get_primary_address.assert_called_with('cluster') - def test_cluster_connected(self): - self.config.return_value = '10.1.1.1' - hacluster_mock = mock.MagicMock() - handlers.cluster_connected(hacluster_mock) - hacluster_mock.add_vip.assert_called_once_with('vault', '10.1.1.1') - hacluster_mock.bind_resources.assert_called_once_with() - @patch.object(handlers, 'get_api_url') @patch.object(handlers, 'requests') def test_get_vault_health(self, requests, get_api_url): @@ -372,7 +366,10 @@ class TestHandlers(unittest.TestCase): ]) def test_assess_status_invalid_channel(self): - self.is_flag_set.return_value = True + statuses = { + 'snap.channel.invalid': True, + 'config.dns_vip.invalid': False} + self.is_flag_set.side_effect = lambda x: statuses[x] self.config.return_value = 'foorbar' handlers._assess_status() self.status_set.assert_called_with( @@ -380,6 +377,16 @@ class TestHandlers(unittest.TestCase): self.is_flag_set.assert_called_with('snap.channel.invalid') self.config.assert_called_with('channel') + def test_assess_status_invalid_haconfig(self): + statuses = { + 'snap.channel.invalid': False, + 'config.dns_vip.invalid': True} + self.is_flag_set.side_effect = lambda x: statuses[x] + handlers._assess_status() + self.status_set.assert_called_with( + 'blocked', 'vip and dns-ha-access-record configured') + self.is_flag_set.assert_called_with('config.dns_vip.invalid') + @patch.object(handlers, '_assess_interface_groups') @patch.object(handlers, 'get_vault_health') def test_assess_status_not_running(self, get_vault_health, @@ -498,3 +505,38 @@ class TestHandlers(unittest.TestCase): self.assertTrue(handlers.validate_snap_channel('candidate')) self.assertFalse(handlers.validate_snap_channel('foobar')) self.assertFalse(handlers.validate_snap_channel('0.10/foobar')) + + def test_cluster_connected_vip(self): + charm_config = { + 'vip': '10.1.1.1'} + self.config.side_effect = lambda x: charm_config.get(x) + hacluster_mock = mock.MagicMock() + handlers.cluster_connected(hacluster_mock) + hacluster_mock.add_vip.assert_called_once_with('vault', '10.1.1.1') + hacluster_mock.bind_resources.assert_called_once_with() + self.clear_flag.assert_called_once_with('config.dns_vip.invalid') + + def test_cluster_connected_dnsha(self): + charm_config = { + 'dns-ha-access-record': 'myrecord.mycopany.co.uk'} + self.config.side_effect = lambda x: charm_config.get(x) + self.network_get_primary_address.return_value = '10.1.100.1' + hacluster_mock = mock.MagicMock() + handlers.cluster_connected(hacluster_mock) + hacluster_mock.add_dnsha.assert_called_once_with( + 'vault', '10.1.100.1', 'myrecord.mycopany.co.uk', 'access') + hacluster_mock.bind_resources.assert_called_once_with() + self.clear_flag.assert_called_once_with('config.dns_vip.invalid') + + def test_cluster_connected_vip_and_dnsha(self): + charm_config = { + 'vip': '10.1.1.1', + 'dns-ha-access-record': 'myrecord.mycopany.co.uk'} + self.config.side_effect = lambda x: charm_config.get(x) + self.network_get_primary_address.return_value = '10.1.100.1' + hacluster_mock = mock.MagicMock() + handlers.cluster_connected(hacluster_mock) + self.assertFalse(hacluster_mock.add_vip.called) + self.assertFalse(hacluster_mock.add_dnsha.called) + self.assertFalse(hacluster_mock.bind_resources.called) + self.set_flag.assert_called_once_with('config.dns_vip.invalid')