# Copyright 2020 Canonical Ltd # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import mock from ovsdb_subordinate import provides import charms_openstack.test_utils as test_utils _hook_args = {} class TestOVSDBSubordinateProvides(test_utils.PatchHelper): def setUp(self): super().setUp() self.target = provides.OVSDBSubordinateProvides('some-relation', []) self._patches = {} self._patches_start = {} def tearDown(self): self.target = None for k, v in self._patches.items(): v.stop() setattr(self, k, None) self._patches = None self._patches_start = None def patch_target(self, attr, return_value=None): mocked = mock.patch.object(self.target, attr) self._patches[attr] = mocked started = mocked.start() started.return_value = return_value self._patches_start[attr] = started setattr(self, attr, started) def patch_topublish(self): self.patch_target('_relations') relation = mock.MagicMock() to_publish = mock.PropertyMock() type(relation).to_publish = to_publish self._relations.__iter__.return_value = [relation] return relation.to_publish def test__get_ovs_value(self): self.patch_object(provides.subprocess, 'run') cp = mock.MagicMock() cp.stdout = '"hostname-42"\n' self.run.return_value = cp self.assertEquals( self.target._get_ovs_value('tbl', 'col'), 'hostname-42') self.run.assert_called_once_with( ('ovs-vsctl', 'get', 'tbl', '.', 'col'), stdout=mock.ANY, check=True, universal_newlines=True) self.run.reset_mock() self.target._get_ovs_value('tbl', 'col', rec='rec') self.run.assert_called_once_with( ('ovs-vsctl', 'get', 'tbl', 'rec', 'col'), stdout=mock.ANY, check=True, universal_newlines=True) def test_publish_chassis_name(self): self.patch_target('_get_ovs_value') to_publish = self.patch_topublish() self._get_ovs_value.return_value = 'aHostname' self.target.publish_chassis_name() to_publish.__setitem__.assert_called_once_with( 'chassis-name', 'aHostname') def test_publish_ovn_configured(self): self.patch_object(provides, 'subprocess') self.subprocess.CalledProcessError = Exception self.patch_target('_get_ovs_value') to_publish = self.patch_topublish() self._get_ovs_value.side_effect = Exception self.target.publish_ovn_configured() to_publish.__setitem__.assert_called_once_with('ovn-configured', False) self._get_ovs_value.assert_called_once_with( 'Open_vSwitch', 'external_ids:ovn-remote') to_publish.__setitem__.reset_mock() self._get_ovs_value.side_effect = None self.target.publish_ovn_configured() to_publish.__setitem__.assert_called_once_with('ovn-configured', True) def test_interface_requests(self): self.patch_target('_all_joined_units') self._all_joined_units.received.get.return_value = 'fakereq' self.assertEquals( self.target.interface_requests, 'fakereq') def test_interface_requests_handled(self): self.patch_object(provides, 'hash_hexdigest') self.hash_hexdigest.return_value = 'fakehash' self.patch_target('_all_joined_units') self._all_joined_units.received_raw.__getitem__.return_value = 'ifreq' to_publish = self.patch_topublish() self.patch_object(provides.reactive, 'clear_flag') self.target.interface_requests_handled() self.hash_hexdigest.assert_called_once_with('ifreq') to_publish.__setitem__.assert_called_once_with( 'interfaces-created', 'fakehash') self.clear_flag.assert_called_once_with( 'some-relation.interfaces.new_requests') def test_joined(self): self.patch_target('publish_chassis_name') self.patch_target('publish_ovn_configured') self.patch_object(provides.reactive, 'set_flag') self.target.joined() self.publish_chassis_name.assert_called_once_with() self.publish_ovn_configured.assert_called_once_with() self.set_flag.assert_has_calls([ mock.call('some-relation.connected'), mock.call('some-relation.available'), ]) def test_broken(self): self.patch_object(provides.reactive, 'clear_flag') self.target.broken() self.clear_flag.assert_has_calls([ mock.call('some-relation.available'), mock.call('some-relation.connected'), ]) def test_new_requests(self): self.patch_object(provides.reactive, 'set_flag') self.patch_object(provides.reactive, 'clear_flag') self.target.new_requests() self.set_flag.assert_called_once_with( 'some-relation.interfaces.new_requests') self.clear_flag.assert_called_once_with( 'endpoint.some-relation.changed.create-interfaces') def test_publish_chassis_certificates(self): to_publish = self.patch_topublish() self.target.publish_chassis_certificates('a', 'b', 'c') to_publish.__setitem__.assert_called_once_with( 'chassis-certificates', { 'ca_cert': 'a', 'certificate': 'b', 'private_key': 'c', })