diff --git a/.pylintrc b/.pylintrc index ea357cb..5558bfe 100644 --- a/.pylintrc +++ b/.pylintrc @@ -373,7 +373,7 @@ max-args=15 ignored-argument-names=_.* # Maximum number of locals for function / method body -max-locals=15 +max-locals=20 # Maximum number of return / yield for function / method body max-returns=6 diff --git a/hnv/client.py b/hnv/client.py index 774d8be..bdcad06 100644 --- a/hnv/client.py +++ b/hnv/client.py @@ -119,6 +119,22 @@ class _BaseHNVModel(model.Model): # Lock the current model self._provision_done = True + def is_ready(self): + """Check if the current model is ready to be used.""" + if not self.provisioning_state: + raise exception.ServiceException("The object doesn't contain " + "`provisioningState`.") + elif self.provisioning_state == constant.FAILED: + raise exception.ServiceException( + "Failed to complete the required operation.") + elif self.provisioning_state == constant.SUCCEEDED: + LOG.debug("The model %s: %s was successfully updated " + "(or created).", + self.__class__.__name__, self.resource_id) + return True + + return False + @staticmethod def _get_client(): """Create a new client for the HNV REST API.""" @@ -212,8 +228,13 @@ class _BaseHNVModel(model.Model): elapsed_time = 0 while wait: try: - client.get_resource(endpoint) + resource = cls._get(resource_id=resource_id, + parent_id=parent_id, + grandparent_id=grandparent_id) + resource.is_ready() + LOG.debug("The resource is still available. %r", resource) except exception.NotFound: + LOG.debug("The resource was successfully removed.") break elapsed_time += CONFIG.HNV.retry_interval @@ -248,9 +269,12 @@ class _BaseHNVModel(model.Model): in that case). """ if not self._changes: + LOG.debug("No changes available for %s: %s", + self.__class__.__name__, self.resource_id) return - super(_BaseHNVModel, self).commit(wait=wait, timeout=timeout) + LOG.debug("Apply all the changes on the current %s: %s", + self.__class__.__name__, self.resource_id) client = self._get_client() endpoint = self._endpoint.format( resource_id=self.resource_id or "", @@ -263,15 +287,8 @@ class _BaseHNVModel(model.Model): elapsed_time = 0 while wait: self.refresh() # Update the representation of the current model - if not self.provisioning_state: - raise exception.ServiceException("The object doesn't contain " - "`provisioningState`.") - elif self.provisioning_state == constant.FAILED: - raise exception.ServiceException( - "Failed to complete the required operation.") - elif self.provisioning_state == constant.SUCCEEDED: + if self.is_ready(): break - elapsed_time += CONFIG.HNV.retry_interval if timeout and elapsed_time > timeout: raise exception.TimeOut("The request timed out.") @@ -286,7 +303,7 @@ class _BaseHNVModel(model.Model): return self @classmethod - def from_raw_data(cls, raw_data): + def process_raw_data(cls, raw_data): """Create a new model using raw API response.""" properties = raw_data.get("properties", {}) @@ -300,7 +317,7 @@ class _BaseHNVModel(model.Model): configuration = ConfigurationState.from_raw_data(raw_state) properties["configurationState"] = configuration - return super(_BaseHNVModel, cls).from_raw_data(raw_data) + return super(_BaseHNVModel, cls).process_raw_data(raw_data) def _set_fields(self, fields): """Set or update the fields value.""" @@ -522,7 +539,7 @@ class LogicalSubnetworks(_BaseHNVModel): administrator portal.""" @classmethod - def from_raw_data(cls, raw_data): + def process_raw_data(cls, raw_data): """Create a new model using raw API response.""" properties = raw_data["properties"] @@ -545,7 +562,7 @@ class LogicalSubnetworks(_BaseHNVModel): network_interfaces.append(resource) properties["networkInterfaces"] = network_interfaces - return super(LogicalSubnetworks, cls).from_raw_data(raw_data) + return super(LogicalSubnetworks, cls).process_raw_data(raw_data) class LogicalNetworks(_BaseHNVModel): @@ -577,7 +594,7 @@ class LogicalNetworks(_BaseHNVModel): the network.""" @classmethod - def from_raw_data(cls, raw_data): + def process_raw_data(cls, raw_data): """Create a new model using raw API response.""" properties = raw_data["properties"] @@ -592,7 +609,7 @@ class LogicalNetworks(_BaseHNVModel): virtual_networks.append(Resource.from_raw_data(raw_network)) properties["virtualNetworks"] = virtual_networks - return super(LogicalNetworks, cls).from_raw_data(raw_data) + return super(LogicalNetworks, cls).process_raw_data(raw_data) class IPConfiguration(_BaseHNVModel): @@ -659,7 +676,7 @@ class IPConfiguration(_BaseHNVModel): is connected to.""" @classmethod - def from_raw_data(cls, raw_data): + def process_raw_data(cls, raw_data): """Create a new model using raw API response.""" properties = raw_data["properties"] @@ -690,7 +707,7 @@ class IPConfiguration(_BaseHNVModel): resource = Resource.from_raw_data(raw_content) properties["subnet"] = resource - return super(IPConfiguration, cls).from_raw_data(raw_data) + return super(IPConfiguration, cls).process_raw_data(raw_data) class DNSSettings(model.Model): @@ -791,12 +808,12 @@ class PortSettings(model.Model): is_required=False, is_property=False) @classmethod - def from_raw_data(cls, raw_data): + def process_raw_data(cls, raw_data): """Create a new model using raw API response.""" raw_settings = raw_data.get("qosSettings", {}) qos_settings = QosSettings.from_raw_data(raw_settings) raw_data["qosSettings"] = qos_settings - return super(PortSettings, cls).from_raw_data(raw_data) + return super(PortSettings, cls).process_raw_data(raw_data) class ConfigurationState(model.Model): @@ -883,7 +900,7 @@ class NetworkInterfaces(_BaseHNVModel): this networkInterfaces resource is part of.""" @classmethod - def from_raw_data(cls, raw_data): + def process_raw_data(cls, raw_data): """Create a new model using raw API response.""" properties = raw_data["properties"] @@ -903,7 +920,7 @@ class NetworkInterfaces(_BaseHNVModel): port_settings = PortSettings.from_raw_data(raw_settings) properties["portSettings"] = port_settings - return super(NetworkInterfaces, cls).from_raw_data(raw_data) + return super(NetworkInterfaces, cls).process_raw_data(raw_data) class SubNetworks(_BaseHNVModel): @@ -959,7 +976,7 @@ class SubNetworks(_BaseHNVModel): are connected to the subnet.""" @classmethod - def from_raw_data(cls, raw_data): + def process_raw_data(cls, raw_data): """Create a new model using raw API response.""" properties = raw_data["properties"] @@ -984,7 +1001,7 @@ class SubNetworks(_BaseHNVModel): ip_configurations.append(Resource.from_raw_data(raw_config)) properties["ipConfigurations"] = ip_configurations - return super(SubNetworks, cls).from_raw_data(raw_data) + return super(SubNetworks, cls).process_raw_data(raw_data) class DHCPOptions(model.Model): @@ -1051,7 +1068,7 @@ class VirtualNetworks(_BaseHNVModel): underlay network which the virtual network runs on.""" @classmethod - def from_raw_data(cls, raw_data): + def process_raw_data(cls, raw_data): """Create a new model using raw API response.""" properties = raw_data["properties"] @@ -1075,7 +1092,7 @@ class VirtualNetworks(_BaseHNVModel): subnetworks.append(SubNetworks.from_raw_data(raw_subnet)) properties["subnets"] = subnetworks - return super(VirtualNetworks, cls).from_raw_data(raw_data) + return super(VirtualNetworks, cls).process_raw_data(raw_data) class ACLRules(_BaseHNVModel): @@ -1198,10 +1215,16 @@ class AccessControlLists(_BaseHNVModel): control list is associated with.""" @classmethod - def from_raw_data(cls, raw_data): + def process_raw_data(cls, raw_data): """Create a new model using raw API response.""" properties = raw_data["properties"] + ip_configurations = [] + for raw_content in properties.get("ipConfigurations", []): + resource = Resource.from_raw_data(raw_content) + ip_configurations.append(resource) + properties["ipConfigurations"] = ip_configurations + subnetworks = [] for raw_subnet in properties.get("subnets", []): subnetworks.append(Resource.from_raw_data(raw_subnet)) @@ -1213,7 +1236,7 @@ class AccessControlLists(_BaseHNVModel): acl_rules.append(ACLRules.from_raw_data(raw_rule)) properties["aclRules"] = acl_rules - return super(AccessControlLists, cls).from_raw_data(raw_data) + return super(AccessControlLists, cls).process_raw_data(raw_data) class VirtualSwtichQosSettings(model.Model): @@ -1284,13 +1307,13 @@ class VirtualSwitchManager(_BaseHNVModel): return cls._get(resource_id, parent_id, grandparent_id) @classmethod - def from_raw_data(cls, raw_data): + def process_raw_data(cls, raw_data): """Create a new model using raw API response.""" properties = raw_data["properties"] qos_settings = properties.get("qosSettings", {}) properties["qosSettings"] = VirtualSwtichQosSettings.from_raw_data( raw_data=qos_settings) - return super(VirtualSwitchManager, cls).from_raw_data(raw_data) + return super(VirtualSwitchManager, cls).process_raw_data(raw_data) @classmethod def remove(cls, resource_id, parent_id=None, grandparent_id=None, @@ -1369,7 +1392,7 @@ class RouteTables(_BaseHNVModel): table is associated with.""" @classmethod - def from_raw_data(cls, raw_data): + def process_raw_data(cls, raw_data): """Create a new model using raw API response.""" properties = raw_data["properties"] @@ -1386,7 +1409,7 @@ class RouteTables(_BaseHNVModel): subnets.append(Resource.from_raw_data(raw_subnet)) properties["subnets"] = subnets - return super(RouteTables, cls).from_raw_data(raw_data) + return super(RouteTables, cls).process_raw_data(raw_data) class MainMode(model.Model): @@ -1566,7 +1589,7 @@ class IPSecConfiguration(model.Model): """Indicates collection of IPsec TrafficSelectors on the tenant side.""" @classmethod - def from_raw_data(cls, raw_data): + def process_raw_data(cls, raw_data): """Create a new model using raw API response.""" raw_main = raw_data.get("mainMode", None) if raw_main is not None: @@ -1590,7 +1613,7 @@ class IPSecConfiguration(model.Model): raw_remote_vpn)) raw_data["remoteVpnTrafficSelector"] = remote_vpn_ts - return super(IPSecConfiguration, cls).from_raw_data(raw_data) + return super(IPSecConfiguration, cls).process_raw_data(raw_data) class IPAddress(model.Model): @@ -1836,7 +1859,7 @@ class NetworkConnections(_BaseHNVModel): is_required=False, is_read_only=False) @classmethod - def from_raw_data(cls, raw_data): + def process_raw_data(cls, raw_data): """Create a new model using raw API response.""" properties = raw_data.get("properties", {}) @@ -1876,7 +1899,7 @@ class NetworkConnections(_BaseHNVModel): gateway = Resource.from_raw_data(raw_content) properties["gateway"] = gateway - return super(NetworkConnections, cls).from_raw_data(raw_data) + return super(NetworkConnections, cls).process_raw_data(raw_data) class PublicIPAddresses(_BaseHNVModel): @@ -1938,7 +1961,7 @@ class PublicIPAddresses(_BaseHNVModel): """ @classmethod - def from_raw_data(cls, raw_data): + def process_raw_data(cls, raw_data): """Create a new model using raw API response.""" properties = raw_data.get("properties", {}) @@ -1947,7 +1970,7 @@ class PublicIPAddresses(_BaseHNVModel): resource = Resource.from_raw_data(raw_content) properties["ipConfiguration"] = resource - return super(PublicIPAddresses, cls).from_raw_data(raw_data) + return super(PublicIPAddresses, cls).process_raw_data(raw_data) class BackendAddressPools(_BaseHNVModel): @@ -1997,7 +2020,7 @@ class BackendAddressPools(_BaseHNVModel): resources that use this backend address pool.""" @classmethod - def from_raw_data(cls, raw_data): + def process_raw_data(cls, raw_data): """Create a new model using raw API response.""" properties = raw_data.get("properties", {}) @@ -2019,7 +2042,7 @@ class BackendAddressPools(_BaseHNVModel): outbound_nat_rules.append(resource) properties["outboundNatRules"] = outbound_nat_rules - return super(BackendAddressPools, cls).from_raw_data(raw_data) + return super(BackendAddressPools, cls).process_raw_data(raw_data) class FrontendIPConfigurations(_BaseHNVModel): @@ -2104,7 +2127,7 @@ class FrontendIPConfigurations(_BaseHNVModel): """ @classmethod - def from_raw_data(cls, raw_data): + def process_raw_data(cls, raw_data): """Create a new model using raw API response.""" properties = raw_data.get("properties", {}) @@ -2131,7 +2154,7 @@ class FrontendIPConfigurations(_BaseHNVModel): resource = Resource.from_raw_data(raw_content) properties["subnet"] = resource - return super(FrontendIPConfigurations, cls).from_raw_data(raw_data) + return super(FrontendIPConfigurations, cls).process_raw_data(raw_data) class InboundNATRules(_BaseHNVModel): @@ -2218,7 +2241,7 @@ class InboundNATRules(_BaseHNVModel): """ @classmethod - def from_raw_data(cls, raw_data): + def process_raw_data(cls, raw_data): """Create a new model using raw API response.""" properties = raw_data.get("properties", {}) @@ -2236,7 +2259,7 @@ class InboundNATRules(_BaseHNVModel): frontend_ip_configurations.append(resource) properties["frontendIPConfigurations"] = frontend_ip_configurations - return super(InboundNATRules, cls).from_raw_data(raw_data) + return super(InboundNATRules, cls).process_raw_data(raw_data) class LoadBalancingRules(_BaseHNVModel): @@ -2359,7 +2382,7 @@ class LoadBalancingRules(_BaseHNVModel): """ @classmethod - def from_raw_data(cls, raw_data): + def process_raw_data(cls, raw_data): """Create a new model using raw API response.""" properties = raw_data.get("properties", {}) @@ -2379,7 +2402,7 @@ class LoadBalancingRules(_BaseHNVModel): resource = Resource.from_raw_data(raw_content) properties["probe"] = resource - return super(LoadBalancingRules, cls).from_raw_data(raw_data) + return super(LoadBalancingRules, cls).process_raw_data(raw_data) class OutboundNATRules(_BaseHNVModel): @@ -2426,7 +2449,7 @@ class OutboundNATRules(_BaseHNVModel): """ @classmethod - def from_raw_data(cls, raw_data): + def process_raw_data(cls, raw_data): """Create a new model using raw API response.""" properties = raw_data.get("properties", {}) @@ -2441,7 +2464,7 @@ class OutboundNATRules(_BaseHNVModel): resource = Resource.from_raw_data(raw_content) properties["backendAddressPool"] = resource - return super(OutboundNATRules, cls).from_raw_data(raw_data) + return super(OutboundNATRules, cls).process_raw_data(raw_data) class Probes(_BaseHNVModel): @@ -2510,7 +2533,7 @@ class Probes(_BaseHNVModel): """ @classmethod - def from_raw_data(cls, raw_data): + def process_raw_data(cls, raw_data): """Create a new model using raw API response.""" properties = raw_data.get("properties", {}) @@ -2520,7 +2543,7 @@ class Probes(_BaseHNVModel): load_balancing_rules.append(resource) properties["loadBalancingRules"] = load_balancing_rules - return super(Probes, cls).from_raw_data(raw_data) + return super(Probes, cls).process_raw_data(raw_data) class LoadBalancers(_BaseHNVModel): @@ -2580,7 +2603,7 @@ class LoadBalancers(_BaseHNVModel): """ @classmethod - def from_raw_data(cls, raw_data): + def process_raw_data(cls, raw_data): properties = raw_data.get("properties", {}) backend_address_pools = [] @@ -2608,8 +2631,8 @@ class LoadBalancers(_BaseHNVModel): outbound_nat_rules = [] for raw_content in properties.get("outboundNatRules", []): raw_content["parentResourceID"] = raw_data["resourceId"] - inbound_nat_rule = OutboundNATRules.from_raw_data(raw_content) - outbound_nat_rules.append(inbound_nat_rule) + outbound_nat_rule = OutboundNATRules.from_raw_data(raw_content) + outbound_nat_rules.append(outbound_nat_rule) properties["outboundNatRules"] = outbound_nat_rules load_balancing_rules = [] @@ -2626,7 +2649,7 @@ class LoadBalancers(_BaseHNVModel): probes.append(probe) properties["probes"] = probes - return super(LoadBalancers, cls).from_raw_data(raw_data) + return super(LoadBalancers, cls).process_raw_data(raw_data) class _BGPPeersStatistics(model.Model): @@ -2783,7 +2806,7 @@ class BGPPeersStatistics(model.Model): """Time stamp when the stats were last updated.""" @classmethod - def from_raw_data(cls, raw_data): + def process_raw_data(cls, raw_data): """Create a new model using raw API response.""" # pylint: disable=redefined-variable-type @@ -2825,7 +2848,7 @@ class BGPPeersStatistics(model.Model): statistics = IPV6Route.from_raw_data(raw_content) raw_data["ipv6Route"] = statistics - return super(BGPPeersStatistics, cls).from_raw_data(raw_data) + return super(BGPPeersStatistics, cls).process_raw_data(raw_data) class BGPPeers(_BaseHNVModel): @@ -2894,7 +2917,7 @@ class BGPPeers(_BaseHNVModel): """This flag is set to `True` for iBGP peers.""" @classmethod - def from_raw_data(cls, raw_data): + def process_raw_data(cls, raw_data): """Create a new model using raw API response.""" properties = raw_data.get("properties", {}) @@ -2903,7 +2926,7 @@ class BGPPeers(_BaseHNVModel): statistics = BGPPeersStatistics.from_raw_data(raw_content) properties["statistics"] = statistics - super(BGPPeers, cls).from_raw_data(raw_data) + return super(BGPPeers, cls).process_raw_data(raw_data) class BGPRouters(_BaseHNVModel): @@ -2957,7 +2980,7 @@ class BGPRouters(_BaseHNVModel): """Collection of BGP peers associated with the BGP Routers resource.""" @classmethod - def from_raw_data(cls, raw_data): + def process_raw_data(cls, raw_data): """Create a new model using raw API response.""" properties = raw_data.get("properties", {}) @@ -2968,7 +2991,7 @@ class BGPRouters(_BaseHNVModel): bgp_peers.append(BGPPeers.from_raw_data(raw_content)) properties["bgpPeers"] = bgp_peers - return super(BGPRouters, cls).from_raw_data(raw_data) + return super(BGPRouters, cls).process_raw_data(raw_data) class LoadBalancerManager(_BaseHNVModel): @@ -3012,7 +3035,7 @@ class LoadBalancerManager(_BaseHNVModel): return cls._get(resource_id, parent_id, grandparent_id) @classmethod - def from_raw_data(cls, raw_data): + def process_raw_data(cls, raw_data): """Create a new model using raw API response.""" properties = raw_data.get("properties", {}) @@ -3022,4 +3045,4 @@ class LoadBalancerManager(_BaseHNVModel): vip_ip_pools.append(resource) properties["vipIpPools"] = vip_ip_pools - return super(LoadBalancerManager, cls).from_raw_data(raw_data) + return super(LoadBalancerManager, cls).process_raw_data(raw_data) diff --git a/hnv/common/utils.py b/hnv/common/utils.py index 1b7860c..ef23040 100644 --- a/hnv/common/utils.py +++ b/hnv/common/utils.py @@ -105,7 +105,7 @@ class _HNVClient(object): return not self._https_allow_insecure def _http_request(self, resource, method=constant.GET, body=None, - if_match=None): + if_match=False): if not resource.startswith("http"): url = requests.compat.urljoin(self._base_url, resource) else: @@ -113,10 +113,10 @@ class _HNVClient(object): headers = self._get_headers() if method in (constant.PUT, constant.PATCH): - if not isinstance(if_match, six.string_types): - if_match = (body or {}).get("etag", None) - if if_match is not None: - headers["If-Match"] = if_match + if if_match: + etag = (body or {}).get("etag", None) + if etag is not None: + headers["If-Match"] = etag attemts = 0 while True: @@ -127,7 +127,8 @@ class _HNVClient(object): timeout=CONFIG.HNV.http_request_timeout ) break - except requests.ConnectionError as exc: + except (requests.ConnectionError, + requests.RequestException) as exc: attemts += 1 self._http_session = None LOG.debug("Request failed: %s", exc) diff --git a/hnv/tests/common/test_utils.py b/hnv/tests/common/test_utils.py index cadd1cd..5ba63b3 100644 --- a/hnv/tests/common/test_utils.py +++ b/hnv/tests/common/test_utils.py @@ -79,7 +79,7 @@ class TestHNVClient(unittest.TestCase): @mock.patch("hnv.common.utils._HNVClient._get_headers") def _test_http_request(self, mock_headers, mock_session, mock_join, mock_dump, mock_sleep, - method, body, response, status_code): + method, body, response, status_code, if_match): output = [] headers = mock_headers.return_value = {} mock_join.return_value = mock.sentinel.url @@ -105,35 +105,38 @@ class TestHNVClient(unittest.TestCase): if isinstance(expected_response, requests.exceptions.SSLError): self.assertRaises(exception.CertificateVerifyFailed, client._http_request, - "/fake/resource", method, body) + "/fake/resource", method, body, if_match) return elif isinstance(expected_response, requests.ConnectionError): self.assertRaises(requests.ConnectionError, client._http_request, - "/fake/resource", method, body) + "/fake/resource", method, body, if_match) return elif status_code == 400: self.assertRaises(exception.ServiceException, client._http_request, - "/fake/resource", method, body) + "/fake/resource", method, body, if_match) elif status_code == 404: self.assertRaises(exception.NotFound, client._http_request, - "/fake/resource", method, body) + "/fake/resource", method, body, if_match) elif status_code != 200: self.assertRaises(requests.HTTPError, client._http_request, - "/fake/resource", method, body) + "/fake/resource", method, body, if_match) else: client_response = client._http_request("/fake/resource", - method, body) + method, body, if_match) mock_join.assert_called_once_with(mock.sentinel.url, "/fake/resource") mock_headers.assert_called_once_with() - if not method == constant.GET: + if not method == constant.GET and if_match: etag = (body or {}).get("etag", None) - self.assertEqual(headers["If-Match"], etag) + if etag is None: + self.assertNotIn("If-Match", headers) + else: + self.assertEqual(headers["If-Match"], etag) if len(response) == 1: session_request.assert_called_once_with( @@ -154,14 +157,16 @@ class TestHNVClient(unittest.TestCase): self._test_http_request(method=constant.GET, body=mock.sentinel.body, response=response, - status_code=200) + status_code=200, + if_match=False) def test_http_request_put(self): response = [mock.MagicMock()] self._test_http_request(method=constant.PUT, body={"etag": mock.sentinel.etag}, response=response, - status_code=200) + status_code=200, + if_match=True) def test_http_request_with_connection_error(self): response = [requests.ConnectionError(), mock.MagicMock()] @@ -169,7 +174,8 @@ class TestHNVClient(unittest.TestCase): self._test_http_request(method=constant.GET, body=mock.sentinel.body, response=response, - status_code=200) + status_code=200, + if_match=False) def test_http_request_connection_error(self): response = [requests.ConnectionError(), requests.ConnectionError()] @@ -177,7 +183,8 @@ class TestHNVClient(unittest.TestCase): self._test_http_request(method=constant.GET, body=mock.sentinel.body, response=response, - status_code=200) + status_code=200, + if_match=False) def test_http_request_ssl_error(self): response = [requests.exceptions.SSLError(), @@ -186,28 +193,32 @@ class TestHNVClient(unittest.TestCase): self._test_http_request(method=constant.GET, body=mock.sentinel.body, response=response, - status_code=200) + status_code=200, + if_match=False) def test_http_request_not_found(self): response = [mock.MagicMock()] self._test_http_request(method=constant.GET, body=mock.sentinel.body, response=response, - status_code=404) + status_code=404, + if_match=False) def test_http_request_bad_request(self): response = [mock.MagicMock()] self._test_http_request(method=constant.GET, body=mock.sentinel.body, response=response, - status_code=400) + status_code=400, + if_match=False) def test_http_request_server_error(self): response = [mock.MagicMock()] self._test_http_request(method=constant.GET, body=mock.sentinel.body, response=response, - status_code=500) + status_code=500, + if_match=False) @mock.patch("hnv.common.utils._HNVClient._http_request") def test_get_resource(self, mock_http_request): diff --git a/hnv/tests/test_client.py b/hnv/tests/test_client.py index 72614c2..8cfdec4 100644 --- a/hnv/tests/test_client.py +++ b/hnv/tests/test_client.py @@ -22,7 +22,6 @@ except ImportError: import mock from hnv import client -from hnv.common import constant from hnv.common import exception from hnv import config as hnv_config from hnv.tests.fake import fake_response @@ -77,15 +76,23 @@ class TestBaseHNVModel(unittest.TestCase): self.assertEqual(resources, [{} for _ in range(10)]) @mock.patch("time.sleep") + @mock.patch("hnv.client._BaseHNVModel._get") @mock.patch("hnv.client._BaseHNVModel._get_client") - def _test_remove(self, mock_get_client, mock_sleep, + def _test_remove(self, mock_get_client, mock_get, mock_sleep, loop_count, timeout): + resource = mock.Mock() + is_ready = resource.is_ready = mock.Mock() + http_client = mock_get_client.return_value = mock.Mock() remove_resource = http_client.remove_resource = mock.Mock() - get_resource = http_client.get_resource = mock.Mock() - side_effect = [None for _ in range(loop_count)] - side_effect.append(exception.NotFound if not timeout else None) - get_resource.side_effect = side_effect + + side_effect = [resource for _ in range(loop_count)] + side_effect.append(exception.NotFound if not timeout else resource) + mock_get.side_effect = side_effect + + side_effect = [False for _ in range(loop_count)] + side_effect.append(True if not timeout else False) + is_ready.side_effect = side_effect request_timeout = CONFIG.HNV.retry_interval * loop_count request_wait = True if loop_count > 0 else False @@ -115,27 +122,29 @@ class TestBaseHNVModel(unittest.TestCase): return {"properties": {"provisioningState": provisioning_state}} @mock.patch("time.sleep") + @mock.patch("hnv.client._BaseHNVModel._reset_model") + @mock.patch("hnv.client._BaseHNVModel.is_ready") + @mock.patch("hnv.client._BaseHNVModel.refresh") @mock.patch("hnv.client._BaseHNVModel.dump") @mock.patch("hnv.client._BaseHNVModel._get_client") - def _test_commit(self, mock_get_client, mock_dump, - mock_sleep, + def _test_commit(self, mock_get_client, mock_dump, mock_refresh, + mock_is_ready, mock_reset_model, mock_sleep, loop_count, timeout, failed, invalid_response): http_client = mock_get_client.return_value = mock.Mock() update_resource = http_client.update_resource = mock.Mock() + update_resource.return_value = mock.sentinel.response mock_dump.return_value = mock.sentinel.request_body - get_resource = http_client.get_resource = mock.Mock() - side_effect = [self._get_provisioning(constant.UPDATING) - for _ in range(loop_count)] + side_effect = [False for _ in range(loop_count)] if timeout: - side_effect.append(self._get_provisioning(constant.UPDATING)) + side_effect.append(False) elif failed: - side_effect.append(self._get_provisioning(constant.FAILED)) + side_effect.append(exception.ServiceException) elif invalid_response: - side_effect.append(self._get_provisioning(None)) + side_effect.append(False) else: - side_effect.append(self._get_provisioning(constant.SUCCEEDED)) - get_resource.side_effect = side_effect + side_effect.append(True) + mock_is_ready.side_effect = side_effect request_timeout = CONFIG.HNV.retry_interval * loop_count request_wait = True if loop_count > 0 else False @@ -158,7 +167,9 @@ class TestBaseHNVModel(unittest.TestCase): if_match=None) if request_wait: - self.assertEqual(get_resource.call_count, loop_count + 1) + self.assertEqual(mock_refresh.call_count, loop_count + 1) + else: + mock_reset_model.assert_called_once_with(mock.sentinel.response) def test_commit(self): self._test_commit(loop_count=0, timeout=False,